Getting a GPF when sending a syscall.

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
maxoufox
Posts: 4
Joined: Fri May 05, 2017 3:06 am

Getting a GPF when sending a syscall.

Post 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...
mallard
Member
Member
Posts: 280
Joined: Tue May 13, 2014 3:02 am
Location: Private, UK

Re: Getting a GPF when sending a syscall.

Post 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?
Image
maxoufox
Posts: 4
Joined: Fri May 05, 2017 3:06 am

Re: Getting a GPF when sending a syscall.

Post 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.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Getting a GPF when sending a syscall.

Post by iansjack »

How are you passing the arguments to the system call?
maxoufox
Posts: 4
Joined: Fri May 05, 2017 3:06 am

Re: Getting a GPF when sending a syscall.

Post 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...
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Getting a GPF when sending a syscall.

Post 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.
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: Getting a GPF when sending a syscall.

Post 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?
maxoufox
Posts: 4
Joined: Fri May 05, 2017 3:06 am

Re: Getting a GPF when sending a syscall.

Post 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.
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: Getting a GPF when sending a syscall.

Post 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.
Post Reply