美文网首页
Syscall routines of Magenta

Syscall routines of Magenta

作者: oceanken | 来源:发表于2017-11-27 19:54 被阅读0次

Google正在酝酿的Fushia以Magenta为内核,它由LK(LittleKernel)发展而来,在LK的基础上封装了各种内核对象,以Handles的形式提供给用户态进程使用。Magenta是一个微内核,只提供了进程、IPC、同步、地址空间管理等等基础设施,更多的功能依靠用户进程来实现。用户进程通过系统调用与内核对象交互,并实现用户进程之间的通信。本文简要介绍了Magenta在X86_64平台中系统调用的实现过程。

  1. 运行magenta/scripts/run-sysgen时,sysgen.cpp会将magenta/system/public/magenta/syscalls.sysgen定义的系统调用函数导出表转换生成相应的文件。特别地,生成的gen-syscalls.h声明了两组相同的函数,分别以“mx_”和“_mx_”作为前缀,如:
    extern mx_status_t mx_handle_close(mx_handle_t handle);
    extern mx_status_t _mx_handle_close(mx_handle_t handle);
    在syscalls-x86-64.S中实现了“_mx_”为前缀的实现,并将“mx_”函数指向“_mx_”函数。

  2. 在magenta/system/ulib/magenta/syscalls-x86-64.S中定义了 “.macro m_syscall nargs, name, n”, 将system/ulib/magenta/gen-x86-64.S中的函数进行了定义。在函数实现中,除了将入参写入寄存器,还将MAGENTA_SYSCALL_MAGIC 与调用号异或后写入%rax,随后调用syscall触发系统调用。同时,将“mx_”和“_mx_”为前缀的函数指向同一实现:

    .macro m_syscall nargs, name, n
    .globl _\name
    .type _\name,STT_FUNC
    _\name:
    ........
    movabs $(MAGENTA_SYSCALL_MAGIC | \n), %rax
    syscall
    ........
    .size _\name, . - _\name
    .weak \name
    .type \name,STT_FUNC
    \name = _\name
    .size \name, . - _\name
    .endm

    这里以“mx_”开头的符号被声明为弱符号,同时将“mx_”函数重命名为“_mx_”函数。可以看出,“_mx_”符号是强符号,必须实现;“mx_”是弱符号,可以只声明不定义,不会引起link error。

  3. 在mp初始化时,向CPU设定syscall的入口:
    // magenta/kernel/arch/x86/mp.c
    void x86_init_percpu(uint8_t cpu_num)
    {
    .......
    #if ARCH_X86_64
    /* load the syscall entry point */
    extern void x86_syscall(void);
    write_msr(X86_MSR_IA32_LSTAR, (uint64_t)&x86_syscall);
    write_msr(X86_MSR_IA32_STAR, (uint64_t)USER_CODE_SELECTOR << 48 |(uint64_t)CODE_64_SELECTOR << 32);
    ......
    #endif
    ......
    }

  4. 在magenta/kernel/arch/x86/64/syscall.S中定义了x86_syscall,实现中将在寄存器中的参数压栈,以调用C方法x86_64_syscall:

    FUNCTION(x86_syscall)
    ......
    /* call the high level routine */
    call x86_64_syscall
    ......
    END(x86_syscall)

  5. 在magenta/kernel/lib/syscalls/syscalls.cpp中实现x86_64_syscall:
    #if ARCH_X86_64
    #include <arch/x86.h>

    using syscall_func = int64_t (*)(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e,
    uint64_t f, uint64_t g, uint64_t h);

    uint64_t x86_64_syscall(uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4,
    uint64_t arg5, uint64_t arg6, uint64_t arg7, uint64_t arg8,
    uint64_t syscall_num, uint64_t ip) {

    /* check for magic value to differentiate our syscalls */
    if (unlikely((syscall_num >> 32) != 0xff00ff)) {
    LTRACEF("syscall does not have magenta magic, %#" PRIx64
    " @ IP %#" PRIx64 "\n", syscall_num, ip);
    return ERR_BAD_SYSCALL;
    }
    syscall_num &= 0xffffffff;

    ......

    /* build a function pointer to call the routine.
    the args are jammed into the function independent of if the function
    uses them or not, which is safe for simple arg passing.
    */
    syscall_func sfunc;

    switch (syscall_num) {
    #define MAGENTA_SYSCALL_DEF(nargs64, nargs32, n, ret, name, args...)
    case n:
    sfunc = reinterpret_cast<syscall_func>(sys_##name);
    break;
    #include <magenta/gen-switch.inc>
    default:
    sfunc = reinterpret_cast<syscall_func>(sys_invalid_syscall);
    }

    /* call the routine */
    uint64_t ret = sfunc(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
    ......
    }

    #endif

    在kernel/lib/magenta/include/magenta/gen-switch.inc中定义了调用号和函数之间的对应关系:
    ......
    case 5:
    sfunc = reinterpret_cast(sys_handle_close);
    break;
    case 6:
    sfunc = reinterpret_cast(sys_handle_duplicate);
    break;
    ......

    在x86_64_syscall中,通过syscall_num去检查MAGENTA_SYSCALL_MAGIC,通过后再取出调用号,并通过kernel/lib/magenta/include/magenta/gen-switch.inc映射到sys_开头(e.g. sys_handle_close)的函数,并调用。从中可以看出,gen-switch.inc 与 gen-x86-64.S 定义的调用号与函数之间的对应关系必须一致。

所以,当用户态进程调用mx_status_t mx_handle_close(mx_handle_t handle),会最终调用到内核里的实现方法mx_status_t sys_handle_close(mx_handle_t handle)。sys_开头的系统调用实现位于kernel/lib/syscall目录下的对应文件中,如kernel/lib/syscall/sys_handle_ops.cpp。

文中涉及到的文件:
magenta/scripts/run-sysgen
magenta/system/tools/sysgen.cpp
magenta/system/public/magenta/syscalls.sysgen
脚本生成的文件===>
system/public/magenta/gen-syscalls.h
system/ulib/magenta/gen-x86-64.S <---included from--- magenta/system/ulib/magenta/syscalls-x86-64.S
system/ulib/magenta/gen-arm32.S <---included from--- magenta/system/ulib/magenta/syscalls-arm32.S
system/ulib/magenta/gen-arm64.S <---included from--- magenta/system/ulib/magenta/syscalls-arm64.S
kernel/lib/magenta/include/magenta/gen-sysdefs.h
kernel/lib/magenta/include/magenta/gen-switch.inc
kernel/lib/magenta/include/magenta/gen-trace.inc

相关文章

网友评论

      本文标题:Syscall routines of Magenta

      本文链接:https://www.haomeiwen.com/subject/mnadbxtx.html