Page 1 of 1

Problems with Interrupts and call gates

Posted: Mon Jun 21, 2004 6:52 am
by ManOfSteel
Hello,
the file I attached to the message (os.zip) is a simplified version of my OS. It contains five files:
[*] 1.44 (the image file) which is a binary file that you can run under Bochs or write to the first sectors of the first floppy drive,
[*] Make.bat which is the batch file I use to compile the source, [*]boot.txt which is (as you probably guessed) the boot loader,
[*]init.txt which is the second stage and kernel.txt the kernel.

In the second stage, I setup the GDT and the IDT, do the PM stuff, then load the kernel.
When the kernel is loaded, it crashes. I'm trying to use a call gate and an interrupt but both are not working. Maybe I misunderstood or forgot something concerning PM.
Thanks for any help.

Re:Problems with Interrupts and call gates

Posted: Mon Jun 21, 2004 7:48 am
by Pype.Clicker
ever considered naming your sources files ".asm" instead of ".txt" ?

Your GDT setting seems correct ...

Code: Select all

[gdtdescr].limit := GDTend - GDT
[gdtdescr].base := ds*16 + GDT
I'm more concerned by taht 'int13h' code, which will fail to catch any errors ...

Code: Select all

mov ax,900h
    mov es,ax
    xor bx,bx
    mov ah,2
    mov al,3
    xor ch,ch
    mov cl,4
    xor dx,dx
    int 13h
having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.

i'd have had

Code: Select all

    mov cr0, eax
    jmp 0x08:.here
.here:
    mov eax, 0x10
    mov ds, eax
    ...
if i were you ...

you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.

Re:Problems with Interrupts and call gates

Posted: Mon Jun 21, 2004 8:24 am
by Brendan
Hi,
ManOfSteel wrote: When the kernel is loaded, it crashes. I'm trying to use a call gate and an interrupt but both are not working. Maybe I misunderstood or forgot something concerning PM.
The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.

The offset for all of your IDT entries is also wrong. You use a 16 bit offset for them but you are also using a 32 bit code segment (which will need a 32 bit offset). In addition you are trying to use the 32 bit code segment to run 16 bit code.

As a side note, things like:
db 0eah
dw 9000h
dw 8h

Are normally written as:
jmp 8h:9000h

NASM is actually quite useful like that - you can even get it to generate a 32 bit far jump in a 16 bit segment:

jmp dword 8h:12345678h


Cheers,

Brendan

Re:Problems with Interrupts and call gates

Posted: Tue Jun 22, 2004 7:50 am
by ManOfSteel
Hello,

Pype.Clicker,
ever considered naming your sources files ".asm" instead of ".txt" ?
Since I program under Window$ and open my source code directly with notepad, I didn't bother creating a new file type entry for *.asm files.
I'm more concerned by taht 'int13h' code, which will fail to catch any errors ...
I will keep these as they are for now, after all everything is working even at the kernel level when I try to print a letter directly to VGA memory.
having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.

i'd have had

Code: Select all

    mov cr0, eax
    jmp 0x08:.here
.here:
    mov eax, 0x10
    mov ds, eax
    ...
if i were you ...
I've already tried that before but it was causing triple faults, that's why I made it three stages and now it's working fine with a jump to "8h:9000h" at the end of init.txt.
you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
How is that done?


Brendan,
The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.
That's why I use the following code before loading the GDT (with lgdt)

Code: Select all

    mov ebx,cg1                    ;calculate call gate offset
    mov [CallGate01],bx
    shr ebx,16
    mov [CallGate01+6],bx
Isn't that supposed to "divide" the 32bits offset address of the call gate into two 16bits offset adresses? (call gates need two 16bits addresses)
As a side note, things like:
db 0eah
dw 9000h
dw 8h

Are normally written as:
jmp 8h:9000h
TASM programming after-effects. :)
The offset for all of your IDT entries is also wrong. You use a 16 bit offset for them but you are also using a 32 bit code segment (which will need a 32 bit offset). In addition you are trying to use the 32 bit code segment to run 16 bit code.
Can you please show me an excerpt of your IDT, I will understand it better.


Thanks for your help.

Re:Problems with Interrupts and call gates

Posted: Tue Jun 22, 2004 8:07 am
by Pype.Clicker
ManOfSteel wrote: Hello,
having so much instructions after 'mov cr0,eax' and before setting up a valid CS selector also concerns me.

i'd have had

Code: Select all

    mov cr0, eax
    jmp 0x08:.here
.here:
    mov eax, 0x10
    mov ds, eax
    ...
if i were you ...
I've already tried that before but it was causing triple faults, that's why I made it three stages and now it's working fine with a jump to "8h:9000h" at the end of init.txt.
the problem was probably due to the fact than, since .here, you need to tell the assembler to produce *32 bits* code rather than *16 bits*, still if it works with late-jumping. Fine. Clean. easy to understand ...
you also know all these 'calculations' of addresses may be performed at compile time since the load address (0x1000) for init.txt is well-known.
How is that done?
Let's say, for instance you have your init.txt loaded at 0x1000:0x0000. and assembled with [ORG 0] (that is, the code file is loaded at the start of a 16-bits segment).

Now let's say you have symbol GDT that you wish to place in GDTR.base, all you have to write is

Code: Select all

gdtr: 
    dw gdtend - gdt - 1
    dd  gdt + 0x1000 * 16

Re:Problems with Interrupts and call gates

Posted: Wed Jun 23, 2004 2:19 am
by Brendan
Hi,
ManOfSteel wrote:
The offset in your call gate's GDT entry is 0x0000000, which is why your call gate crashes. You need to set it to an address in some 32 bit code.
That's why I use the following code before loading the GDT (with lgdt)
Sorry, I missed that. Your call gate has the same problem as your interrupt gates - the wrong offset and using 16 bit code with a 32 bit code segment.

I assume that eventually your 32 bit kernel will contain the interrupt handling code, and that the call gate will be used for the kernel API (which would also be in the kernel binary). Rather than fixing the current problems you may want to shift this code into the kernel now...
ManOfSteel wrote: Can you please show me an excerpt of your IDT, I will understand it better.
Not really - my kernel contains 3 seperate lists of offsets to use for IDT entries. The boot code uses these lists to dynamically create the IDT. The first list is for exception handlers and is always used. The second list is for IRQs and is only used if the PIC chips are used. The third list is also for IRQs but is only used if IO APIC/s are used instead of the PIC chips. My boot code detects if IO APIC/s will be used or not and builds the IDT accordingly.


Cheers,

Brendan

Re:Problems with Interrupts and call gates

Posted: Wed Jun 30, 2004 1:46 am
by ManOfSteel
Hello,
sorry I couldn't reply before because I had no more Internet.

Anyway, ...
Rather than fixing the current problems you may want to shift this code into the kernel now...
Ok, so you're saying I have to move my GDT, my IDT and maybe all my PM stuff to the kernel making my OS two staged instead of three staged. If that's the case, than I already tried that but it was causing me a lot of trouble and that's why I decided to make it three staged.

I tried to make a one staged "OS" and everything went OK (the call gate, the interrupt, ...).
But now I'm trying to make it (the one staged "OS") a two staged OS and it won't work. It is causing triple faults even before I use the call gate or interrupt (actually when I'm setting up PM). It is printing 'test' to the screen than when I press any key it crashes BOCHS.

Please help me find the error.
Thanks.

Re:Problems with Interrupts and call gates

Posted: Wed Jun 30, 2004 2:38 am
by Brendan
Hi,
ManOfSteel wrote: I tried to make a one staged "OS" and everything went OK (the call gate, the interrupt, ...).
But now I'm trying to make it (the one staged "OS") a two staged OS and it won't work. It is causing triple faults even before I use the call gate or interrupt (actually when I'm setting up PM). It is printing 'test' to the screen than when I press any key it crashes BOCHS.
The problems with your 2 stage code are all the same mistake - you forget that the code is running at 0x90000 (or 0x9000:0x0000 in real mode). Change these bits:

Code: Select all

    mov ebx,cg1+0x90000
    mov [callgate1],bx
    shr ebx,16
    mov [callgate1+6],bx

    mov ebx,donothing+0x90000
    mov [interone],bx
    shr ebx,16
    mov [interone+6],bx
..and..

Code: Select all

    jmp dword 8h:pm+0x90000
[bits 32]
Because this code is assembled with ORG = 0x0 and is actually running at 0x90000, every offset that you use in protected mode will be wrong and you'll need to add 0x90000 to them to fix it.

I'd recommend making the first stage contain 16 bit code only, and the second stage contain 32 bit code only. Then you could use the correct ORG for each. For e.g.:

"BOOT.TXT"

Code: Select all

  bits 16
  org 0x7C00

%define kernelAddress 0x90000

  jmp 0x00:start

start:
  ..set DS, ES and SS:ESP..
  ..load 32 bit code into memory..
  ..copy GDT to fixed address..
  ..load the GDT..
  cli
  mov eax,cr0
  or eax,1
  mov cr0,eax
  jmp dword 0x08:kernelAddress
..and..

"KERNEL.TXT"

Code: Select all

  bits 32
  org 0x90000

  jmp start

start:
  ..set DS, ES and SS:ESP..
  ..setup IDT..
  ..add call gate to GDT..

  jmp $
Cheers,

Brendan

Re:Problems with Interrupts and call gates

Posted: Wed Jun 30, 2004 3:32 am
by Curufir
Hmm. Well as Brendan says you're going to have to patch up those memory references for the ISR/Call Gate entry points.

Couple of things I noticed looking through:

Code: Select all

    jmp next
next:
Is pretty pointless.

Code: Select all

    jmp 8h:pm
If you're using NASM (That's what it looks like), then I think this gets encoded with only a 16-bit offset when used in a 16-bit section, which would be wrong. I'm not totally sure though, so diassemble and check. Any way you look at it you're going to have to hardcode the base somewhere. Either as a non-zero base for the pmode code segment (Yuck!) or as a define in your assembly. Reason being that a far jump has the form immediate:immediate, so you can't patch up the address in a register and pass it that way (Brendan already pointed this out).

Code: Select all

    mov ax,GDTEND                  ;calculate GDT limit
    mov bx,GDT
    sub ax,bx
This is redundant (And the wrong value anyway) since you calculate it correctly using the preprocessor when defining your GDT (Same goes for the IDT code).

Something fun for the future (Once you get into PMode).

Code: Select all

    int 0h
This is fine for calling your interrupt, with the minor problem that when you iret all interrupts will be enabled again. Since you haven't remapped/masked the PICs you'll start getting timer interrupts hitting on your 'donothing' routine at 18.2hz. This is not a bad thing (The output won't ever change so it's unlikely you'll even notice), and since you acknowledge the IRQ I'm guessing it's what you wanted. Problem is that you're not handling any of the other IRQs, so anything but the timer is going to triple fault the processor. Just something to keep aware of.

Re:Problems with Interrupts and call gates

Posted: Wed Jun 30, 2004 7:15 am
by Brendan
Hi,
Curufir wrote:

Code: Select all

    int 0h
This is fine for calling your interrupt, with the minor problem that when you iret all interrupts will be enabled again.
Not quite - "int 0h" is using an interrupt gate, which will push eflags, disable interrupts and then pop eflags, so that the interrupt disable flag would remain unchanged...

Cheers,

Brendan

Re:Problems with Interrupts and call gates

Posted: Wed Jun 30, 2004 1:22 pm
by Curufir
Serves me right for posting before coffee ;D.