Call gates

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
ManOfSteel

Call gates

Post by ManOfSteel »

Hello,
I'm very confused about call gates. I read somewhere (in 'Intel - System Programming', I think) that call gates are divided into trap gates and interrupt gates. Since call gates are found in the GDT and the two others in the IDT and that GDT has nothing to do with IDT, then, how can this be possible?
Besides, I didn't find any helpful description of a call gate. They can be used to call procedures (like the interrupts), right? How can I modify a normal GDT segment so it can become a call gate?
thanks for any help.
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:Call gates

Post by Pype.Clicker »

you do not modify a segment to become a gate: you define a gate that makes a user enter a segment.

You may think of gates as "redirectors". when one calls a gate, it actually get redirected towards what the gate defines.

Since gates provide all the information required to define an entry point, Intel designers found it smart to call the 'interrupt table' descriptors 'gates' aswell. Some gates make little sense out of the IDT (like the Interrupt gate, which is simply a trap that will clear the IF bit when entered and restore it when left, iirc)

Other kind of gates (notably the Task gate) may exist in both GDT, LDT and IDT.
ManOfSteel

Re:Call gates

Post by ManOfSteel »

Hello,
is there anything wrong with this call gate?

Code: Select all

GDT:
;null segment
;code segment
;data segment
;video segment
CallGate01:
         dw cg1          ;offset
         dw 08h          ;selector
         db 0            ;
         db 10001100b    ;present (1), ring0 (00), type (01100)
         dw 0            ;offset
GDTEnd:


cg1:                     ;call gate handler (does nothing)
    iret
How do I call it? 'call 28h:0'?
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:Call gates

Post by Pype.Clicker »

"call far 28h:0" could be preferred depending on your assembler. Note that a call gate does not return with "iret" but instead with "retf"
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Call gates

Post by Brendan »

Hi,
ManOfSteel wrote:

Code: Select all

GDT:
;null segment
;code segment
;data segment
;video segment
CallGate01:
         dw cg1          ;offset
         dw 08h          ;selector
         db 0            ;
         db 10001100b    ;present (1), ring0 (00), type (01100)
         dw 0            ;offset
GDTEnd:

cg1:                     ;call gate handler (does nothing)
    iret
If the offset "cg1" is not within the first 64 Kb of memory it will be truncated (your assembler may/may not give a warning/error). If the call gate is to be used by CPL=3 code (a good assumption IMHO) then you'll want DPL=3. Also the code called by the call gate should use "RETF" to return rather than "IRETD".

Code: Select all

GDT:
;null segment          0x0000
;code segment          0x0008
;data segment          0x0010
;video segment         0x0018
CallGate01:          ; 0x0020
         dw (cg1 & 0xFFFF)  ;offset low word
         dw 08h             ;selector
         db 0               ;stack parameters to copy
         db 11101100b       ;present (1), DPL (03), type (01100)
         dw (cg1 >> 16)     ;offset high word
GDTEnd:

cg1:                     ;call gate handler (does nothing)
       retf
How do I call it? 'call 28h:0'?
Yes, well almost - "call 20h:0" :-)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ManOfSteel

Re:Call gates

Post by ManOfSteel »

Hello and thanks for your replies, but after a lot of tries, my call gate is still not working. Bochs crashes (illegal opertion) before running any piece of code.
I used Bochs 1.4.1 and 2.1 and it is not working better with any one.

The illegal operation (with Bochs 1.4.1 only):

Code: Select all

BOCHS caused an invalid page fault in module BOCHS.EXE at 0187:0043d132.
Registers:
EAX=00bafd20 CS=0187 EIP=0043d132 EFLGS=00010246
EBX=00aa0000 SS=018f ESP=00bafc94 EBP=00bafcf8
ECX=549d01e5 DS=018f ESI=81766e60 FS=4ee7
EDX=00000000 ES=018f EDI=00000000 GS=0000
Bytes at CS:EIP:
8a 11 89 55 e8 8b 45 08 83 c0 01 89 45 08 8b 4d
Stack dump:
00bafca0 0046b739 00000020 00bafcb0 0046b20a 004adc60 00000000 00bafcc8 00401986 004adc60 00000002 00cd07f0 00000065 00bafce8 00401da3 00000019
Bochs 1.4.1 output:

Code: Select all

00000000000i[MEM0 ] 8.00MB
00000000000i[MEM0 ] rom at 0xf0000/65536 ('../BIOS-bochs-latest')
00000000000i[MEM0 ] rom at 0xc0000/32769 ('../VGABIOS-elpin-2.40')
00000000000i[CMOS ] Setting initial clock to: Thu May 13 09:53:15 2004
00000000000i[FDD  ] fd0: '1.44' ro=0, h=2,t=80,spt=18
00000000000i[SB16 ] midi=0,  wave=0,  log=0,  dmatimer=0
00000000000i[VGA  ] interval=30000
00000000000i[VGA  ] VBE Bochs Display Extension Enabled
00000000000i[KBD  ] will paste characters every 1000 keyboard ticks
00000004012i[BIOS ]  rombios.c,v 1.42.2.1 2002/05/15 13:41:03 cbothamy Exp $
00000006521i[VGA  ] char map select: #1=0 / #2=0 (unused)
00000156932e[HD   ] device set to 0 which does not exist
00000158492e[HD   ] device set to 1 which does not exist
00000160052e[HD   ] device set to 0 which does not exist
00000162496e[HD   ] device set to 1 which does not exist
00000163456e[HD   ] device set to 0 which does not exist
00000164493e[HD   ] device set to 1 which does not exist
00000165092e[HD   ] device set to 0 which does not exist
00000165696e[HD   ] device set to 0 which does not exist
00000166896e[HD   ] device set to 1 which does not exist
00000168115e[HD   ] device set to 1 which does not exist
00000168717e[HD   ] device set to 0 which does not exist
00000171200e[HD   ] device set to 1 which does not exist
00000172160e[HD   ] device set to 0 which does not exist
00000173197e[HD   ] device set to 1 which does not exist
00000173796e[HD   ] device set to 0 which does not exist
00000176592e[HD   ] device set to 1 which does not exist
00000177552e[HD   ] device set to 0 which does not exist
00000178589e[HD   ] device set to 1 which does not exist
00000179188e[HD   ] device set to 0 which does not exist
00000216075i[FDD  ] partial read() on floppy image returns 328/512
00000217085e[CPU  ] prefetch: running in bogus memory
ManOfSteel

Re:Call gates

Post by ManOfSteel »

My GDT, which contains the call gate, is directly followed by the call gate handler:

Code: Select all

GDTDESCR:
GDTLimit dw GDTEnd-GDT-1
GDTBase  dd GDT
GDT:
GDTNull:
         db 0
         db 0
         db 0
         db 0
         db 0
         db 0
         db 0
         db 0
GDTCode:
         db 0ffh
         db 0ffh
         db 00h
         db 00h
         db 00h
         db 10011011b
         db 11011111b
         db 00h
GDTData:
         db 0ffh
         db 0ffh
         db 00h
         db 00h
         db 00h
         db 10010011b
         db 11011111b
         db 00h
GDTVideo:
         db 9fh
         db 0fh
         db 00h
         db 80h
         db 0bh
         db 92h
         db 00h
         db 00h
CallGate01:
         dw cg1
         dw 08h
         db 0
         db 10001100b
         dw 0
GDTEnd:

cg1:
    retf
I jump to the call gate like this:

Code: Select all

call 20h:0
Brendan, I didn't really understand what you meant by these:

Code: Select all

dw (cg1 & 0xFFFF)  ;offset low word
...
dw (cg1 >> 16)     ;offset high word
If the call gate is to be used by CPL=3 code (a good assumption IMHO) then you'll want DPL=3.
In fact, I'm using it with ring zero code. I will not use it only to jump to different-DPL-code but as interrupts (yeah, I know, I can do it with interrupt gates).


PS: sorry for pasting too much information here.
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:Call gates

Post by Pype.Clicker »

ManOfSteel wrote: Brendan, I didn't really understand what you meant by these:

Code: Select all

dw (cg1 & 0xFFFF)  ;offset low word
...
dw (cg1 >> 16)     ;offset high word
What brendan mean is that a 'dw' can only hold 16 bits of your potentially-32-bits offset (cg1). A 32 bits value can be split in two 16 bits values using lo=full & 0xFFFF (masking out the higher bits) and hi=full >> 16 (right-shifting the full value).

The problem is that, in most situations, such things doesn't work because the exact value of the symbol 'cg1' is unknown to the assembler (which must leave a part of the job to the linker) and that linkable objects usually cannot tell "this is the lowest 16 bits of a 32 bits offset, the highest 16 bits are there... look ..."

So you have to leave the two fields unfilled and perform the computations yourself at runtime, before you use the callgate (of course)
ManOfSteel

Re:Call gates

Post by ManOfSteel »

So you have to leave the two fields unfilled and perform the computations yourself at runtime, before you use the callgate (of course)
And how is that done? Is it possible to take the 32 bits offset and split it into two 16 bits offset? Can it be done using shr and shl or something else?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Call gates

Post by Brendan »

Hi,
ManOfSteel wrote: And how is that done? Is it possible to take the 32 bits offset and split it into two 16 bits offset? Can it be done using shr and shl or something else?
Yes:

Code: Select all

;Set kernel process call gate offset

   mov ebx,[KERNspace+HEADEREND]
   mov [GDTaddress+SELPROCAPI],bx
   shr ebx,16
   mov [GDTaddress+SELPROCAPI+6],bx
Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ManOfSteel

Re:Call gates

Post by ManOfSteel »

What am I doing wrong again?

This is before setting up the GDT (lgdt)...

Code: Select all

    mov ebx,[cg1]
    mov [cg1low],bx
    shr ebx,16
    mov [cg1high],bx
...and This is my call gate

Code: Select all

CallGate01:
         dw cg1low
         dw 08h
         db 0
         db 10001100b
         dw cg1high
GDTEnd:

cg1:
    retf

cg1low  dw 0
cg1high dw 0
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Call gates

Post by Brendan »

Hi,
ManOfSteel wrote: What am I doing wrong again?
Try this:

Code: Select all

    mov ebx,cg1
    mov [CallGate01],bx
    shr ebx,16
    mov [CallGate01+6],bx


...and This is the call gate:

CallGate01:
         dw 0              ;Offset low word (set dynamically)
         dw 08h            ;Code segment
         db 0
         db 11101100b      ;present (1), ring3 (11), type (01100)
         dw 0              ;Offset high word (set dynamically)
GDTEnd:

cg1:
    retf

Hope that helps...

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Post Reply