Re: syscalls implementation

From: Terry Lambert (tlambert2_at_mindspring.com)
Date: 08/27/04

  • Next message: Mmaist: "Re: syscalls implementation"
    Date: Fri, 27 Aug 2004 04:16:12 -0700
    To: Mmaist <mmaist@email.it>
    
    

    Mmaist wrote:
    > Hi!
    > I was wondering were syscalls implementation is in the FreeBSD source tree.
    > I would like to know, especially, where
    >
    > int kldload(const char*);
    >
    > is located. sys/kern/kern_linker.c contains
    >
    > int
    > kldload(struct thread *, struct kldload_args *)
    >
    > and I need to watch at what called between them.

    This is probably the wrong list. You probably want -questions.

    Here's the simplest answer you will probably understand, given that the
    question you are really asking is about understanding how system calls
    work, and where baby system calls come from. 8-).

    The system calls are in code that's generated from the file
    /usr/src/sys/kern/syscalls.master by /usr/src/sys/kern/maksyscalls.sh,
    which is an awk script encapsulated in a shell script.

    In user space, the system calls are stubs in a library that traps into
    the vector code generated from syscalls.master in the kernel. This
    code is located in /usr/src/lib/libc. In the case os system calls
    that are unwrapped (like kldload(2)), the calls are generated assembly
    code that comes from running a script against the same syscalls.master
    file describd earlier; see src/lib/libc/sys/Makefile.inc for the exact
    place in the source tree that these stubs are being generated from.

    The way a system call happens is that the arguments are pushed on the
    stack (or put into registers, depending), and then a trap is issued by
    attempting to execute a supervisor-only instruction in user code. This
    effectively generates a fault which is then serviced by a fault handler
    in the kernel which recognizes the particular trap as "special", and
    treats it as a system call.

    Now when the special trap code in the kernel itself is activated, it
    packages up the arguments in a structure of a known size (known to the
    code in init_sysent.c, generated from syscalls.master).

    For the Intel version of the trap code, see /usr/src/sys/i386/i386/trap.c
    and the related assembly code there. The current thread and the packaged
    argument pointer are passed to the system call.

    Techinically, it makes a lot of things difficult that the current thread
    is passed into the system call as part of its context, rather than obtained
    when needed, and cached locally, if necessary, but since it's handy at the
    time, it's passed in. On non-register-poor architectures, the current
    thread is usually made available in a register, so the cost in obtaining it
    later is actually lss than a memory dereference of a computed stack offset,
    as it is/was (depends on the version, architecture, etc.) in FreeBSD because
    it's being passed in. On of the major things this makes difficult is
    accurate proxy credential representation at various points in the kernel (see
    the NFS server source code for examples of the contorted logic this makes
    necessary).

    The packages argument structures are defined in the (also generated from
    the syscalls.master) file /usr/src/sys/sys/sysproto.h. For the kldload
    system call, this looks like:

    struct kldload_args {
      char file_l_[PADL_(const char *)]; const char * file; char
    file_r_[PADR_(const char *)];
    };

    This argument structure is actually a dscriptor. A descriptor is used to
    ensure packing and alignment, so that the user stack save area can be
    coerced directly to the structure type, and dereferenced in the function.

    The descriptor contains the information necessary to line the structure
    contents up with the user stack area and/or register spill area, where the
    arguments were stored in user space before the trap. Mostly, you can just
    look at the middle element to know what the argument is, for each line of
    arguments. In this case, it's a "const char * file". This matches what
    it was in user space when you made the call.

    So the function you are seeing in the kernel:

            int kldload(struct thread *, struct kldload_args *);

    *is* the system call you saw in user space:

            int kldload(const char*);

    with the trap added thread pointer and pointer to the packed up save area
    containing the same char * value you passed in user space.

    Note that since the user and kernel space are not necessarily in core at
    the same time (maybe the pointer you pointed to was in a page that was
    swapped out), so you have to use copyin/uiomove in the function in the
    kernel to copy the path in before it can be used in the kernel address
    space.

    Probably you should not be hacking in this area until you understand the
    code operation a little better, since unless you know what you are doing,
    most changes you could possibly make will leave you with a dead system.

    -- Terry
    _______________________________________________
    freebsd-hackers@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
    To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"


  • Next message: Mmaist: "Re: syscalls implementation"

    Relevant Pages

    • Re: linux kernel user space
      ... >> I am developing a kernel module, and as to prevent a page fault from ... >> occuring when accessing data from user space, I need to copy it to ... >> the pointer points to. ... have to allocate enough space for the user space data but you don't ...
      (comp.os.linux.development.system)
    • Re: fuword(), suword(), etc.
      ... > at the moment ia need to know the size of a pointer and select the ... You cannot be certain that specific user space pointers are 64 ... want to be able to run the 32 bit applications. ... if you assume that the kernel pointer size is fixed on every ...
      (freebsd-current)
    • Re: [PATCH 2 of 4] Introduce i386 fibril scheduling
      ... You don't need an explicit cookie if you're passing in a pointer to ... In kernel space, the "one pointer" would be the fibril pointer (which ... anyway), and in user space, it would be better to have just the cookie be ...
      (Linux-Kernel)
    • Cannot boot with newly compiled kernel, or kernel.old after upgrading to RELENG_6
      ... The error when trying to boot the new kernel makes the system reboots ... Fatal trap 12: page fault while in kernel mode. ... instruction pointer = 0x8:0xc060bdff ...
      (freebsd-questions)
    • Re: call user function from kernel module?
      ... > Through a function pointer. ... I inserted a function pointer into an existing kernel function and ... extern void; ... so, if I create a function foo_userin user space, how do I set the ...
      (comp.os.linux.development.system)