IDT in C

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
xleelz
Posts: 8
Joined: Mon Aug 01, 2011 7:59 pm

IDT in C

Post by xleelz »

I've recently decided to code my kernel in C instead of assembly and I ran across a problem when I tried to install the IDT.

Code: Select all

#include "./kernel/idt.h"
#include "./kernel/datastruc.h"
#include "./kernel/io.h"
#include "./kernel/pic.h"

void int50(void);

void kmain()
{
	ints(false);
	maskIrq(ALL);

	void (*int50ptr)(void);
	int50ptr = int50;
	addisr(0x50,int50ptr,0);
	setIDT();
	
	
	unsigned char *vidmem = (unsigned char *) 0xB8000;
	for(int i=0;i<=160*25;i+=2)
	{
		vidmem[i]=' ';
		vidmem[i+1]=0x1f;
	}
	ints(true);
	__asm__ volatile("int $0x50");   //<---The problem is calling it.  In the Virtual Box debugger it shows that int 50 is installed, but it freezes when it's called.
	vidmem[0] = 'A';	
	vidmem[1] = 0x1f;
	__asm__ volatile ("cli;hlt");
}

void int50(void)
{
	__asm__ __volatile__("pusha;push %es;push %ds; push %fs; push %gs");
	unsigned char *vidmem = (unsigned char *) 0xB8E00;
	vidmem[0] = 'U';
	__asm__ __volatile__("pop %gs; pop %fs; pop %ds; pop %es; popa; iret;");
}
I'm not exactly sure what I'm doing wrong, seeing as how I've done most of my kernel in asm before. Any advice?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IDT in C

Post by Combuster »

C functions can't be interrupt entry points. For example:

Code: Select all

__asm__ __volatile__("pusha;push %es;push %ds; push %fs; push %gs");
will be executed when it's already too late. (Besides the fact that it completely messes up your stack.)


You need assembly for those things.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
xleelz
Posts: 8
Joined: Mon Aug 01, 2011 7:59 pm

Re: IDT in C

Post by xleelz »

Ok... maybe I'm not so good at C but my solution (had a similar problem but didn't freeze, just ran into random memory):

isrs.asm:

Code: Select all

[extern int50]
[global int50ptr]

int50ptr:
	pushad
	push es
	push ds
	call int50
	pop ds
	pop es
	popad
	iret
kernel (again):

Code: Select all

#include "./kernel/idt.h"
#include "./kernel/datastruc.h"
#include "./kernel/io.h"
#include "./kernel/pic.h"


extern void int50ptr(void);
void int50(void);

void kmain()
{
	ints(false);
	maskIrq(ALL);
	addisr(0x50,int50ptr,0);
	setIDT();
	
	
	unsigned char *vidmem = (unsigned char *) 0xB8000;
	for(int i=0;i<=160*25;i+=2)
	{
		vidmem[i]=' ';
		vidmem[i+1]=0x1f;
	}
	ints(true);
	__asm__ volatile("int $0x50");
	vidmem[0] = 'A';	
	vidmem[1] = 0x1f;
	__asm__ volatile ("cli;hlt");
}

void int50(void)
{
	unsigned char *vidmem = (unsigned char *) 0xB8E00;
	vidmem[0] = 'U';
}
There is something I'm really not getting here. Any other advise?
A detailed explanation would be preferable.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: IDT in C

Post by gerryg400 »

A detailed explanation would be preferable.
A detailed description of the problem would be required. That will require some debugging on your part.

Is your linker resolving references between the 2 files ?
You call some external functions, have you unit tested each of them ?
Have you printed out your IDT ? Was it correct ?
Does the int vector correctly ?
Does it make it to the assembler stub ?
Does it get to the C code ?
Does it ret ?
Does it iret ?
What is the last good instruction that runs ?

By the time you answer these questions you will likely have found and fixed the bug.
If a trainstation is where trains stop, what is a workstation ?
User avatar
Jvac
Member
Member
Posts: 58
Joined: Fri Mar 11, 2011 9:51 pm
Location: Bronx, NY

Re: IDT in C

Post by Jvac »

A detailed description of the problem would be required. That will require some debugging on your part.
Agree!

Real mode or protected mode?

See the Wiki
Interrupt descriptor table
See this tutorial
"The best way to prepare for programming is to write programs, and
to study great programs that other people have written." - Bill Gates


Think beyond Windows ReactOS®
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: IDT in C

Post by Chandra »

xleelz wrote:There is something I'm really not getting here. Any other advise?

Code: Select all

void int50(void)
{
   unsigned char *vidmem = (unsigned char *) 0xB8E00;
   vidmem[0] = 'U';
// Put a 'freeze' statement here and see if 'U' is actually printed out
// Besides, gerryg400 gave you some important tips
}
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IDT in C

Post by Combuster »

You could use attribute(naked) in gcc, but it's not available on all architectures.
Nor is it a proper fix for like, anything.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
rdos
Member
Member
Posts: 3308
Joined: Wed Oct 01, 2008 1:55 pm

Re: IDT in C

Post by rdos »

berkus wrote:True, an interrupt stub in assembly is the best approach.

Edit: or should I say "thunk" instead. Or "trampoline"?
The stub should be present in the PIC/APIC module already, since it also needs to send EOI to the controller, and methods of doing that differs between PIC/APIC. When linking a new interrupt, it is best to supply an IRQ # and callback address to a registering function. When an interrupt happens, either in the PIC or APIC module, the assembly handler would save registers and call the previous callback function (which could be in C/C++). As the callback returns, registers should be restored and an EOI should be sent before doing an iret.
Post Reply