system reboots when executing an int inside the before creat

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.
Freanan(who cannot login)

system reboots when executing an int inside the before creat

Post by Freanan(who cannot login) »

just tried to build an idt, loadt it with lidt,
insert an interrupt, and call this interrupt with int n.
My system reboots at the point of the int-instruction.
(i tried it out with the int outcommented and it did not reboot then, so it must be the int).
So either my idt is completely false or i do something wrong installing the interrupt vector.
But i cannot imagine where there can be a bug, for i use pretty much the same code as several other kernels i found on the web...
Please help me with that - thank you.

Here is my kmain(stripped off the text-output to keep it short):

Code: Select all

void kmain()
{
 initIDT(); //setup an idt
 setinteruptvector(9,kbhandler,0x08,0xEE00);//install an interupt vector -later it will be the keyboard handler
 asm("int $9");//call the interupt
 while(true);//hang
};

//This is my struct for idt entries:
typedef struct interrupt_vector
{
 word handleroffset_l;
 word segmentselector;
 word properties;
 word handleroffset_h;
}intvect;
This is the stuff that does the work:

Code: Select all

intvect* idt;     //Interupt Descriptor Table (global)

inline void initIDT()
{
  unsigned long idtinfo[2]; //this is the info i am going to load into idtr
  int i;
  for(i=0; i<256; i++)setinteruptvector(i,emptyint,0x08,0xEE00);//fill idt with empty ints
  asm("pushfl");//disable ints while loading idt
  idtinfo[0]=(256*(sizeof(intvect)-1))<<16; //size of idt 
  //(i also tried it without '<<16', because some sources do it and others not 
  // i also wonder why one should do that '<<16')
  idtinfo[1]=(unsigned long)idt;            //idt adress
  __asm__ __volatile__ ("lidt (%0)": :"p" (((char *) idtinfo)+2));//load the idt-info stuff
  asm("popfl"); //re-enable ints
};

void setinteruptvector(int tableindex, void *hoffset, word selector, word properties)
//I also tried void(*hoffset)() instead of void* hoffset 
//(and when calling: &kbhandler instead of kbhandler) 
//i have seen both and i think in the end it does the same...(?)
{
  idt[tableindex].segmentselector=selector;
  idt[tableindex].properties=properties;
  idt[tableindex].handleroffset_l=(unsigned short)(((unsigned long)hoffset) & 0xFFFF);
  idt[tableindex].handleroffset_h=(unsigned short)(((unsigned long)hoffset) >>16);
};
And the two interrupt handlers:

Code: Select all

void kbhandler()
{
  //asm ("cli \n");
  kprint("Keyboard input or Coprocessor Overrun Exception!",7);
  while(true);
  //asm("sti \n" "iret \n");
};

void emptyint()
{
 //asm ("cli \n");
 kprint("Empty Interupt!",7);
 while(true);
 //asm("sti \n" "iret \n");
};
//I also tried it with the asm statements not outcommented and the while(true);
//outcommented - same result
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

sorry for the messed up quotes-stuff - but i had to write on another pc and could not login, so i cannot format my text properly :(
i hope this does not keep anybody from helping me :)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

first of all, you should know that INT 9 isn't free for keyboard in protected mode. Actually, it is reserved for some exception (x87 overflow)... So you'll eventually have to re-map your hardware interrupts using the PIC (8259a) chip -- see Bona Fide OS Dev tutorials for more info.

second, it's a pretty bad idea to have your "idtinfo" structure as a function-local variable. Local variables are allocated on the stack and their content will be destroyed with the next function call. This means that the processor may find garbage when it'll try to access the IDT (though some processor might cache the content ad thus work anyway)

As for the "<<16", its reason is that the real structure of the IDTR memory location is

Code: Select all

0     16     32     48
+-----+-----+-----+
|limit| base       |
+-----+-----+-----+
the "<<16" actually shifts the limit to the highest half-word of idt_info[0], and thus the 6 bytes starting at ((char*)idt_info) are your IDTR location.
It's kind of a workaround to bypass any kind of field-alignment the compiler could try to use...

do *not* use "asm sti" before you do the "iret". "iret" is in charge of restoring the IF flag itself. all it could do is bugging.
Also, as the compiled code actually adds stack-manipulations like "push ebp; mov ebp, esp" at the function start, having "asm iret" in a C function is usually a bad idea...

Finally, you should load GPF exception handler with a valid descriptor so that you get a "Segmentation fault" message if your IDT misbehaves rather than having the CPU rebooting.

Last but not least, debugging your kernel with BOCHS may save time, as it will gives you more comprehensive error messages that what your PC can do before interrupts are working ;)
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

Thank you Pype.Clicker!
I just put idtinfo before the initIDT function to make it a global variable and
changed the stuff inside the interrupts
kprint('something',7) and an endless loop afterwards.
I also filled thw whole idt with standard-handlers that put out text, to have output instead of rebooting, as you suggested.
There is just one problem:
ld does not find my idtinfo variable and says 'undefined reference to _idtinfo'! :(
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

did you include the "BSS" section in your linker script ? as idtinfo is now an uninitialized global variable, that's where it should be...
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

I do not use any linker script.
Perhaps i should do that :-[!
Is there a good manual how to use them online?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

i'm not sure, but i think there's none easily googlable. Solar collected all sort of infos about it here, though.
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

I just decided to setup idt in assembler.
So there can't be any errors because of messed up linking.
At the moment i just have a kernelfile in assembler, but later i think i'll make an asm-start-routine which sets everything up and calls the c-main-function...
But i still have the same error - when calling an int (i just used int 0x02...) the pc reboots.
So it must be something about my code :'(
Here is my new code:

Code: Select all

[BITS 32]

;main-program
mov byte [0xB8000], "K"   ;debug-textoutput
mov byte [0xB8001],  4
lidt [idt_pointer]                ;load idtr
mov byte [0xB8002], "!"    ;more textoutput
mov byte [0xB8003],  4

int 0x02                             ;calling an int

hang:
jmp hang


;interrupt descriptor table
idt:
%rep 0xF    ;repeat 16 times the following desc
dw handler ;the adress of the isr 
dw 0x08     ;codesegment-selector
db 0xEE      ;11101110=EE
db 0            ;empty byte
dw 0           ; that would be the end of the adress
%endrep
idt_end:

;idt data to load into idtr
idt_pointer:
dw idt_end-idt-1 ;size
dd idt                  ;adress

;standard-isr to test the idt
handler:
mov byte [0xB8002], "I" ;Output 
mov byte [0xB8003],  4
hng jmp hng                   ;and hang
The descriptor i used here i found in some educational kernel about idt-loading. But i think it is strange, that here
only 'handler' and '0' are used as the two parts of the adress, because in all the kernels in c i saw, the adress was shifted to get the first word of the adress...

Please tell me what i did wrong again!
Thank you!
Therx

Re:system reboots when executing an int inside the before cr

Post by Therx »

The only possible bug I can see is that depending where the kernel is loaded I doubt that the address of handler is 16bit so you'll have to use the second double word at the end.

If you want to look at my code (in colour ;D) it's here

Hope this helps

Pete
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

Thank you pete for the link, i'll look if it helps me!

I just realised that there are some errors in my code:
the ':' at 'hng: jmp hng' is missing and it has to be
...
db 0
db 0xEE...
not the other way round...
I also changed the dpl to 0.
But fixing these two errors did not change anything...
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

hmm ... i'm surprised you assembled this without complaints from nasm (which shouldn't like a 32-bits offset "handler" to be stored in a 16-bits place). Chances are that your IDT get screwed up in the building process. Check the hexdump of your kernel to be sure everything is okay ...
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

That sounds logic...
Is there any possibility to be sure, that it is not messed up?
I tried to do the &-ing and shifting as in all the c-kernels - the operators were also described in the nasm-manual. But then nasm complained that "& and shift operators are only to be used with scalars".
Or i have to tell the assembler that it is supposed to be a word as in 'mov word ...'?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

as i can't remember if base_me and base_hi are close to each other in IDT descriptors - i know they aren't in segment descriptors.

Code: Select all

mov edi, idt_start
.loop:
mov eax,default_irq_handler ;; this could be relocated by the linker if needed
mov [edi+.descriptor_base_lo],ax
shr eax,16
mov [edi+.descriptor_base_me],al
mov [edi+.descriptor_base_hi],ah
add edi,8
cmp edi,idt_end
jb .loop
Freanan

Re:system reboots when executing an int inside the before cr

Post by Freanan »

Following your advise, Pype.Clicker, i looked at my binary with a hexeditor.
Being a complete hobbyist i never learned how to use that thing, but i think it helped me:
I found 8 bytes that were repeated 16 times, so this must be my descriptor:
...A8 00 08 00 00 8E 00 00...
I copied it into this forum-post and put together two bytes were there should be words...:
A800 -my handler adress
0800 -the 0x08, my codesegmentselector
00 -the 0-byte
8E -the flags
0000 -the other part of the handler
So this seems NOT to be messed up, at least if the A800 really is my handleradress...
The start adress of my handler should be 6 bytes (because of the 'idt_pointer')
after the last descriptor. And this location has, according to my editor
indeed the adress A8. So this should be allright.
Or did i get something wrong?
I might also post the whole output of the editor if it helps you helping me..
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:system reboots when executing an int inside the before cr

Post by Pype.Clicker »

at which address do your binary get loaded ?
Post Reply