Page 1 of 1

Getting odd interrupt code from ISR

Posted: Mon Feb 20, 2023 3:48 pm
by adoreyourpain
Hello, I have been following along Bran's Kernel development and James Molloy's OS development guide, nearly to a T, with my boot code being the only exception. I have successfully loaded the GDT and IDT, and created a few ISRs. Everything seems to work perfectly, up until I try to test it out. He writes in his kernel main

Code: Select all

asm volatile ("int $0x3");
asm volatile ("int $0x4"); 
His output is 0x03, where the output I am getting is 0x102840. I have followed his code for printing decimal and hex, so it would seem to me that I would get the same output. Is what I am getting normal? Is it because I'm on QEMU and he is using BOCHS? Any insight would be greatly appreciated, thanks!

My kernel code

Code: Select all

#include "utils/system.h"
#include "utils/print.h"
#include "cpu/gdt.h"
#include "cpu/idt.h"

void kernel_main()
{
    init_video();
    
	init_gdt();
	init_idt();
	
	/* Test our interrupt handlers */
	asm volatile ("int $0x3");
	asm volatile ("int $0x4");

    puts("Hello World");

    for (;;);
}

Code for printing decimal

Code: Select all

void putn(uint32_t n)
{
    if (n == 0)
    {
        putch('0');
        return;
    }

    int32_t acc = n;
    char c[32];
    int i = 0;
    while (acc > 0)
    {
        c[i] = '0' + acc%10;
        acc /= 10;
        i++;
    }
    c[i] = 0;

    char c2[32];
    c2[i--] = 0;
    int j = 0;
    while(i >= 0)
    {
        c2[i--] = c[j++];
    }
    puts(c2);
}
ISR Registers code

Code: Select all

typedef struct
{
	uint32_t ds;
	uint32_t edi, esi, esp, ebx, edx, ecx, eax;
	uint32_t int_num, err_code;
	uint32_t eip, cs, eflags, useresp, ss;
} __attribute__((packed)) registers_t;

void isr_handler(registers_t regs);
The code that actually prints the interrupt number

Code: Select all

void isr_handler(registers_t regs)
{
	puts("Recieved interrupt: ");
	puth(regs.int_num);
	putch('\n');
}

Re: Getting odd interrupt code from ISR

Posted: Sat Mar 04, 2023 3:49 pm
by Octocontrabass
adoreyourpain wrote:I have been following along Bran's Kernel development and James Molloy's OS development guide, nearly to a T
That might be the problem. Take a look at the list of known bugs in Bran's tutorial and in James Molloy's tutorial.
adoreyourpain wrote:The rest of my source code is here https://github.com/tehtko/Oryx/tree/master/src/arch/x86
No it's not?

Re: Getting odd interrupt code from ISR

Posted: Sun Mar 05, 2023 8:13 am
by MichaelPetch
Octco's observation that your code base doesn't appear in Github is what I am seeing. Have you made it private?
Octo also mentioned a list of well known bugs. The primary one related to ISRs and IRQs is the passing of `registers_t` by value rather than by reference/pointer (`registers_t *`). I have more information on that particular bug in this Stackoverflow answer and how to fix it.

The other problem may be that you have changed how James Molloy's code sets up the stack prior to calling the IRQ handler in C. If the stack isn't set up properly for use with the `registers_t` structure you may end up referencing the interrupt number by reading the wrong memory location. In your case the value being printed almost looks like an address that may suggest you loaded your kernel at 0x100000? The James Molloy code for the interrupt stubs (with the aforementioned bug can be found here.

In the James Molloy code the IRQ/ISR_NOERRCODE/ISR_ERRCODE macros set up the stack in a particular way ensuring there is an interrupt number and an error code properly placed. In `isr_common_stub` and `irq_common_stub` the rest of the registers are pushed in a certain order that match the `registers_t` structure. If you don't set up the stack the same way before calling over to the ISR/IRQ handlers (in C) then you will likely not read the interrupt number properly, but rather something else on the stack. I have seen people modify how the stack is set up in the assembly stub code and then they get garbage when trying to read the interrupt number.