Procházet zdrojové kódy

Rebase and squash the FreeBSD PAL.

woachk před 5 roky
rodič
revize
f07dfd052f

+ 2 - 2
Pal/src/host/FreeBSD/Makefile

@@ -16,8 +16,8 @@ host_target = libpal-FreeBSD.a ../../pal-gdb
 
 defs	= -DIN_PAL -DPAL_DIR="$(PAL_DIR)"
 objs	= $(addprefix db_,files devices pipes sockets streams memory threading \
-	    semaphore mutex events process object main rtld misc ipc \
-	    exception) rfork_thread
+	    mutex events process object main rtld misc ipc \
+	    exception2) rfork_thread
 graphene_lib = .lib/graphene-lib.a
 headers	= $(wildcard *.h) $(wildcard ../../*.h) $(wildcard ../../../lib/*.h)
 

+ 2 - 2
Pal/src/host/FreeBSD/db_devices.c

@@ -104,12 +104,12 @@ static int open_standard_term (PAL_HANDLE * handle, const char * param,
     hdl->dev.dev_type = device_type_term;
 
     if (!(access & PAL_ACCESS_WRONLY)) {
-        hdl->__in.flags |= RFD(0);
+        hdl->hdr.flags |= RFD(0);
         hdl->dev.fd_in = 0;
     }
 
     if (access & (PAL_ACCESS_WRONLY|PAL_ACCESS_RDWR)) {
-        hdl->__in.flags |= WFD(1);
+        hdl->hdr.flags |= WFD(1);
         hdl->dev.fd_out = 1;
     }
 

+ 19 - 1
Pal/src/host/FreeBSD/db_events.c

@@ -78,7 +78,7 @@ int _DkEventSet (PAL_HANDLE event, int wakeup)
     return IS_ERR(ret) ? PAL_ERROR_TRYAGAIN : ret;
 }
 
-int _DkEventWaitTimeout (PAL_HANDLE event, int timeout)
+int _DkEventWaitTimeout (PAL_HANDLE event, uint64_t timeout)
 {
     int ret = 0;
     if (!event->event.isnotification || !atomic_read(&event->event.signaled)) {
@@ -142,3 +142,21 @@ int _DkEventClear (PAL_HANDLE event)
     atomic_set(&event->event.signaled, 0);
     return 0;
 }
+
+
+static int event_close (PAL_HANDLE handle)
+{
+    _DkEventSet(handle, -1);
+    return 0;
+}
+
+static int event_wait (PAL_HANDLE handle, uint64_t timeout)
+{
+    return timeout == NO_TIMEOUT ? _DkEventWait(handle) :
+           _DkEventWaitTimeout(handle, timeout);
+}
+
+struct handle_ops event_ops = {
+        .close              = &event_close,
+        .wait               = &event_wait,
+};

+ 4 - 5
Pal/src/host/FreeBSD/db_exception.c

@@ -40,6 +40,8 @@
 #include <ucontext.h>
 #include <errno.h>
 
+typedef void (*PAL_UPCALL) (PAL_PTR, PAL_NUM, PAL_CONTEXT *);
+
 int set_sighandler (int * sigs, int nsig, void * handler)
 {
     struct sigaction action;
@@ -327,8 +329,7 @@ static struct pal_frame * get_frame (ucontext_t * uc)
     for (unsigned long ptr = rbp - sizeof(unsigned long) ;
          ptr > last_rbp ; ptr -= 8) {
         struct pal_frame * frame = (struct pal_frame *) ptr;
-
-        if (frame->self == frame)
+        if (frame->identifier == PAL_FRAME_IDENTIFIER)
             return frame;
     }
 
@@ -429,7 +430,6 @@ struct signal_ops {
 };
 
 struct signal_ops on_signals[PAL_EVENT_NUM_BOUND] = {
-        /* reserved    */ { .signum = { 0 }, .handler = NULL },
         /* DivZero     */ { .signum = { SIGFPE, 0 },
                             .handler = _DkGenericSighandler },
         /* MemFault    */ { .signum = { SIGSEGV, SIGBUS, 0 },
@@ -442,7 +442,6 @@ struct signal_ops on_signals[PAL_EVENT_NUM_BOUND] = {
                             .handler = _DkTerminateSighandler },
         /* Resume      */ { .signum = { SIGCONT, 0 },
                             .handler = _DkGenericSighandler },
-        /* Failure     */ { .signum = { 0 }, .handler = NULL },
     };
 
 static int _DkPersistentSighandlerSetup (int event_num)
@@ -571,7 +570,7 @@ err:
     init_fail(-ret, "cannot setup signal handlers");
 }
 
-void _DkExceptionReturn (const void * event)
+void _DkExceptionReturn (void * event)
 {
     const struct exception_event * e = (const struct exception_event *) event;
     if (e->uc) {

+ 465 - 0
Pal/src/host/FreeBSD/db_exception2.c

@@ -0,0 +1,465 @@
+/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
+/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
+
+/* Copyright (C) 2014 Stony Brook University
+   This file is part of Graphene Library OS.
+
+   Graphene Library OS is free software: you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   Graphene Library OS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+ * db_signal.c
+ *
+ * This file contains APIs to set up handlers of exceptions issued by the
+ * host, and the methods to pass the exceptions to the upcalls.
+ */
+
+#include "pal_defs.h"
+#include "pal_freebsd_defs.h"
+#include "pal.h"
+#include "pal_internal.h"
+#include "pal_freebsd.h"
+#include "pal_error.h"
+#include "pal_security.h"
+#include "api.h"
+
+#include <atomic.h>
+#include <sigset.h>
+#include <ucontext.h>
+#include <errno.h>
+
+#if !defined(__i386__)
+/* In x86_64 kernels, sigaction is required to have a user-defined
+ * restorer. Also, they not yet support SA_INFO. The reference:
+ * http://lxr.linux.no/linux+v2.6.35/arch/x86/kernel/signal.c#L448
+ *
+ *     / * x86-64 should always use SA_RESTORER. * /
+ *     if (ka->sa.sa_flags & SA_RESTORER) {
+ *             put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
+ *     } else {
+ *             / * could use a vstub here * /
+ *             err |= -EFAULT;
+ *     }
+ */
+
+void restore_rt (void) asm ("__restore_rt");
+
+#ifndef SA_RESTORER
+#define SA_RESTORER  0x04000000
+#endif
+
+#define DEFINE_RESTORE_RT(syscall) DEFINE_RESTORE_RT2(syscall)
+# define DEFINE_RESTORE_RT2(syscall)                \
+    asm (                                           \
+         "    nop\n"                                \
+         ".align 16\n"                              \
+         ".LSTART_restore_rt:\n"                    \
+         "    .type __restore_rt,@function\n"       \
+         "__restore_rt:\n"                          \
+         "    movq $" #syscall ", %rax\n"           \
+         "    syscall\n");
+
+#endif
+
+int set_sighandler (int * sigs, int nsig, void * handler)
+{
+    struct sigaction action;
+
+    if (handler) {
+        action.sa_handler = (void (*)(int)) handler;
+        action.sa_flags = SA_SIGINFO;
+#if !defined(__i386__)
+        //action.sa_flags |= SA_RESTORER;
+        //action.sa_restorer = restore_rt;
+#endif
+    } else {
+        action.sa_handler = SIG_IGN;
+    }
+
+#ifdef DEBUG
+    if (!linux_state.in_gdb)
+#endif
+        action.sa_flags |= SA_NOCLDWAIT;
+
+    __sigemptyset((__sigset_t *) &action.sa_mask);
+    __sigaddset((__sigset_t *) &action.sa_mask, SIGCONT);
+
+    for (int i = 0 ; i < nsig ; i++) {
+#if defined(__i386__)
+        int ret = INLINE_SYSCALL(sigaction, 3, sigs[i], &action, NULL)
+#else
+        int ret = INLINE_SYSCALL(sigaction, 4, sigs[i], &action, NULL,
+                                 sizeof(sigset_t));
+#endif
+        if (IS_ERR(ret))
+            return -PAL_ERROR_DENIED;
+    }
+
+    return 0;
+}
+
+typedef struct {
+    PAL_IDX         event_num;
+    PAL_CONTEXT     context;
+    ucontext_t *    uc;
+    PAL_PTR         eframe;
+} PAL_EVENT;
+
+#define SIGNAL_MASK_TIME 1000
+
+#define save_return_point(ptr)                      \
+    asm volatile ("leaq 0(%%rip), %%rax\r\n"        \
+                  "movq %%rax, %0\r\n"              \
+                  : "=b"(ptr) :: "memory", "rax")
+
+static int get_event_num (int signum)
+{
+    switch(signum) {
+        case SIGFPE:                return PAL_EVENT_DIVZERO;
+        case SIGSEGV: case SIGBUS:  return PAL_EVENT_MEMFAULT;
+        case SIGILL:  case SIGSYS:  return PAL_EVENT_ILLEGAL;
+        case SIGTERM:               return PAL_EVENT_QUIT;
+        case SIGINT:                return PAL_EVENT_SUSPEND;
+        case SIGCONT:               return PAL_EVENT_RESUME;
+        default: return -1;
+    }
+}
+
+void _DkGenericEventTrigger (PAL_IDX event_num, PAL_EVENT_HANDLER upcall,
+                             PAL_NUM arg, struct pal_frame * frame,
+                             ucontext_t * uc, void * eframe)
+{
+    PAL_EVENT event;
+    event.event_num = event_num;
+
+    if (uc) {
+        event.context.r8  = uc->uc_mcontext.mc_r8;
+        event.context.r9  = uc->uc_mcontext.mc_r9;
+        event.context.r10 = uc->uc_mcontext.mc_r10;
+        event.context.r11 = uc->uc_mcontext.mc_r11;
+        event.context.r12 = uc->uc_mcontext.mc_r12;
+        event.context.r13 = uc->uc_mcontext.mc_r13;
+        event.context.r14 = uc->uc_mcontext.mc_r14;
+        event.context.r15 = uc->uc_mcontext.mc_r15;
+        event.context.rdi = uc->uc_mcontext.mc_rdi;
+        event.context.rsi = uc->uc_mcontext.mc_rsi;
+        event.context.rbp = uc->uc_mcontext.mc_rbp;
+        event.context.rbx = uc->uc_mcontext.mc_rbx;
+        event.context.rdx = uc->uc_mcontext.mc_rdx;
+        event.context.rax = uc->uc_mcontext.mc_rax;
+        event.context.rcx = uc->uc_mcontext.mc_rcx;
+        event.context.rsp = uc->uc_mcontext.mc_rsp;
+        event.context.rip = uc->uc_mcontext.mc_rip;
+        event.context.efl = uc->uc_mcontext.mc_flags;
+        event.context.err = uc->uc_mcontext.mc_err;
+        event.context.trapno = uc->uc_mcontext.mc_trapno;
+        event.context.csgsfs  = 0;
+        event.context.oldmask = 0;
+        event.context.cr2     = 0;
+    }
+
+    if (frame) {
+        event.context.r15 = frame->arch.r15;
+        event.context.r14 = frame->arch.r14;
+        event.context.r13 = frame->arch.r13;
+        event.context.r12 = frame->arch.r12;
+        event.context.rdi = frame->arch.rdi;
+        event.context.rsi = frame->arch.rsi;
+        event.context.rbx = frame->arch.rbx;
+        /* find last frame */
+        event.context.rsp = frame->arch.rbp + sizeof(unsigned long) * 2;
+        event.context.rbp = ((unsigned long *) frame->arch.rbp)[0];
+        event.context.rip = ((unsigned long *) frame->arch.rbp)[1];
+        /* making rax = 0 to tell the caller that this PAL call failed */
+        event.context.rax = 0;
+    }
+
+    event.uc = uc;
+    event.eframe = eframe;
+
+    (*upcall) ((PAL_PTR) &event, arg, &event.context);
+}
+
+static bool _DkGenericSignalHandle (int event_num, siginfo_t * info,
+                                    struct pal_frame * frame,
+                                    ucontext_t * uc, void * eframe)
+{
+    PAL_EVENT_HANDLER upcall = _DkGetExceptionHandler(event_num);
+
+    if (upcall) {
+        PAL_NUM arg = 0;
+
+        if (event_num == PAL_EVENT_DIVZERO ||
+            event_num == PAL_EVENT_MEMFAULT ||
+            event_num == PAL_EVENT_ILLEGAL)
+            arg = (PAL_NUM) (info ? info->si_addr : 0);
+
+        _DkGenericEventTrigger(event_num, upcall, arg, frame, uc, eframe);
+        return true;
+    }
+
+    return false;
+}
+
+#define ADDR_IN_PAL(addr) \
+        ((void *) (addr) > TEXT_START && (void *) (addr) < TEXT_END)
+
+/* This function walks the stack to find the PAL_FRAME
+ * that was saved upon entry to the PAL, if an exception/interrupt
+ * comes in during a PAL call.  This is needed to support the behavior that an
+ * exception in the PAL has Unix-style, EAGAIN semantics.
+ * 
+ * The PAL_FRAME is supposed to be in the first PAL frame, and we look for 
+ * it by matching a special magic number, that should only appear on the stack
+ * once.
+ * 
+ * If an exception comes in while we are not in the PAL, this PAL_FRAME won't
+ * exist, and it is ok to return NULL.
+ */
+static struct pal_frame * get_frame (ucontext_t * uc)
+{
+    unsigned long rip = uc->uc_mcontext.mc_rip;
+    unsigned long rbp = uc->uc_mcontext.mc_rbp;
+    unsigned long last_rbp = rbp - 64;
+
+    if (!ADDR_IN_PAL(rip))
+        return NULL;
+
+    while (ADDR_IN_PAL(((unsigned long *) rbp)[1])) {
+        last_rbp = rbp;
+        rbp = *(unsigned long *) rbp;
+    }
+
+    /* search frame record in the top frame of PAL */
+    for (unsigned long ptr = rbp - sizeof(unsigned long) ;
+         ptr > last_rbp ; ptr -= 8) {
+        struct pal_frame * frame = (struct pal_frame *) ptr;
+        if (frame->identifier == PAL_FRAME_IDENTIFIER)
+            return frame;
+    }
+
+    return NULL;
+}
+
+static void return_frame (struct pal_frame * frame, int err)
+{
+    if (err)
+        _DkRaiseFailure(err);
+
+    __clear_frame(frame);
+    arch_restore_frame(&frame->arch);
+
+    asm volatile ("xor %rax, %rax\r\n"
+                  "leaveq\r\n"
+                  "retq\r\n");
+}
+
+#if BLOCK_SIGFAULT == 1
+static char exception_msg[24] = "--- SIGSEGV --- [     ]\n";
+static volatile bool cont_exec = false;
+#endif
+
+static void _DkGenericSighandler (int signum, siginfo_t * info,
+                                  struct ucontext * uc)
+{
+#if BLOCK_SIGFUALT == 1
+    /* reseurrect this code if signal handler if giving segmentation fault */
+    if (signum == SIGSEGV) {
+        int pid = INLINE_SYSCALL(getpid, 0);
+        exception_msg[17] = '0' + pid / 10000;
+        exception_msg[18] = '0' + (pid / 1000) % 10;
+        exception_msg[19] = '0' + (pid / 100) % 10;
+        exception_msg[20] = '0' + (pid / 10) % 10;
+        exception_msg[21] = '0' + pid % 10;
+        INLINE_SYSCALL(write, 3, 1, exception_msg, 24);
+        while(!cont_exec);
+    }
+#endif
+
+    struct pal_frame * frame = get_frame(uc);
+    void * eframe;
+
+    if (signum == SIGCONT && frame && frame->func == DkObjectsWaitAny)
+        return;
+
+    asm volatile ("movq %%rbp, %0" : "=r"(eframe));
+
+    if (frame && frame->func != &_DkGenericSighandler &&
+        signum != SIGCONT &&
+        signum != SIGINT  &&
+        signum != SIGTERM) {
+        return_frame(frame, PAL_ERROR_BADADDR);
+        return;
+    }
+
+    int event_num = get_event_num(signum);
+    if (event_num == -1)
+        return;
+
+    _DkGenericSignalHandle(event_num, info, frame, uc, eframe);
+}
+
+static void _DkTerminateSighandler (int signum, siginfo_t * info,
+                                    struct ucontext * uc)
+{
+    struct pal_frame * frame = get_frame(uc);
+    void * eframe;
+
+    asm volatile ("movq %%rbp, %0" : "=r"(eframe));
+
+    int event_num = get_event_num(signum);
+    if (event_num == -1)
+        return;
+
+    if (!_DkGenericSignalHandle(event_num, NULL, frame, uc, eframe))
+        _DkThreadExit();
+}
+
+static void _DkPipeSighandler (int signum, siginfo_t * info,
+                               struct ucontext * uc)
+{
+    return;
+}
+
+void _DkRaiseFailure (int error)
+{
+    PAL_EVENT_HANDLER upcall = _DkGetExceptionHandler(PAL_EVENT_FAILURE);
+
+    if (!upcall)
+        return;
+
+    PAL_EVENT event;
+    event.event_num = PAL_EVENT_FAILURE;
+    event.uc = NULL;
+    event.eframe = NULL;
+
+    (*upcall) ((PAL_PTR) &event, error, NULL);
+}
+
+struct signal_ops {
+    int signum[3];
+    void (*handler) (int signum, siginfo_t * info, ucontext_t * uc);
+};
+
+struct signal_ops on_signals[] = {
+        [PAL_EVENT_DIVZERO]     = { .signum = { SIGFPE, 0 },
+                                    .handler = _DkGenericSighandler },
+        [PAL_EVENT_MEMFAULT]    = { .signum = { SIGSEGV, SIGBUS, 0 },
+                                    .handler = _DkGenericSighandler },
+        [PAL_EVENT_ILLEGAL]     = { .signum = { SIGILL,  SIGSYS, 0 },
+                                    .handler = _DkGenericSighandler },
+        [PAL_EVENT_QUIT]        = { .signum = { SIGTERM, 0, 0 },
+                                    .handler = _DkTerminateSighandler },
+        [PAL_EVENT_SUSPEND]     = { .signum = { SIGINT, 0 },
+                                    .handler = _DkTerminateSighandler },
+        [PAL_EVENT_RESUME]      = { .signum = { SIGCONT, 0 },
+                                    .handler = _DkGenericSighandler },
+    };
+
+static int _DkPersistentSighandlerSetup (int event_num)
+{
+    int nsigs, * sigs = on_signals[event_num].signum;
+    for (nsigs = 0 ; sigs[nsigs] ; nsigs++);
+
+    int ret = set_sighandler(sigs, nsigs, on_signals[event_num].handler);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+void signal_setup (void)
+{
+    int ret, sig = SIGCHLD;
+
+#ifdef DEBUG
+    if (!linux_state.in_gdb)
+#endif
+        set_sighandler(&sig, 1, NULL);
+
+    sig = SIGPIPE;
+    if ((ret = set_sighandler(&sig, 1, &_DkPipeSighandler)) < 0)
+        goto err;
+
+    int events[] = {
+        PAL_EVENT_DIVZERO,
+        PAL_EVENT_MEMFAULT,
+        PAL_EVENT_ILLEGAL,
+        PAL_EVENT_QUIT,
+        PAL_EVENT_SUSPEND,
+        PAL_EVENT_RESUME,
+    };
+
+    for (int e = 0 ; e < sizeof(events) / sizeof(events[0]) ; e++)
+        if ((ret = _DkPersistentSighandlerSetup(events[e])) < 0)
+            goto err;
+
+    return;
+err:
+    init_fail(-ret, "cannot setup signal handlers");
+}
+
+void _DkExceptionReturn (void * event)
+{
+    PAL_EVENT * e = event;
+
+    if (e->eframe) {
+        struct pal_frame * frame = (struct pal_frame *) e->eframe;
+        int err = 0;
+
+        switch (e->event_num) {
+            case PAL_EVENT_MEMFAULT:
+                err = PAL_ERROR_BADADDR;
+                break;
+            case PAL_EVENT_QUIT:
+            case PAL_EVENT_SUSPEND:
+            case PAL_EVENT_RESUME:
+                err = PAL_ERROR_INTERRUPTED;
+                break;
+        }
+
+        if (err)
+            _DkRaiseFailure(err);
+
+        __clear_frame(frame);
+    }
+
+    if (e->uc) {
+        /* copy the context back to ucontext */
+        e->uc->uc_mcontext.mc_r8 = e->context.r8;
+        e->uc->uc_mcontext.mc_r9 = e->context.r9;
+        e->uc->uc_mcontext.mc_r10 = e->context.r10;
+        e->uc->uc_mcontext.mc_r11 = e->context.r11;
+        e->uc->uc_mcontext.mc_r12 = e->context.r12;
+        e->uc->uc_mcontext.mc_r13 = e->context.r13;
+        e->uc->uc_mcontext.mc_r14 = e->context.r14;
+        e->uc->uc_mcontext.mc_r15 = e->context.r15;
+        e->uc->uc_mcontext.mc_rdi = e->context.rdi;
+        e->uc->uc_mcontext.mc_rsi = e->context.rsi;
+        e->uc->uc_mcontext.mc_rbp = e->context.rbp;
+        e->uc->uc_mcontext.mc_rbx = e->context.rbx;
+        e->uc->uc_mcontext.mc_rdx = e->context.rdx;
+        e->uc->uc_mcontext.mc_rax = e->context.rax;
+        e->uc->uc_mcontext.mc_rcx = e->context.rcx;
+        e->uc->uc_mcontext.mc_rsp = e->context.rsp;
+        e->uc->uc_mcontext.mc_rip = e->context.rip;
+        e->uc->uc_mcontext.mc_flags = e->context.efl;
+        e->uc->uc_mcontext.mc_err = e->context.err;
+        e->uc->uc_mcontext.mc_trapno = e->context.trapno;
+
+        /* return to the frame of exception handler */
+        asm volatile ("movq %0, %%rbp\r\n"
+                      "leaveq\r\n"
+                      "retq\r\n" :: "r"(e->eframe) : "memory");
+    }
+}

+ 4 - 4
Pal/src/host/FreeBSD/db_files.c

@@ -58,7 +58,7 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri,
     int len = strlen(uri);
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(file) + len + 1);
     SET_HANDLE_TYPE(hdl, file);
-    hdl->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
+    hdl->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
     hdl->file.fd = ret;
     hdl->file.offset = 0;
     hdl->file.append = 0;
@@ -243,7 +243,7 @@ static int file_attrquery (const char * type, const char * uri,
 static int file_attrquerybyhdl (PAL_HANDLE handle,
                                 PAL_STREAM_ATTR * attr)
 {
-    int fd = handle->__in.fds[0];
+    int fd = handle->hdr.fds[0];
     struct stat stat_buf;
 
     int ret = INLINE_SYSCALL(fstat, 2, fd, &stat_buf);
@@ -258,7 +258,7 @@ static int file_attrquerybyhdl (PAL_HANDLE handle,
 static int file_attrsetbyhdl (PAL_HANDLE handle,
                               PAL_STREAM_ATTR * attr)
 {
-    int fd = handle->__in.fds[0], ret;
+    int fd = handle->hdr.fds[0], ret;
 
     ret = INLINE_SYSCALL(fchmod, 2, fd, attr->share_flags);
     if (IS_ERR(ret))
@@ -341,7 +341,7 @@ static int dir_open (PAL_HANDLE * handle, const char * type, const char * uri,
     int len = strlen(uri);
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(dir) + len + 1);
     SET_HANDLE_TYPE(hdl, dir);
-    hdl->__in.flags |= RFD(0);
+    hdl->hdr.flags |= RFD(0);
     hdl->dir.fd = ret;
     char * path = (void *) hdl + HANDLE_SIZE(dir);
     memcpy(path, uri, len + 1);

+ 9 - 59
Pal/src/host/FreeBSD/db_main.c

@@ -186,57 +186,6 @@ PAL_NUM _DkGetHostId (void)
     return 0;
 }
 
-int create_domain_dir (void)
-{
-    int ret = 0;
-    const char * path;
-
-    ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
-
-    if (IS_ERR(ret) && ERRNO(ret) != EEXIST) {
-        if (ERRNO(ret) == ENOENT) {
-            ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_TEMPDIR), 0777);
-            if (!IS_ERR(ret)) {
-                INLINE_SYSCALL(chmod, 2, GRAPHENE_TEMPDIR, 0777);
-                ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
-            }
-        }
-
-        if (IS_ERR(ret)) {
-            printf("Cannot create directory %s, please check permission\n",
-                   path);
-            return -PAL_ERROR_DENIED;
-        }
-    }
-
-    if (!IS_ERR(ret))
-        INLINE_SYSCALL(chmod, 2, GRAPHENE_PIPEDIR, 0777);
-
-    char * pipedir = __alloca(sizeof(GRAPHENE_PIPEDIR) + 10);
-    unsigned int id;
-
-    do {
-        if (!getrand(&id, sizeof(unsigned int))) {
-            printf("Unable to generate random numbers\n");
-            return -PAL_ERROR_DENIED;
-        }
-
-        snprintf(pipedir, sizeof(GRAPHENE_PIPEDIR) + 10,
-                 GRAPHENE_PIPEDIR "/%08x", id);
-
-        ret = INLINE_SYSCALL(mkdir, 2, pipedir, 0700);
-
-        if (IS_ERR(ret) && ERRNO(ret) != -EEXIST) {
-            printf("Cannot create directory %s, please fix permission\n",
-                   pipedir);
-            return -PAL_ERROR_DENIED;
-        }
-    } while (IS_ERR(ret));
-
-    pal_sec.domain_id = id;
-    return 0;
-}
-
 #include "dynamic_link.h"
 
 void setup_pal_map (struct link_map * map);
@@ -271,6 +220,9 @@ void pal_bsd_main (void * args)
     bsd_state.pid = INLINE_SYSCALL(getpid, 0);
     bsd_state.uid = uid;
     bsd_state.gid = gid;
+    
+    if (!bsd_state.parent_pid)
+        bsd_state.parent_pid = bsd_state.pid;
 
     PAL_HANDLE first_thread = malloc(HANDLE_SIZE(thread));
     SET_HANDLE_TYPE(first_thread, thread);
@@ -288,7 +240,7 @@ void pal_bsd_main (void * args)
     int len = strlen(argv[0]);
     PAL_HANDLE file = malloc(HANDLE_SIZE(file) + len + 1);
     SET_HANDLE_TYPE(file, file);
-    file->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
+    file->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
     file->file.fd = fd;
     char * path = (void *) file + HANDLE_SIZE(file);
     get_norm_path(argv[0], path, 0, len + 1);
@@ -302,17 +254,15 @@ void pal_bsd_main (void * args)
     manifest = file;
 
 done_init:
-    /* Create domain directory for pipes */
-    if(!pal_sec.domain_id){
-        if ((ret = create_domain_dir()) < 0)
-            init_fail(-ret, "cannot create pipe directory");
+    if (!parent && !exec && !manifest) {
+        printf("USAGE: %s [executable|manifest] args ...\n", pal_name);
+        _DkProcessExit(0);
+        return;
     }
-
     signal_setup();
 
     /* jump to main function */
-    pal_main(pal_sec.domain_id, (void *) pal_map.l_addr,
-             pal_name, argc, argv, envp, parent, first_thread, exec, manifest);
+    pal_main(bsd_state.parent_pid, manifest, exec, NULL, parent, first_thread, argv, envp);
 }
 
 /* the following code is borrowed from CPUID */

+ 3 - 3
Pal/src/host/FreeBSD/db_memory.c

@@ -40,7 +40,7 @@ bool _DkCheckMemoryMappable (const void * addr, int size)
 {
     return (addr <= DATA_END && addr + size >= TEXT_START);
 }
-int _DkVirtualMemoryAlloc (void ** paddr, int size, int alloc_type,
+int _DkVirtualMemoryAlloc (void ** paddr, uint64_t size, int alloc_type,
                            int prot)
 {
     void * addr = *paddr, * mem = addr;
@@ -59,14 +59,14 @@ int _DkVirtualMemoryAlloc (void ** paddr, int size, int alloc_type,
     return 0;
 }
 
-int _DkVirtualMemoryFree (void * addr, int size)
+int _DkVirtualMemoryFree (void * addr, uint64_t size)
 {
     int ret = INLINE_SYSCALL(munmap, 2, addr, size);
 
     return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
 }
 
-int _DkVirtualMemoryProtect (void * addr, int size, int prot)
+int _DkVirtualMemoryProtect (void * addr, uint64_t size, int prot)
 {
     int ret = INLINE_SYSCALL(mprotect, 3, addr, size, HOST_PROT(prot));
 

+ 8 - 1
Pal/src/host/FreeBSD/db_misc.c

@@ -200,7 +200,7 @@ static int init_randgen (void)
     return 0;
 }
 
-void getrand (void * buffer, size_t size)
+int getrand (void * buffer, size_t size)
 {
     unsigned long val;
     size_t bytes = 0;
@@ -228,4 +228,11 @@ void getrand (void * buffer, size_t size)
     _DkInternalLock(&lock);
     randval = val;
     _DkInternalUnlock(&lock);
+    return 0;
+}
+
+int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
+                      unsigned int values[4])
+{
+    return -PAL_ERROR_NOTIMPLEMENTED;
 }

+ 29 - 1
Pal/src/host/FreeBSD/db_mutex.c

@@ -35,7 +35,6 @@
 
 #include <limits.h>
 #include <atomic.h>
-#include <cmpxchg.h>
 #include <errno.h>
 #include <sys/time.h>
 #include <unistd.h>
@@ -203,3 +202,32 @@ int _DkMutexUnlock (struct mutex_handle * mut)
 out:
     return ret;
 }
+
+int _DkMutexAcquireTimeout (PAL_HANDLE handle, int timeout)
+{
+    return _DkMutexLockTimeout(&handle->mutex.mut, timeout);
+}
+
+
+void _DkMutexRelease (PAL_HANDLE handle)
+{
+    _DkMutexUnlock(&handle->mutex.mut);
+    return;
+}
+
+static int mutex_wait (PAL_HANDLE handle, uint64_t timeout)
+{
+    return _DkMutexAcquireTimeout(handle, timeout);
+}
+
+struct handle_ops mutex_ops = {
+        .wait               = &mutex_wait,
+};
+
+int _DkMutexCreate (PAL_HANDLE *handle, int count) {
+     PAL_HANDLE mut = malloc(HANDLE_SIZE(mutex));
+     SET_HANDLE_TYPE(mut, mutex);
+     atomic_set(&mut->mutex.mut.value, 0);
+     *handle = mut;
+     return 0;
+}

+ 23 - 24
Pal/src/host/FreeBSD/db_object.c

@@ -36,7 +36,6 @@
 #include <sys/poll.h>
 #include <sys/wait.h>
 #include <atomic.h>
-#include <cmpxchg.h>
 #include <errno.h>
 
 #define DEFAULT_QUANTUM 500
@@ -47,24 +46,24 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
 {
     /* only for all these handle which has a file descriptor, or
        a eventfd. events and semaphores will skip this part */
-    if (handle->__in.flags & HAS_FDS) {
+    if (handle->hdr.flags & HAS_FDS) {
         struct pollfd fds[MAX_FDS];
         int off[MAX_FDS];
         int nfds = 0;
         for (int i = 0 ; i < MAX_FDS ; i++) {
             int events = 0;
 
-            if ((handle->__in.flags & RFD(i)) &&
-                !(handle->__in.flags & ERROR(i)))
+            if ((handle->hdr.flags & RFD(i)) &&
+                !(handle->hdr.flags & ERROR(i)))
                 events |= POLLIN;
 
-            if ((handle->__in.flags & WFD(i)) &&
-                !(handle->__in.flags & WRITEABLE(i)) &&
-                !(handle->__in.flags & ERROR(i)))
+            if ((handle->hdr.flags & WFD(i)) &&
+                !(handle->hdr.flags & WRITEABLE(i)) &&
+                !(handle->hdr.flags & ERROR(i)))
                 events |= POLLOUT;
 
             if (events) {
-                fds[nfds].fd = handle->__in.fds[i];
+                fds[nfds].fd = handle->hdr.fds[i];
                 fds[nfds].events = events|POLLHUP|POLLERR;
                 fds[nfds].revents = 0;
                 off[nfds] = i;
@@ -93,9 +92,9 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
             if (!fds[i].revents)
                 continue;
             if (fds[i].revents & POLLOUT)
-                handle->__in.flags |= WRITEABLE(off[i]);
+                handle->hdr.flags |= WRITEABLE(off[i]);
             if (fds[i].revents & (POLLHUP|POLLERR))
-                handle->__in.flags |= ERROR(off[i]);
+                handle->hdr.flags |= ERROR(off[i]);
         }
 
         return 0;
@@ -111,7 +110,7 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout)
 
 /* _DkObjectsWaitAny for internal use. The function wait for any of the handle
    in the handle array. timeout can be set for the wait. */
-int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
+int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, uint64_t timeout,
                        PAL_HANDLE * polled)
 {
     if (count <= 0)
@@ -133,7 +132,7 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
         if (!hdl)
             continue;
 
-        if (!(hdl->__in.flags & HAS_FDS))
+        if (!(hdl->hdr.flags & HAS_FDS))
             return -PAL_ERROR_NOTSUPPORT;
 
         /* eliminate repeated entries */
@@ -142,7 +141,7 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
                 break;
         if (j == i) {
             for (j = 0 ; j < MAX_FDS ; j++)
-                if (hdl->__in.flags & (RFD(j)|WFD(j)))
+                if (hdl->hdr.flags & (RFD(j)|WFD(j)))
                     maxfds++;
         }
     }
@@ -165,17 +164,17 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
         for (j = 0 ; j < MAX_FDS ; j++) {
             int events = 0;
 
-            if ((hdl->__in.flags & RFD(j)) &&
-                !(hdl->__in.flags & ERROR(j)))
+            if ((hdl->hdr.flags & RFD(j)) &&
+                !(hdl->hdr.flags & ERROR(j)))
                 events |= POLLIN;
 
-            if ((hdl->__in.flags & WFD(j)) &&
-                !(hdl->__in.flags & WRITEABLE(j)) &&
-                !(hdl->__in.flags & ERROR(j)))
+            if ((hdl->hdr.flags & WFD(j)) &&
+                !(hdl->hdr.flags & WRITEABLE(j)) &&
+                !(hdl->hdr.flags & ERROR(j)))
                 events |= POLLOUT;
 
-            if (events && hdl->__in.fds[j] != PAL_IDX_POISON) {
-                fds[nfds].fd = hdl->__in.fds[j];
+            if (events && hdl->hdr.fds[j] != PAL_IDX_POISON) {
+                fds[nfds].fd = hdl->hdr.fds[j];
                 fds[nfds].events = events|POLLHUP|POLLERR;
                 fds[nfds].revents = 0;
                 hdls[nfds] = hdl;
@@ -216,17 +215,17 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout,
         }
 
         for (j = 0 ; j < MAX_FDS ; j++)
-            if ((hdl->__in.flags & (RFD(j)|WFD(j))) &&
-                hdl->__in.fds[j] == fds[i].fd)
+            if ((hdl->hdr.flags & (RFD(j)|WFD(j))) &&
+                hdl->hdr.fds[j] == fds[i].fd)
                 break;
 
         if (j == MAX_FDS)
             continue;
 
         if (fds[i].revents & POLLOUT)
-            hdl->__in.flags |= WRITEABLE(j);
+            hdl->hdr.flags |= WRITEABLE(j);
         if (fds[i].revents & (POLLHUP|POLLERR))
-            hdl->__in.flags |= ERROR(j);
+            hdl->hdr.flags |= ERROR(j);
     }
 
     *polled = polled_hdl;

+ 18 - 18
Pal/src/host/FreeBSD/db_pipes.c

@@ -102,7 +102,7 @@ static int pipe_listen (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
 
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
     SET_HANDLE_TYPE(hdl, pipesrv);
-    hdl->__in.flags |= RFD(0);
+    hdl->hdr.flags |= RFD(0);
     hdl->pipe.fd = fd;
     hdl->pipe.pipeid = pipeid;
     hdl->pipe.nonblocking = options & O_NONBLOCK ?
@@ -160,14 +160,14 @@ static int pipe_waitforclient (PAL_HANDLE handle, PAL_HANDLE * client)
 
     PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipeprv));
     SET_HANDLE_TYPE(clnt, pipeprv);
-    clnt->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
+    clnt->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
     clnt->pipeprv.fds[0] = pipes[0];
     clnt->pipeprv.fds[1] = pipes[1];
     *client = clnt;
 #else
     PAL_HANDLE clnt = malloc(HANDLE_SIZE(pipe));
     SET_HANDLE_TYPE(clnt, pipecli);
-    clnt->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
+    clnt->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
     clnt->pipe.fd = newfd;
     clnt->pipe.nonblocking = PAL_FALSE;
     clnt->pipe.pipeid = handle->pipe.pipeid;
@@ -254,7 +254,7 @@ static int pipe_connect (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
 
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
     SET_HANDLE_TYPE(hdl, pipeprv);
-    hdl->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
+    hdl->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
     hdl->pipeprv.fds[0] = pipes[0];
     hdl->pipeprv.fds[1] = pipes[1];
     hdl->pipeprv.nonblocking = (options & O_NONBLOCK) ?
@@ -262,7 +262,7 @@ static int pipe_connect (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
 #else
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
     SET_HANDLE_TYPE(hdl, pipe);
-    hdl->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
+    hdl->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
     hdl->pipe.fd = fd;
     hdl->pipe.pipeid = pipeid;
     hdl->pipe.nonblocking = (options & O_NONBLOCK) ?
@@ -290,7 +290,7 @@ static int pipe_private (PAL_HANDLE * handle, int options)
 
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
     SET_HANDLE_TYPE(hdl, pipeprv);
-    hdl->__in.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
+    hdl->hdr.flags |= RFD(0)|WFD(1)|WRITEABLE(1);
     hdl->pipeprv.fds[0] = fds[0];
     hdl->pipeprv.fds[1] = fds[1];
     hdl->pipeprv.nonblocking = (options & O_NONBLOCK) ?
@@ -420,7 +420,7 @@ static int pipe_write (PAL_HANDLE handle, int offset, int len,
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
             case EWOULDBLOCK:
-                handle->__in.flags &= ~writeable;
+                handle->hdr.flags &= ~writeable;
                 return-PAL_ERROR_TRYAGAIN;
             case EINTR:
                 return -PAL_ERROR_INTERRUPTED;
@@ -429,9 +429,9 @@ static int pipe_write (PAL_HANDLE handle, int offset, int len,
         }
 
     if (bytes == len)
-        handle->__in.flags |= writeable;
+        handle->hdr.flags |= writeable;
     else
-        handle->__in.flags &= ~writeable;
+        handle->hdr.flags &= ~writeable;
 
     return bytes;
 }
@@ -518,38 +518,38 @@ static int pipe_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
     int ret, val;
 
-    if (handle->__in.fds[0] == PAL_IDX_POISON)
+    if (handle->hdr.fds[0] == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
-    ret = INLINE_SYSCALL(ioctl, 3, handle->__in.fds[0], FIONREAD, &val);
+    ret = INLINE_SYSCALL(ioctl, 3, handle->hdr.fds[0], FIONREAD, &val);
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
     attr->handle_type  = pal_type_pipe;
-    attr->disconnected = handle->__in.flags & ERROR(0);
-    attr->nonblocking  = (handle->__in.type == pal_type_pipeprv) ?
+    attr->disconnected = handle->hdr.flags & ERROR(0);
+    attr->nonblocking  = (handle->hdr.type == pal_type_pipeprv) ?
                          handle->pipeprv.nonblocking : handle->pipe.nonblocking;
     attr->readable     = val > 0;
     if (PAL_GET_TYPE(handle) == pal_type_pipeprv)
-        attr->writeable = handle->__in.flags & WRITEABLE(1);
+        attr->writeable = handle->hdr.flags & WRITEABLE(1);
     else
-        attr->writeable = handle->__in.flags & WRITEABLE(0);
+        attr->writeable = handle->hdr.flags & WRITEABLE(0);
     attr->pending_size = val;
     return 0;
 }
 
 static int pipe_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
-    if (handle->__in.fds[0] == PAL_IDX_POISON)
+    if (handle->hdr.fds[0] == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
     int ret;
-    PAL_BOL * nonblocking = (handle->__in.type == pal_type_pipeprv) ?
+    PAL_BOL * nonblocking = (handle->hdr.type == pal_type_pipeprv) ?
                             &handle->pipeprv.nonblocking :
                             &handle->pipe.nonblocking;
 
     if (attr->nonblocking != *nonblocking) {
-        ret = INLINE_SYSCALL(fcntl, 3, handle->__in.fds[0], F_SETFL,
+        ret = INLINE_SYSCALL(fcntl, 3, handle->hdr.fds[0], F_SETFL,
                              *nonblocking ? O_NONBLOCK : 0);
 
         if (IS_ERR(ret))

+ 13 - 7
Pal/src/host/FreeBSD/db_process.c

@@ -79,7 +79,7 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(phdl, process);
-    phdl->__in.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
+    phdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
     phdl->process.stream_in   = proc_fds[0][0];
     phdl->process.stream_out  = proc_fds[0][1];
     phdl->process.cargo       = proc_fds[0][2];
@@ -93,7 +93,7 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(chdl, process);
-    chdl->__in.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
+    chdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITEABLE(1)|WRITEABLE(2);
     chdl->process.stream_in   = proc_fds[1][0];
     chdl->process.stream_out  = proc_fds[1][1];
     chdl->process.cargo       = proc_fds[1][2];
@@ -124,6 +124,7 @@ struct proc_param {
 };
 
 struct proc_args {
+    PAL_NUM parent_process_id;
     struct pal_sec  pal_sec;
     unsigned long   memory_quota;
     unsigned int    parent_data_size;
@@ -220,6 +221,7 @@ int _DkProcessCreate (PAL_HANDLE * handle,
     struct proc_args * proc_args =
             __alloca(sizeof(struct proc_args) + datasz);
 
+    proc_args->parent_process_id = bsd_state.parent_pid;
     memcpy(&proc_args->pal_sec, &pal_sec, sizeof(struct pal_sec));
     proc_args->pal_sec.r_debug_state = NULL;
     proc_args->pal_sec.r_debug = NULL;
@@ -391,6 +393,10 @@ void _DkProcessExit (int exitcode)
 
 int _DkProcessSandboxCreate (const char * manifest, int flags)
 {
+    PAL_HANDLE handle = NULL;
+    _DkStreamOpen(&handle, manifest, PAL_ACCESS_RDONLY, 0, 0, 0);
+    pal_state.manifest_handle = handle;
+    pal_state.manifest = manifest;
     return -PAL_ERROR_NOTIMPLEMENTED;
 }
 
@@ -422,7 +428,7 @@ static int proc_write (PAL_HANDLE handle, int offset, int count,
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
             case EWOULDBLOCK:
-                handle->__in.flags &= ~WRITEABLE(1);
+                handle->hdr.flags &= ~WRITEABLE(1);
                 return-PAL_ERROR_TRYAGAIN;
             case EINTR:
                 return -PAL_ERROR_INTERRUPTED;
@@ -431,9 +437,9 @@ static int proc_write (PAL_HANDLE handle, int offset, int count,
         }
 
     if (bytes == count)
-        handle->__in.flags |= WRITEABLE(1);
+        handle->hdr.flags |= WRITEABLE(1);
     else
-        handle->__in.flags &= ~WRITEABLE(1);
+        handle->hdr.flags &= ~WRITEABLE(1);
 
     return bytes;
 }
@@ -506,9 +512,9 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 
     attr->handle_type  = pal_type_process;
     attr->nonblocking  = handle->process.nonblocking;
-    attr->disconnected = handle->__in.flags & (ERROR(0)|ERROR(1));
+    attr->disconnected = handle->hdr.flags & (ERROR(0)|ERROR(1));
     attr->readable     = !!val;
-    attr->writeable    = handle->__in.flags & WRITEABLE(1);
+    attr->writeable    = handle->hdr.flags & WRITEABLE(1);
     attr->runnable     = PAL_FALSE;
     attr->pending_size = val;
 

+ 1 - 1
Pal/src/host/FreeBSD/db_rtld.c

@@ -39,7 +39,7 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
+#include <dlfcn.h>
 
 #include "elf-x86_64.h"
 

+ 0 - 264
Pal/src/host/FreeBSD/db_semaphore.c

@@ -1,264 +0,0 @@
-/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
-/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
-
-/* Copyright (C) 2014 Stony Brook University
-   This file is part of Graphene Library OS.
-
-   Graphene Library OS is free software: you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public License
-   as published by the Free Software Foundation, either version 3 of the
-   License, or (at your option) any later version.
-
-   Graphene Library OS is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/*
- * db_semaphore.c
- *
- * This file contains APIs that provides operations of semaphores.
- */
-
-#include "pal_defs.h"
-#include "pal_freebsd_defs.h"
-#include "pal.h"
-#include "pal_internal.h"
-#include "pal_freebsd.h"
-#include "pal_error.h"
-#include "api.h"
-
-#include <cmpxchg.h>
-#include <atomic.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/time.h>
-
-static inline int atomic_dec_if_positive (struct atomic_int *v)
-{
-    int c, old, dec;
-    c = atomic_read(v);
-    for (;;) {
-        dec = c - 1;
-        if (unlikely(dec < 0))
-            break;
-        old = atomic_cmpxchg((v), c, dec);
-        if (likely(old == c))
-            break;
-        c = old;
-    }
-    return dec;
-}
-
-int _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount)
-{
-    /*
-     * 1. Allocate memory for db_sem (this includes a futex variable).
-     * 2. Pack it into a PAL_HANDLE
-     * 3. Set the semaphore object with the argument values (count, maxCount)
-     */
-
-    SET_HANDLE_TYPE(handle, semaphore);
-    atomic_set(&handle->semaphore.nwaiters, 0);
-    handle->semaphore.max_value = maxCount;
-
-    /* optimization: if maxCount == 1, we make it into mutex */
-    if (handle->semaphore.max_value == 1) {
-        atomic_set(&handle->semaphore.value.mut.value, 1 - initialCount);
-    } else {
-        atomic_set(&handle->semaphore.value.i, maxCount - initialCount);
-    }
-
-    return 0;
-}
-
-void _DkSemaphoreDestroy (PAL_HANDLE semaphoreHandle)
-{
-    free(semaphoreHandle);
-}
-
-int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout);
-
-int _DkSemaphoreAcquire (PAL_HANDLE sem, int count)
-{
-    /* optimization: use it as a mutex */
-    if (sem->semaphore.max_value == 1) {
-        struct mutex_handle * mut = &sem->semaphore.value.mut;
-        _DkMutexLock(mut);
-        return 0;
-    }
-
-    if (count > sem->semaphore.max_value)
-        return -PAL_ERROR_INVAL;
-
-    struct atomic_int * value = &sem->semaphore.value.i;
-    int c = 0;
-
-    if (!value)
-        return -PAL_ERROR_BADHANDLE;
-
-    if (count == 1)
-        c = atomic_dec_and_test_nonnegative (value);
-    else
-        c = atomic_sub_and_test_nonnegative (count, value);
-
-    if (c)
-        return 0;
-
-    /* We didn't get the lock.  Bump the count back up. */
-    if (count == 1)
-        atomic_inc (value);
-    else
-        atomic_add (count, value);
-
-    int ret = 0;
-    atomic_inc (&sem->semaphore.nwaiters);
-    
-        while (1) {
-        ret = INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAIT, 0,
-                             NULL, NULL);
-
-        if (IS_ERR(ret)) {
-            if (ERRNO(ret) == EWOULDBLOCK) {
-                ret = 0;
-            } else {
-                ret = unix_to_pal_error(ERRNO(ret));
-                break;
-            }
-        }
-
-        if (count == 1)
-            c = atomic_dec_and_test_nonnegative (value);
-        else
-            c = atomic_sub_and_test_nonnegative (count, value);
-
-        if (c)
-            break;
-
-        /* We didn't get the lock.  Bump the count back up. */
-        if (count == 1)
-            atomic_inc (value);
-        else
-            atomic_add (count, value);
-    }
-
-    atomic_dec (&sem->semaphore.nwaiters);
-    return ret;
-}
-
-int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout)
-{
-    /* Pass it up to the no-timeout version if no timeout requested */
-    if (timeout == -1)
-        return _DkSemaphoreAcquire(sem, count);
-
-    /* optimization: use it as a mutex */
-    if (sem->semaphore.max_value == 1) {
-        struct mutex_handle * mut = & sem->semaphore.value.mut;
-        _DkMutexLockTimeout(mut, timeout);
-        return 0;
-    }
-
-    if (count > sem->semaphore.max_value)
-        return -PAL_ERROR_INVAL;
-
-    struct atomic_int * value = &sem->semaphore.value.i;
-    int c = 0;
-
-    if (!value)
-        return -PAL_ERROR_BADHANDLE;
-
-    if (count == 1)
-        c = atomic_dec_and_test_nonnegative (value);
-    else
-        c = atomic_sub_and_test_nonnegative (count, value);
-
-    if (c)
-        return 0;
-
-    /* We didn't get the lock.  Bump the count back up. */
-    if (count == 1)
-        atomic_inc (value);
-    else
-        atomic_add (count, value);
-
-    if (!timeout)
-        return 0;
-
-    struct timespec waittime;
-    long sec = timeout / 1000000;
-    long microsec = timeout - (sec * 1000000);
-    waittime.tv_sec = sec;
-    waittime.tv_nsec = microsec * 1000;
-    int ret = 0;
-    atomic_inc (&sem->semaphore.nwaiters);
-
-    while (1) {
-        ret = INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAIT_UINT, 0,
-                             NULL, &waittime);
-
-        if (ERRNO(ret) == EWOULDBLOCK) {
-            ret = 0;
-        } else {
-            ret = unix_to_pal_error(ERRNO(ret));
-            break;
-        }
-
-        if (count == 1)
-            c = atomic_dec_and_test_nonnegative (value);
-        else
-            c = atomic_sub_and_test_nonnegative (count, value);
-
-        if (c)
-            break;
-    }
-
-    /* We didn't get the lock.  Bump the count back up. */
-    if (count == 1)
-        atomic_inc (value);
-    else
-        atomic_add (count, value);
-
-    atomic_dec (&sem->semaphore.nwaiters);
-    return ret;
-}
-
-void _DkSemaphoreRelease (PAL_HANDLE sem, int count)
-{
-    /* optimization: use it as a mutex */
-    if (sem->semaphore.max_value == 1) {
-        struct mutex_handle * mut =
-            &sem->semaphore.value.mut;
-
-        _DkMutexUnlock(mut);
-        return;
-    }
-
-    struct atomic_int * value = &sem->semaphore.value.i;
-
-    if (count == 1)
-        atomic_inc (value);
-    else
-        atomic_add (count, value);
-
-    int nwaiters = atomic_read (&sem->semaphore.nwaiters);
-
-    if (nwaiters > 0)
-        INLINE_SYSCALL(_umtx_op, 5, value, UMTX_OP_WAKE,
-                       nwaiters, NULL, NULL);
-}
-
-int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem)
-{
-    if (sem->semaphore.max_value == 1) {
-        struct mutex_handle * mut =
-            &sem->semaphore.value.mut;
-        return atomic_read(&mut->value);
-    }
-
-    int c = atomic_read(&sem->semaphore.value.i);
-    return sem->semaphore.max_value - c;
-}

+ 24 - 20
Pal/src/host/FreeBSD/db_sockets.c

@@ -45,6 +45,10 @@ typedef __kernel_pid_t pid_t;
 #include <errno.h>
 #include <sys/filio.h>
 
+/* FreeBSD doesn't have addr_check_any. */
+#undef ALLOW_BIND_ANY
+#define ALLOW_BIND_ANY 1
+
 /* 96 bytes is the minimal size of buffer to store a IPv4/IPv6
    address */
 #define PAL_SOCKADDR_SIZE   96
@@ -233,7 +237,7 @@ PAL_HANDLE socket_create_handle (int type, int fd, int options,
 
     memset(hdl, 0, sizeof(union pal_handle));
     PAL_GET_TYPE(hdl) = type;
-    hdl->__in.flags |= RFD(0)|(type != pal_type_tcpsrv ? WFD(0) : 0);
+    hdl->hdr.flags |= RFD(0)|(type != pal_type_tcpsrv ? WFD(0) : 0);
     hdl->sock.fd = fd;
     void * addr = (void *) hdl + HANDLE_SIZE(sock);
     if (bind_addr) {
@@ -351,7 +355,7 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
     options = HOST_SOCKET_OPTIONS(options);
     /* the socket need to have a binding address, a null address or an
        any address is not allowed */
-    if (!bind_addr || addr_check_any(bind_addr) == 0)
+    if (!bind_addr == 0)
         return -PAL_ERROR_INVAL;
 
     fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family,
@@ -619,16 +623,16 @@ static int tcp_write (PAL_HANDLE handle, int offset, int len, const void * buf)
             case EPIPE:
                 return -PAL_ERROR_CONNFAILED;
             case EWOULDBLOCK:
-                handle->__in.flags &= ~WRITEABLE(0);
+                handle->hdr.flags &= ~WRITEABLE(0);
                 return -PAL_ERROR_TRYAGAIN;
             default:
                 return unix_to_pal_error(ERRNO(bytes));
         }
 
     if (bytes == len)
-        handle->__in.flags |= WRITEABLE(0);
+        handle->hdr.flags |= WRITEABLE(0);
     else
-        handle->__in.flags &= ~WRITEABLE(0);
+        handle->hdr.flags &= ~WRITEABLE(0);
 
     return bytes;
 }
@@ -882,7 +886,7 @@ static int udp_send (PAL_HANDLE handle, int offset, int len, const void * buf)
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
             case EAGAIN:
-                handle->__in.flags &= ~WRITEABLE(0);
+                handle->hdr.flags &= ~WRITEABLE(0);
                 return -PAL_ERROR_TRYAGAIN;
             case ECONNRESET:
             case EPIPE:
@@ -892,9 +896,9 @@ static int udp_send (PAL_HANDLE handle, int offset, int len, const void * buf)
         }
 
     if (bytes == len)
-        handle->__in.flags |= WRITEABLE(0);
+        handle->hdr.flags |= WRITEABLE(0);
     else
-        handle->__in.flags &= ~WRITEABLE(0);
+        handle->hdr.flags &= ~WRITEABLE(0);
 
     return bytes;
 }
@@ -943,15 +947,15 @@ static int udp_sendbyaddr (PAL_HANDLE handle, int offset, int len,
             case EPIPE:
                 return -PAL_ERROR_CONNFAILED;
             case EAGAIN:
-                handle->__in.flags &= ~WRITEABLE(0);
+                handle->hdr.flags &= ~WRITEABLE(0);
             default:
                 return unix_to_pal_error(ERRNO(bytes));
         }
 
     if (bytes == len)
-        handle->__in.flags |= WRITEABLE(0);
+        handle->hdr.flags |= WRITEABLE(0);
     else
-        handle->__in.flags &= ~WRITEABLE(0);
+        handle->hdr.flags &= ~WRITEABLE(0);
 
     return bytes;
 }
@@ -1022,10 +1026,10 @@ static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR  * attr)
         attr->readable = !attr->disconnected;
     }
 
-    attr->handle_type           = handle->__in.type;
-    attr->disconnected          = handle->__in.flags & ERROR(0);
+    attr->handle_type           = handle->hdr.type;
+    attr->disconnected          = handle->hdr.flags & ERROR(0);
     attr->nonblocking           = handle->sock.nonblocking;
-    attr->writeable             = handle->__in.flags & WRITEABLE(0);
+    attr->writeable             = handle->hdr.flags & WRITEABLE(0);
     attr->socket.linger         = handle->sock.linger;
     attr->socket.receivebuf     = handle->sock.receivebuf;
     attr->socket.sendbuf        = handle->sock.sendbuf;
@@ -1275,7 +1279,7 @@ static int mcast_s (PAL_HANDLE handle, int port)
     if (IS_ERR(ret))
         return -PAL_ERROR_DENIED;
 
-    handle->__in.flags |= WFD(1)|WRITEABLE(1);
+    handle->hdr.flags |= WFD(1)|WRITEABLE(1);
     handle->mcast.srv = fd;
     return 0;
 }
@@ -1375,15 +1379,15 @@ static int mcast_send (PAL_HANDLE handle, int offset, int size,
             case EPIPE:
                 return -PAL_ERROR_CONNFAILED;
             case EAGAIN:
-                handle->__in.flags &= ~WRITEABLE(1);
+                handle->hdr.flags &= ~WRITEABLE(1);
             default:
                 return unix_to_pal_error(ERRNO(bytes));
         }
 
     if (bytes == size)
-        handle->__in.flags |= WRITEABLE(1);
+        handle->hdr.flags |= WRITEABLE(1);
     else
-        handle->__in.flags &= ~WRITEABLE(1);
+        handle->hdr.flags &= ~WRITEABLE(1);
 
     return bytes;
 }
@@ -1437,10 +1441,10 @@ static int mcast_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
         return unix_to_pal_error(ERRNO(ret));
 
     attr->handle_type  = pal_type_mcast;
-    attr->disconnected = handle->__in.flags & (ERROR(0)|ERROR(1));
+    attr->disconnected = handle->hdr.flags & (ERROR(0)|ERROR(1));
     attr->nonblocking  = handle->mcast.nonblocking;
     attr->readable     = !!val;
-    attr->writeable    = handle->__in.flags & WRITEABLE(1);
+    attr->writeable    = handle->hdr.flags & WRITEABLE(1);
     attr->runnable     = PAL_FALSE;
     attr->pending_size = val;
     return 0;

+ 7 - 7
Pal/src/host/FreeBSD/db_streams.c

@@ -73,10 +73,10 @@ out:
 int handle_set_cloexec (PAL_HANDLE handle, bool enable)
 {
     for (int i = 0 ; i < MAX_FDS ; i++)
-        if (handle->__in.flags & (RFD(i)|WFD(i))) {
+        if (handle->hdr.flags & (RFD(i)|WFD(i))) {
             long flags = enable ? FD_CLOEXEC : 0;
             int ret = INLINE_SYSCALL(fcntl, 3,
-                                     handle->__in.fds[i], F_SETFD,
+                                     handle->hdr.fds[i], F_SETFD,
                                      flags);
             if (IS_ERR(ret) && ERRNO(ret) != EBADF)
                 return -PAL_ERROR_DENIED;
@@ -87,7 +87,7 @@ int handle_set_cloexec (PAL_HANDLE handle, bool enable)
 
 /* _DkStreamUnmap for internal use. Unmap stream at certain memory address.
    The memory is unmapped as a whole.*/
-int _DkStreamUnmap (void * addr, int size)
+int _DkStreamUnmap (void * addr, uint64_t size)
 {
     /* Just let the kernel tell us if the mapping isn't good. */
     int ret = INLINE_SYSCALL(munmap, 2, addr, size);
@@ -289,9 +289,9 @@ int _DkSendHandle (PAL_HANDLE hdl, PAL_HANDLE cargo)
     int fds[MAX_FDS];
     int nfds = 0;
     for (int i = 0 ; i < MAX_FDS ; i++)
-        if (cargo->__in.flags & (RFD(i)|WFD(1))) {
+        if (cargo->hdr.flags & (RFD(i)|WFD(1))) {
             hdl_hdr.fds |= 1U << i;
-            fds[nfds++] = cargo->__in.fds[i];
+            fds[nfds++] = cargo->hdr.fds[i];
         }
     // ~ Initialize common parameter formessage passing
     // Channel between parent and child
@@ -434,9 +434,9 @@ int _DkReceiveHandle(PAL_HANDLE hdl, PAL_HANDLE * cargo)
     for (int i = 0 ; i < MAX_FDS ; i++)
         if (hdl_hdr.fds & (1U << i)) {
             if (n < total_fds) {
-                handle->__in.fds[i] = ((int *) CMSG_DATA(chdr))[n++];
+                handle->hdr.fds[i] = ((int *) CMSG_DATA(chdr))[n++];
             } else {
-                handle->__in.flags &= ~(RFD(i)|WFD(i));
+                handle->hdr.flags &= ~(RFD(i)|WFD(i));
             }
         }
 

+ 4 - 4
Pal/src/host/FreeBSD/pal_freebsd.h

@@ -47,7 +47,7 @@ typedef int __kernel_pid_t;
 #define ERRNO INTERNAL_SYSCALL_ERRNO
 #define ERRNO_P INTERNAL_SYSCALL_ERRNO_P
 
-int getrand (void * buffer, int size);
+int getrand (void * buffer, size_t size);
 
 struct timespec;
 struct timeval;
@@ -58,10 +58,10 @@ extern struct pal_bsd_state {
     /* credentails */
     unsigned int    pid;
     unsigned int    uid, gid;
-
+    unsigned int    parent_pid;
     /* currently enabled signals */
     _sigset_t       sigset;
-
+  
     unsigned long   memory_quota;
 } bsd_state;
 
@@ -99,7 +99,7 @@ extern struct pal_bsd_state {
 
 static inline int HOST_FLAGS (int alloc_type, int prot)
 {
-    return ((alloc_type & PAL_ALLOC_RESERVE) ? MAP_NORESERVE : 0) |
+    return 
            ((prot & PAL_PROT_WRITECOPY) ? MAP_PRIVATE : MAP_SHARED);
 }
 

+ 128 - 14
Pal/src/host/FreeBSD/pal_host.h

@@ -57,16 +57,20 @@ typedef union pal_handle
      * handle, also there is no need to allocate the internal
      * handles, so we hide the type name of these handles on purpose.
      */
+    struct {
+        PAL_HDR hdr;
+        struct mutex_handle mut;
+    } mutex;
 
     struct {
         PAL_IDX type;
         PAL_FLG flags;
         PAL_REF ref;
         PAL_IDX fds[];
-    } __in;
+    } hdr;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd;
         PAL_NUM offset;
         PAL_BOL append;
@@ -75,20 +79,20 @@ typedef union pal_handle
     } file;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd;
         PAL_NUM pipeid;
         PAL_BOL nonblocking;
     } pipe;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fds[2];
         PAL_BOL nonblocking;
     } pipeprv;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd_in, fd_out;
         PAL_IDX dev_type;
         PAL_BOL destroy;
@@ -96,7 +100,7 @@ typedef union pal_handle
     } dev;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd;
         PAL_STR realpath;
         PAL_PTR buf;
@@ -106,13 +110,13 @@ typedef union pal_handle
     } dir;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd;
         PAL_NUM token;
     } gipc;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX fd;
         PAL_PTR bind;
         PAL_PTR conn;
@@ -129,7 +133,7 @@ typedef union pal_handle
     } sock;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX stream_in, stream_out;
         PAL_IDX cargo;
         PAL_IDX pid;
@@ -137,7 +141,7 @@ typedef union pal_handle
     } process;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX cli;
         PAL_IDX srv;
         PAL_IDX port;
@@ -145,12 +149,12 @@ typedef union pal_handle
     } mcast;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         PAL_IDX tid;
     } thread;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         struct atomic_int nwaiters;
         PAL_NUM max_value;
         union {
@@ -160,7 +164,7 @@ typedef union pal_handle
     } semaphore;
 
     struct {
-        PAL_HDR __in;
+        PAL_HDR hdr;
         struct atomic_int signaled;
         struct atomic_int nwaiters;
         PAL_BOL isnotification;
@@ -174,5 +178,115 @@ typedef union pal_handle
 #define MAX_FDS         (3)
 #define HAS_FDS         (00077)
 
-#define HANDLE_TYPE(handle)  ((handle)->__in.type)
+#define HANDLE_TYPE(handle)  ((handle)->hdr.type)
+struct arch_frame {
+#ifdef __x86_64__
+    uint64_t rsp, rbp, rbx, rsi, rdi, r12, r13, r14, r15;
+#else
+# error "unsupported architecture"
+#endif
+};
+
+#ifdef __x86_64__
+# define store_register(reg, var)     \
+    asm volatile ("movq %%" #reg ", %0" : "=a" (var) :: "memory");
+
+# define store_register_in_frame(reg, f)     store_register(reg, (f)->reg)
+
+# define arch_store_frame(f)                     \
+    store_register_in_frame(rsp, f)              \
+    store_register_in_frame(rbp, f)              \
+    store_register_in_frame(rbx, f)              \
+    store_register_in_frame(rsi, f)              \
+    store_register_in_frame(rdi, f)              \
+    store_register_in_frame(r12, f)              \
+    store_register_in_frame(r13, f)              \
+    store_register_in_frame(r14, f)              \
+    store_register_in_frame(r15, f)
+
+# define restore_register(reg, var, clobber...)  \
+    asm volatile ("movq %0, %%" #reg :: "g" (var) : "memory", ##clobber);
+
+# define restore_register_in_frame(reg, f)       \
+    restore_register(reg, (f)->reg,              \
+                     "r15", "r14", "r13", "r12", "rdi", "rsi", "rbx")
+
+# define arch_restore_frame(f)                   \
+    restore_register_in_frame(r15, f)            \
+    restore_register_in_frame(r14, f)            \
+    restore_register_in_frame(r13, f)            \
+    restore_register_in_frame(r12, f)            \
+    restore_register_in_frame(rdi, f)            \
+    restore_register_in_frame(rsi, f)            \
+    restore_register_in_frame(rbx, f)            \
+    restore_register_in_frame(rbp, f)            \
+    restore_register_in_frame(rsp, f)
+#else /* __x86_64__ */
+# error "unsupported architecture"
+#endif
+
+#define PAL_FRAME_IDENTIFIER    (0xdeaddeadbeefbeef)
+
+struct pal_frame {
+    volatile uint64_t           identifier;
+    void *                      func;
+    const char *                funcname;
+    struct arch_frame           arch;
+};
+
+/* When a PAL call is issued, a special PAL_FRAME is placed on the stack.
+ * This stores both a magic identifier, debugging information, 
+ * as well as callee-saved state.  This is used as a way to deal
+ * with PAL-internal failures where the goal is to exit the PAL and return a
+ * failure.
+ * 
+ * Arguably, an alternative is to unwind the stack and handle error cases at
+ * each stage.  In general, this is probably more robust, but would take work
+ * in the short term.  The one exception where the current strategy is
+ * probably better is when the PAL gets in a state where the code is
+ * unrecoverable, but ideally, this shouldn't happen.
+ */
+
+/* DEP 12/25/17: This frame storage thing is important to mark volatile.
+ * The compiler should not optimize out any of these changes, and 
+ * because some accesses can happen during an exception, these are not
+ * visible to the compiler in an otherwise stack-local variable (so the
+ * compiler will try to optimize out these assignments.
+ */
+static inline
+void __store_frame (volatile struct pal_frame * frame,
+                    void * func, const char * funcname)
+{
+    arch_store_frame(&frame->arch)
+    frame->func = func;
+    frame->funcname = funcname;
+    asm volatile ("nop" ::: "memory");
+    frame->identifier = PAL_FRAME_IDENTIFIER;
+}
+
+#define ENTER_PAL_CALL(name)                \
+    struct pal_frame frame;                 \
+    __store_frame(&frame, &(name), #name)
+
+
+static inline
+void __clear_frame (volatile struct pal_frame * frame)
+{
+    if (frame->identifier == PAL_FRAME_IDENTIFIER) {
+        asm volatile ("nop" ::: "memory");
+        frame->identifier = 0;
+    }
+}
+
+#define LEAVE_PAL_CALL()                    \
+    do {                                    \
+        __clear_frame(&frame);              \
+    } while (0)
+
+#define LEAVE_PAL_CALL_RETURN(retval)       \
+    do {                                    \
+        __clear_frame(&frame);              \
+        return (retval);                    \
+} while (0)
+
 #endif /* PAL_HOST_H */