1/**
2 * \file
3 * \brief User-side system call implementation
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#ifndef ARCH_X86_32_BARRELFISH_SYSCALL_H
16#define ARCH_X86_32_BARRELFISH_SYSCALL_H
17
18#include <barrelfish_kpi/syscalls.h>  // for struct sysret.
19
20/* Always review the generated assembly when changing this! */
21// XXX: noinline for now, until I figured out why GCC doesn't obey the asm
22// constraints
23static __attribute__ ((noinline))
24struct sysret syscall(uintptr_t arg0, uintptr_t arg1,
25                      uintptr_t arg2, uintptr_t arg3,
26                      uintptr_t arg4, uintptr_t arg5,
27                      uintptr_t arg6)
28{
29    /* XXX: This pushes the PIC register and frame pointer. Some GCC
30     * versions disallow specifying EBP as a register variable. Since
31     * we don't know when this is the case, we currently go via memory
32     * for that variable and so the frame pointer doesn't need to be
33     * pushed here. Also, we don't need to push the PIC register while
34     * declaring this function noinline.
35     */
36    /* __asm volatile("push %ebx"); */
37    /* __asm volatile("push %ebp"); */
38
39    // This order is important!
40    register uintptr_t a0 __asm("edi") = arg0;
41    register uintptr_t a1 __asm("esi") = arg1;
42    register uintptr_t a2_ret2 __asm("edx") = arg2;
43    register uintptr_t a3_ret1 __asm("eax") = arg3;
44    register uintptr_t a4 __asm("ebx") = arg4;
45    register uintptr_t a6 __asm("ecx") = arg6;
46    //    register uintptr_t a5 __asm("ebp") = arg5;  // Needs to be last
47
48    __asm volatile("push %%ebp                  \n\t"
49                   "mov %[arg5], %%ebp          \n\t"
50                   "int $0xff                   \n\t"
51                   "pop %%ebp                   \n\t"
52                   /* "pop %%ebx                   \n\t" */
53                   : "+a" (a3_ret1), "+d" (a2_ret2), "+r" (a6)
54                   : "r" (a0), "r" (a1), "r" (a4), [arg5] "m" (arg5));
55
56    return (struct sysret){/*error*/ a3_ret1, /*value*/ a2_ret2};
57}
58
59#define syscall7(_a, _b, _c, _d, _e, _f, _g)    \
60    syscall(_a, _b, _c, _d, _e, _f, _g)
61#define syscall6(_a, _b, _c, _d, _e, _f)        \
62    syscall7(_a, _b, _c, _d, _e, _f, 0)
63#define syscall5(_a, _b, _c, _d, _e)            \
64    syscall6(_a, _b, _c, _d, _e, 0)
65#define syscall4(_a, _b, _c, _d)                \
66    syscall5(_a, _b, _c, _d, 0)
67#define syscall3(_a, _b, _c)                    \
68    syscall4(_a, _b, _c, 0)
69#define syscall2(_a, _b)                        \
70    syscall3(_a, _b, 0)
71#define syscall1(_a)                            \
72    syscall2(_a, 0)
73
74#endif
75