Page 1 of 1

Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 3:23 am
by maxoufox
Hello, i'm trying to make system calls work on my kernel. I have successfully get to ring 3, but when in send my int 0x30, a GPF is triggered. I get two revelant lines in my bochslog:

Code: Select all

00650553140e[CPU0 ] stackPrefetch(4): access [0x0000002c] > SS.limit [0x00000fff] ED
00650553159e[CPU0 ] fetch_raw_descriptor: GDT: index (f37) 1e6 > limit (7f8)
I have the source code hosted here: http://git.vic-team.fr/maxoufox/TestOS. I am following a tutorial in french wich is here: http://a.michelizza.free.fr/pmwiki.php?n=TutoOS.Syscall. I don't like the global code organisation in this tutorial, so I based my code on the meaty skeletton project. The source code provided with the tutorial is compilling and running well, without any errors, but my code fails, and I don't know why... I hope to get help, because after looking at the code for hours, I can't find the problem...

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 4:03 am
by mallard
I'm not sure how to get at the code on that website, but the error messages look like they relate to the stack segment being invalid. Have you set the kernel-mode stack segment and address in your TSS?

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 4:22 am
by maxoufox
Code is here: http://a.michelizza.free.fr/uploads/Tut ... yscall.tgz.
I don't know why the message appears, but when I comment the lne 51 in kernel.c ("asm("mov %0, %%ebx; mov $0x01, %%eax; int $0x30" :: "m" (msg));"), all goes whell. I still get interrupts comming from the PIT and the keyboard...

EDIT: So, I've take a look at the wiki page about TSS, and i've set esp0 to 0x10 instead of 0x18, and I no longer get the GPF. But now I have another problem... The arguments for the syscalls are not ok... i don't know why, but i'll search.

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 5:46 am
by iansjack
How are you passing the arguments to the system call?

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 5:57 am
by maxoufox
I'm using registers. Here is my syscall.c:

Code: Select all

#include <stddef.h>
#include <kernel/gdt.h>
#include <stdio.h>
#include <stdlib.h>

void do_syscalls(int sys_num) {
	uint16_t ds_select;
	uint32_t ds_base;
	struct gdtdesc *ds;
	char *message;

	if (sys_num == 1) {
		asm("	mov 44(%%ebp), %%eax    \n \
				mov %%eax, %0           \n \
				mov 24(%%ebp), %%ax     \n \
				mov %%ax, %1" : "=m"(message), "=m"(ds_select) : );
		printf("printf\n");
		
		ds = (struct gdtdesc *) (GDTBASE + (ds_select & 0xF8));
		ds_base = ds->base0_15 + (ds->base16_23 << 16) + (ds->base24_31 << 24);
		
		char* buf;
		itoa((uint64_t)(ds_base + message), 16, buf);
		printf("%s", buf);
		
		asm("xchgw %bx, %bx");
		
		printf((ds_base + message));
	} else {
		printf("syscall\n");
	}

	return;
}
I have checked the address that the code returns, and i have debugged the memory with bochs, and the only things that i've found on the memory location in a bunch of 0x00...

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 6:05 am
by iansjack
I'm sorry but I can't follow what that code is doing. A few comments would help.

Anyway, if you are putting the arguments in registers then I can see no way that an int x instruction would change them. If you were using the stack I would have suggested that you were looking at the wrong part of the stack, or even the wrong stack.

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 6:33 am
by LtG
Not sure if I'm missing something, but all of the do_syscall variables are on the stack and all of them are uninitialized, is that intentional?

Also your first asm block thrashes EAX, yet you've not informed GCC of that in the clobbered list?

Re: Getting a GPF when sending a syscall.

Posted: Fri May 05, 2017 9:46 am
by maxoufox
So, I've solved the problem... I'm just sacrifying a register to store %ds, here is the commit where I fix everything, if someone has another idea.

Re: Getting a GPF when sending a syscall.

Posted: Sat May 06, 2017 1:07 am
by Octocontrabass
maxoufox wrote:I am following a tutorial in french wich is here:
That tutorial is very bad. Almost all of the inline assembly is wrong.
maxoufox wrote:So, I've solved the problem... I'm just sacrifying a register to store %ds, here is the commit where I fix everything, if someone has another idea.
I have another idea: pass all of the registers as an argument to your syscall handler.

For the assembly portion of your syscall handler:

Code: Select all

_asm_syscalls:
        SAVE_REGS
        push esp                 ; regs_t *
        call do_syscalls
        add esp, 4
        RESTORE_REGS
        iret
And the C portion:

Code: Select all

typedef struct regs
{
        uint32_t gs, fs, es, ds;
        uint32_t edi, esi, ebp, padding, ebx, edx, ecx, eax; //pushad, popad
        uint32_t eip, cs, eflags, esp, ss;                   //int, iret
} regs_t; 


void do_syscalls(regs_t * regs)
{
        uint32_t ds_base;
        struct gdtdesc *ds;
        unsigned char *message;
        if (regs->eax == 1) {

                ds = (struct gdtdesc *) (GDTBASE + (regs->ds & 0xF8));
                message = (unsigned char*)(regs->ebx);
                // example code, you can figure out the rest
        }

        return;
}
And then you can use system calls like this:

Code: Select all

asm("int $0x30" :: "a"(1), "b"(msg) : "memory" );
I haven't tested this code, so it may have mistakes.