IDT Loading 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
Therx

IDT Loading in C

Post by Therx »

In my previous OSes I've always loaded the IDT from assembly and routed all the ints through one global handler which sorted them out but this time I'd like to use the IDT through C and my code doesn't work. I think I've loaded my IDT right because the code doesn't reboot when I leave my IRQ0 handler blank. I know you have to push everything and then pop it and my old assembly code did this fine but whenever I try and transfer it into inline it doesn't work. I think this is down to my lack of experience with AT&T. With the -masm=intel option described in another post I could leave the operands the "right" way round and leave off the % on the registers couldn't I. I'll try that now. Any other ideas or example code?

Thanks

Pete
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:IDT Loading in C

Post by Pype.Clicker »

to be honest, i never dared to move my IDT setup code to C because of the kind of reasons you're evoking.

Having inline assembly for ISR prolog & epilog is not (imho) a good idea at all, because you cannot prevent the compiler to add its *own* prolog/epilog and you cannot (afaik) control what's put in it...

this means if you do something like

Code: Select all

isr_timer() {
     asm("pushad;push %%ds; push %%es");
     kprint("*clock*\n");
     outb(0x20,0x20);
     asm("pop %%es; pop %%ds; popad");
     asm("iretd");
}
the compiler may be issuing

Code: Select all

isr_timer:
     push ebp
     mov ebp,esp
     pushad
     ....
     popad
     iretd
     mov esp,ebp
     pop ebp
     ret
which is obviously wrong :-p

note that according to "info gcc, optimize options", you could do
-fomit-frame-pointer'
Don't keep the frame pointer in a register for functions that
don't need one. This avoids the instructions to save, set up and
restore frame pointers; it also makes an extra register available
in many functions. *It also makes debugging impossible on some
machines.*
and hope it will solve your problem. Your ISR may not have any argument or local variable if you want that trick to work (imho -- never tried) and it sounds *very* hackish to my limited senses ... but if you really want to give it a try ...
Therx

Re:IDT Loading in C

Post by Therx »

The reason I've switched is that I need to have the task scheduler as the real ISR. Before I had a NASM macro which I used to make all the stubs which did all the pushing, poping,etc and then pushed the INT number onto the stack and called a generic C function int_hand(int intno);. But now with the Page Fault Handler, Task Scheduler etc. I need to go direct.
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:IDT Loading in C

Post by Pype.Clicker »

why so ?? the "page fault" can be processed like any other interrupt (i do it) and the task switching (even software stack-switch) can be handled by a "stack_switc()" function called from the C-based ISR handler rather than relying on some dark magic performed by the stub (like expecting the handler to return the new ESP value or something like this ...)
Therx

Re:IDT Loading in C

Post by Therx »

The way I want to do task switching is quicker because it doesn't store everything. Just the ESP. On entering the ISR it will push everything to the stack and then store the ESP value. Then it will restore the ESP value for a different task and pop everything off the stack.

For more info read my OS Plans thread.

Pete
Therx

Re:IDT Loading in C

Post by Therx »

Ok I've transfered it back to assembly but as I don't want them all going through the same function (3 different handlers - exceptions, irqs and scheduler) I've had to change it a bit. And it doesn't work yet doesn't crash. I think I've got the entries a bit out of place by one but I'm not sure. I have attached the assembly file (NASM). Please could someone check my numbers. AFAIK there are 32 exceptions 0->31, 16 IRQs which I want mapped straight after the exceptions 32->48, but the task switcher takes IRQ0 (32). All numbers in decimal

Any help would be much appreciated.

Thanks

Pete

[attachment deleted by admin]
nullify

Re:IDT Loading in C

Post by nullify »

You can use a macro to automatically set up the stub and wrap your C handler.

Code: Select all

/* eg. for a non-errorcode exception handler */
#define END_EXC(func) \
   void excstub_##func(void); \
   asm(".text\n" \
      ".globl excstub_" #func "\n" \
      "excstub_" #func ":\n" \
      "   pusha\n" \
      "   call " #func "\n" \
      "   popa\n" \
      "   iret")

/* then when define your ISR... */

void exception0(void)
{
    kprintf("Divide by zero.");
} END_EXC(exception0);

/* when you set the IDT entry, every handler's stub name is prefixed by 'excstub_' */

set_idt_entry(0, excstub_exception0);
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:IDT Loading in C

Post by Candy »

To be very honest, as far as I have seen (GCC 2.95.3 and 3.1/3.2) they all use push ebp; mov ebp, esp ....... leave; ret to start/leave a function. If you could replace the leave/ret with a leave/iret you would be all set. Because dead code is no real concern, just add the leave/iret before the leave/ret.

In result, before compilation:

Code: Select all

int bla() {
    // something
    i++;
    asm ("leave; iret");
}
and after compilation:

Code: Select all

bla:
  push %ebp
  mov %esp, %ebp
  ; do the i++ thing

  leave
  iret

  leave
  ret
which, at least in my case, has worked each time I tried it.
Therx

Re:IDT Loading in C

Post by Therx »

Ok it was no bug with the IDT but with my test code.

Why doesn't:-

Code: Select all

while(1)
   *vidmem++;
work for making the top left character rotate, when

Code: Select all

char temp;
while(1){
   temp++;
   *vidmem = temp;
}
works perfectly?

Pete
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:IDT Loading in C

Post by Candy »

try using (*vidmem)++. The ++ operator has precedence over the * operator
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:IDT Loading in C

Post by Solar »

...that's why you should always use parantheses in compound statements, even if you (think you) are sure about operator precedence. Helps with reading, too. ;-)
Every good solution is obvious once you've found it.
Post Reply