OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 10:15 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 3:23 am 
Offline

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


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 4:03 am 
Offline
Member
Member

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


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 4:22 am 
Offline

Joined: Fri May 05, 2017 3:06 am
Posts: 4
Code is here: http://a.michelizza.free.fr/uploads/TutoOS/kernel_MonoTask_Syscall.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.


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 5:46 am 
Online
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
How are you passing the arguments to the system call?


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 5:57 am 
Offline

Joined: Fri May 05, 2017 3:06 am
Posts: 4
I'm using registers. Here is my syscall.c:
Code:
#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...


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 6:05 am 
Online
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
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.


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 6:33 am 
Offline
Member
Member

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


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Fri May 05, 2017 9:46 am 
Offline

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


Top
 Profile  
 
 Post subject: Re: Getting a GPF when sending a syscall.
PostPosted: Sat May 06, 2017 1:07 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5137
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:
_asm_syscalls:
        SAVE_REGS
        push esp                 ; regs_t *
        call do_syscalls
        add esp, 4
        RESTORE_REGS
        iret


And the C portion:
Code:
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:
asm("int $0x30" :: "a"(1), "b"(msg) : "memory" );


I haven't tested this code, so it may have mistakes.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 87 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group