Page 1 of 1

Syscall troubles

Posted: Wed Aug 26, 2009 3:56 am
by dak91
I implemented gdt idt isr and irq following Bran's tutorial (http://www.osdever.net/bkerndev/), now, I've started a syscall interface.

This is my C syscall handler: (only a piece)

Code: Select all

    void syscall_callback(regs_t *r)
    {   
       printf("Syscall: %d -> ", r->eax);
       if(r->eax == SYSCALL_FS_FOPEN)         { ...

called from an assembler function:

Code: Select all

    global syscallisr

    extern syscall_callback

    syscallisr:
       call syscall_callback
       iret

and the handler was added with this call:

Code: Select all

    idt_set_gate(84, (unsigned)syscallisr, 0x08, 0x8E);


I wanted to try if syscalls correctly run. I only put 1 on eax, and call the interrupt of syscall:

Code: Select all

    asm volatile("mov $1,%eax\n int $84\n");
but into the C syscall handler, (regs_t *)->eax doesn't have the value that I putted with mov, why? Sorry for my bad english xD

Re: Syscall troubles

Posted: Wed Aug 26, 2009 4:04 am
by pcmattman
dak91 wrote: called from an assembler function:

Code: Select all

    global syscallisr

    extern syscall_callback

    syscallisr:
       call syscall_callback
       iret

and the handler was added with this call:

Code: Select all

    idt_set_gate(84, (unsigned)syscallisr, 0x08, 0x8E);
You may want to try pushing the general purpose registers and segments to actually build your stack frame before you call "syscall_callback". An interrupt like the one you're doing only pushes CS:EIP and the EFLAGS (and possibly SS:ESP, if a privilege level change occurs - see section 5.12.1, Volume 3A, of the Intel Manuals).

Re: Syscall troubles

Posted: Wed Aug 26, 2009 4:08 am
by Brendan
Hi,

Your "syscall_callback(regs_t *r)" function expects the real EAX (the first and only parameter) to be a pointer to a structure. I would assume that your ISR handler is meant to build this structure on the stack (e.g. by using PUSH and maybe PUSHA), then set EAX to the address of this structure before calling the C code. For the C code, "r->eax" would access the copy of EAX in this structure, that was saved on the stack by "syscallisr". I'd also assume that your ISR handler is meant to load values from the stack back into general registers before it returns (e.g. with POP and maybe POPA).

For example, if might go something like:

Code: Select all

syscallisr:
       push ds
       push es
       pusha
       mov eax,<kernel's_data_selector>
       mov ds,eax
       mov es,eax
       mov eax,esp                    ;eax = pointer to the structure on the stack
       call syscall_callback
       popa
       pop es
       pop ds
       iret
Of course what you put on the stack (and what order you do it) must match the fields in your "regs_t" structure, and must match what you take off of the stack before you IRET.


Cheers,

Brendan

Re: Syscall troubles

Posted: Wed Aug 26, 2009 4:29 am
by Velko
Your "syscall_callback(regs_t *r)" function expects the real EAX (the first and only parameter) to be a pointer to a structure.
Am I missing something? Shouldn't pointer to structure be pushed onto stack?

Re: Syscall troubles

Posted: Wed Aug 26, 2009 4:44 am
by Brendan
Hi,
Velko wrote:
Your "syscall_callback(regs_t *r)" function expects the real EAX (the first and only parameter) to be a pointer to a structure.
Am I missing something? Shouldn't pointer to structure be pushed onto stack?
Ah - yes :)

I'm used to my own calling conventions (assembly language)...


Cheers,

Brendan