OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 10:09 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Timer interrupts don't work under qemu (work under Vmware)
PostPosted: Sat Aug 11, 2018 10:49 am 
Offline

Joined: Tue Jun 12, 2018 8:57 am
Posts: 3
I started writing kernel on top of code provided in Bare Bones tutorial.
First thing I wanted to implement is timer interrupt handling.

So I implemented GDT and IDT initialization, implemented functionality for setting up interrupts handlers in C code.
The problem is timer interrupts fire and work as expected in VMware Workstation, they are not firing when testing on QEMU or VirtualBox.
I spent week trying to figure out why this is happening, no success so far.
Honestly I do not know what I am doing wrong, I dont think the QEMU or VirtualBox are buggy.
I will post images and explanation how I implemented GDT and IDT initialization( Could this be a problem).


Here are images:
VMware:
Image
QEMU:
Image
VirtualBox:
Image

Link to repo: https://github.com/bojan96/kernel

As I wrote earlier I started making kernel with code provided in Bare Bones tutorial.
In src directory there is assembly code and C code.

boot.asm is modified boot.s from Bare Bones tutorial.
When _start function is called( i.e. when GRUB boots the kernel), I disable all interrupts, set up stack and call procedure gdt_init which performs GDT initialization which is defined in same file.

In .data section I define 3 descriptors null, code and data.
gdt_init copies address of null descriptor(table start address), and GDT_SIZE(23, this is last byte in table) to memory location gdt_reg,
from there I load GDTR.
After that I load all data segment registers with DATA_SELECTOR (0x10), and perform far jump to label inside this procedure in order to initialize CS register.

After that remap_irq procedure is called, this procedure is defined in irq.asm.
This procedure remaps PIC, 0-15 PIC interrupts are mapped to 32-48 entries in IDT.

The code:
Code:
OUT 0x21, 0xfe
OUT 0xa1, 0xff

masks all hardware interrupts except timer interrupt.
Next initialization procedure is init_idt.
I reserve memory in data segment for IDT(idt label).

The line:
Code:
idt times 2048 db 0

initializes 2048 bytes(max 256 entries, each entry has size of 8 bytes) with 0.

I defined three macros for populating IDT.

- IDT_ENTRY_SETUP - This macro intializes one entry with isr_handler_<number> (isr_handler_<number> are global labels defined in isr.asm. Those handlers call C function with argument that corresponds to IDT index. We use that code to print message that corresponds to fault/trap which caused the interrupt.(e.g. 0 corresponds to Divide by zero exception).

- IDT_ENTRY_SETUP_ERR - So far I did not care about these interrupts, this macro initializes entry handler with interrupt_error(this handler just pops error code and returns).

- IDT_IRQ_ENTRY_SETUP - this one initializes entry handler with irq_handler_<number>(<number> corresponds to IRQ index, e.g. irq_handler_0 is handler for timer interrupt). Those handlers are defined in irq.asm via macro. Those handlers just invoke common asm procedure which saves all general purpose registers, and invoke common C function(irq_common_high_level) defined in irq_high_level.c.
After returning, we check which IRQ invoked handler, and based on that we send EOI either to master or both master and slave.

Now it is time to initialize IDT register.
I initialize memory location(idt_reg) with IDT_SIZE(index of last byte in table) and address of table(idt label).
From that memory location I load IDTR.
After that kernel_main function(defined in kernel.c) is called which initializes terminal and registers timer handler( which prints "Timer Handler").
Interrupts are enabled with function "enableInterrupts"(sti instruction).

Also I invoke handlers manually to test interrupt return.
Code:
__asm__ volatile("int 0\n\t":::); // "Division by zero"
__asm__ volatile("int 1\n\t":::); // "Debug"
__asm__ volatile("int 2\n\t":::); // "Non Maskable Interrupt"
__asm__ volatile("int 3\n\t":::); // "Breakpoint"


Also on QEMU for unknown reasons the extra "Division by zero" is printed. Neither do I perform division nor I invoke it manually.
( I noticed this happening every time I enable interrupts with sti instruction).

Question:
Did I miss something during initialization, is it possible that VB and QEMU have buggy PIC implemenations.


Top
 Profile  
 
 Post subject: Re: Timer interrupts don't work under qemu (work under Vmwar
PostPosted: Sat Aug 11, 2018 4:34 pm 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
in IRQ.ASM you have this:
Code:
    mov ax, %2
    out %1, ax
out %1, ax will use the OUTW instruction to write a WORD to the port since you use the AX register. The ports in question require OUTB. This causes the remapping of IRQs to not work and thus your interrupts don't fire as expected. Change to:
Code:
mov al, %2
out %1, al


Top
 Profile  
 
 Post subject: Re: Timer interrupts don't work under qemu (work under Vmwar
PostPosted: Mon Aug 13, 2018 11:09 am 
Offline

Joined: Tue Jun 12, 2018 8:57 am
Posts: 3
MichaelPetch wrote:
in IRQ.ASM you have this:
Code:
    mov ax, %2
    out %1, ax
out %1, ax will use the OUTW instruction to write a WORD to the port since you use the AX register. The ports in question require OUTB. This causes the remapping of IRQs to not work and thus your interrupts don't fire as expected. Change to:
Code:
mov al, %2
out %1, al


I had checked this code dozen of times, never find these two lines suspicious, I thought I missed something on larger scale.
I am kinda embarrassed now, but then again thank you for having time to check this.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot], Sa41848, SemrushBot [Bot] and 75 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group