mirror of
https://github.com/clearlinux/graphene.git
synced 2026-09-06 05:41:37 +00:00
810 lines
26 KiB
C
810 lines
26 KiB
C
/* SPDX-License-Identifier: LGPL-3.0-or-later */
|
|
/* Copyright (C) 2014 Stony Brook University */
|
|
|
|
/*
|
|
* This file contains definition of PAL host ABI.
|
|
*/
|
|
|
|
#ifndef PAL_H
|
|
#define PAL_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdnoreturn.h>
|
|
|
|
#include "toml.h"
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
#include "cpu.h"
|
|
#endif
|
|
|
|
typedef uint64_t PAL_NUM; /*!< a number */
|
|
typedef const char* PAL_STR; /*!< a pointer to a C-string */
|
|
typedef void* PAL_PTR; /*!< a pointer to memory or buffer (something other than string) */
|
|
typedef uint32_t PAL_FLG; /*!< a set of flags */
|
|
typedef uint32_t PAL_IDX; /*!< an index */
|
|
|
|
/*!
|
|
* \brief a boolean value (either #PAL_TRUE or #PAL_FALSE)
|
|
*
|
|
* This data type is commonly used as the return value of
|
|
* a PAL API to determine whether the call succeeded
|
|
*/
|
|
typedef bool PAL_BOL;
|
|
|
|
/*!
|
|
* True value for #PAL_BOL.
|
|
*/
|
|
#define PAL_TRUE true
|
|
|
|
/*!
|
|
* False value for #PAL_BOL.
|
|
*/
|
|
#define PAL_FALSE false
|
|
|
|
/* Moved MAX_FDS from <host_kernel>/pal_host.h to here,
|
|
* since it is 3, across all host kernels. */
|
|
#define MAX_FDS 3
|
|
|
|
/* maximum length of pipe/FIFO name (should be less than Linux sockaddr_un.sun_path = 108) */
|
|
#define PIPE_NAME_MAX 96
|
|
|
|
#ifdef IN_PAL
|
|
#include "atomic.h"
|
|
typedef struct atomic_int PAL_REF;
|
|
|
|
typedef struct {
|
|
PAL_IDX type;
|
|
PAL_FLG flags;
|
|
} PAL_HDR;
|
|
|
|
#include "pal_host.h"
|
|
|
|
#ifndef HANDLE_HDR
|
|
#define HANDLE_HDR(handle) (&((handle)->hdr))
|
|
#endif
|
|
|
|
static inline void init_handle_hdr(PAL_HDR* hdr, int pal_type) {
|
|
hdr->type = pal_type;
|
|
hdr->flags = 0;
|
|
}
|
|
|
|
#define SET_HANDLE_TYPE(handle, t) init_handle_hdr(HANDLE_HDR(handle), pal_type_##t)
|
|
#define IS_HANDLE_TYPE(handle, t) (HANDLE_HDR(handle)->type == pal_type_##t)
|
|
|
|
#else
|
|
typedef union pal_handle {
|
|
struct {
|
|
PAL_IDX type;
|
|
/* the PAL-level reference counting is deprecated */
|
|
} hdr;
|
|
}* PAL_HANDLE;
|
|
|
|
#ifndef HANDLE_HDR
|
|
#define HANDLE_HDR(handle) (&((handle)->hdr))
|
|
#endif
|
|
|
|
#endif /* !IN_PAL */
|
|
|
|
#include "pal-arch.h"
|
|
|
|
/*! Log level */
|
|
enum {
|
|
PAL_LOG_NONE = 0,
|
|
PAL_LOG_ERROR = 1,
|
|
PAL_LOG_WARNING = 2,
|
|
PAL_LOG_DEBUG = 3,
|
|
PAL_LOG_TRACE = 4,
|
|
PAL_LOG_ALL = 5,
|
|
};
|
|
|
|
/********** PAL TYPE DEFINITIONS **********/
|
|
enum {
|
|
pal_type_file,
|
|
pal_type_pipe,
|
|
pal_type_pipesrv,
|
|
pal_type_pipecli,
|
|
pal_type_pipeprv,
|
|
pal_type_dev,
|
|
pal_type_dir,
|
|
pal_type_tcp,
|
|
pal_type_tcpsrv,
|
|
pal_type_udp,
|
|
pal_type_udpsrv,
|
|
pal_type_process,
|
|
pal_type_thread,
|
|
pal_type_mutex,
|
|
pal_type_event,
|
|
pal_type_eventfd,
|
|
PAL_HANDLE_TYPE_BOUND,
|
|
};
|
|
|
|
#define PAL_IDX_POISON ((PAL_IDX)-1) /* PAL identifier poison value */
|
|
#define PAL_GET_TYPE(h) (HANDLE_HDR(h)->type)
|
|
#define PAL_CHECK_TYPE(h, t) (PAL_GET_TYPE(h) == pal_type_##t)
|
|
#define UNKNOWN_HANDLE(handle) (PAL_GET_TYPE(handle) >= PAL_HANDLE_TYPE_BOUND)
|
|
|
|
typedef struct PAL_PTR_RANGE_ {
|
|
PAL_PTR start, end;
|
|
} PAL_PTR_RANGE;
|
|
|
|
typedef struct PAL_MEM_INFO_ {
|
|
PAL_NUM mem_total;
|
|
} PAL_MEM_INFO;
|
|
|
|
/********** PAL APIs **********/
|
|
typedef struct PAL_CONTROL_ {
|
|
PAL_STR host_type;
|
|
PAL_NUM process_id; /*!< An identifier of current picoprocess */
|
|
|
|
/*
|
|
* Handles and executables
|
|
*/
|
|
|
|
toml_table_t* manifest_root; /*!< program manifest */
|
|
PAL_STR executable; /*!< initial executable name. TODO: remove from PAL */
|
|
PAL_HANDLE parent_process; /*!< handle of parent process */
|
|
PAL_HANDLE first_thread; /*!< handle of first thread */
|
|
PAL_NUM log_level; /*!< what log messsages to enable */
|
|
|
|
/*
|
|
* Memory layout
|
|
*/
|
|
PAL_BOL disable_aslr; /*!< disable ASLR (may be necessary for restricted environments) */
|
|
PAL_PTR_RANGE user_address; /*!< The range of user addresses */
|
|
|
|
PAL_PTR_RANGE manifest_preload; /*!< manifest was preloaded here */
|
|
|
|
/*
|
|
* Host information
|
|
*/
|
|
|
|
/*!
|
|
* \brief Host allocation alignment.
|
|
*
|
|
* This currently is (and most likely will always be) indistinguishable from the page size,
|
|
* looking from the LibOS perspective. The two values can be different on the PAL level though,
|
|
* see e.g. SYSTEM_INFO::dwAllocationGranularity on Windows.
|
|
*/
|
|
PAL_NUM alloc_align;
|
|
|
|
PAL_CPU_INFO cpu_info; /*!< CPU information (only required ones) */
|
|
PAL_MEM_INFO mem_info; /*!< memory information (only required ones) */
|
|
PAL_TOPO_INFO topo_info; /*!< Topology information (only required ones) */
|
|
} PAL_CONTROL;
|
|
|
|
#define pal_control (*pal_control_addr())
|
|
PAL_CONTROL* pal_control_addr(void);
|
|
|
|
/*
|
|
* MEMORY ALLOCATION
|
|
*/
|
|
|
|
/*! Memory Allocation Flags */
|
|
enum PAL_ALLOC {
|
|
PAL_ALLOC_RESERVE = 0x1, /*!< Only reserve the memory */
|
|
PAL_ALLOC_INTERNAL = 0x2, /*!< Allocate for PAL (valid only if #IN_PAL) */
|
|
|
|
PAL_ALLOC_MASK = 0x3,
|
|
};
|
|
|
|
/*! Memory Protection Flags */
|
|
enum PAL_PROT {
|
|
PAL_PROT_NONE = 0x0,
|
|
PAL_PROT_READ = 0x1,
|
|
PAL_PROT_WRITE = 0x2,
|
|
PAL_PROT_EXEC = 0x4,
|
|
PAL_PROT_WRITECOPY = 0x8, /*!< Copy on write */
|
|
|
|
PAL_PROT_MASK = 0xF,
|
|
};
|
|
|
|
/*!
|
|
* \brief Allocate virtual memory for the library OS and zero it out.
|
|
*
|
|
* \param addr
|
|
* can be either `NULL` or any valid address aligned at the allocation alignment. When `addr` is
|
|
* non-NULL, the API will try to allocate the memory at the given address and potentially rewrite
|
|
* any memory previously allocated at the same address. Overwriting any part of PAL and host kernel
|
|
* is forbidden.
|
|
* \param size must be a positive number, aligned at the allocation alignment.
|
|
* \param alloc_type can be a combination of any of the #PAL_ALLOC flags
|
|
* \param prot can be a combination of the #PAL_PROT flags
|
|
*/
|
|
PAL_PTR DkVirtualMemoryAlloc(PAL_PTR addr, PAL_NUM size, PAL_FLG alloc_type, PAL_FLG prot);
|
|
|
|
/*!
|
|
* \brief This API deallocates a previously allocated memory mapping.
|
|
*
|
|
* \param addr the address
|
|
* \param size the size
|
|
*
|
|
* Both `addr` and `size` must be non-zero and aligned at the allocation alignment.
|
|
*/
|
|
void DkVirtualMemoryFree(PAL_PTR addr, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief Modify the permissions of a previously allocated memory mapping.
|
|
*
|
|
* \param addr the address
|
|
* \param size the size
|
|
* \param prot see #DkVirtualMemoryAlloc()
|
|
*
|
|
* Both `addr` and `size` must be non-zero and aligned at the allocation alignment.
|
|
*/
|
|
PAL_BOL DkVirtualMemoryProtect(PAL_PTR addr, PAL_NUM size, PAL_FLG prot);
|
|
|
|
/*
|
|
* PROCESS CREATION
|
|
*/
|
|
|
|
#define PAL_PROCESS_MASK 0x0
|
|
|
|
/*!
|
|
* \brief Create a new process to run a separate executable.
|
|
*
|
|
* \param exec_uri the URI of the executable to be loaded in the new process.
|
|
* \param args an array of strings -- the arguments to be passed to the new process.
|
|
*/
|
|
PAL_HANDLE DkProcessCreate(PAL_STR exec_uri, PAL_STR* args);
|
|
|
|
/*!
|
|
* \brief Terminate all threads in the process immediately.
|
|
*
|
|
* \param exitCode the exit value returned to the host.
|
|
*/
|
|
noreturn void DkProcessExit(PAL_NUM exitCode);
|
|
|
|
/*
|
|
* STREAMS
|
|
*/
|
|
|
|
/*! Stream Access Flags */
|
|
enum PAL_ACCESS {
|
|
PAL_ACCESS_RDONLY = 0,
|
|
PAL_ACCESS_WRONLY = 1,
|
|
PAL_ACCESS_RDWR = 2,
|
|
PAL_ACCESS_APPEND = 4,
|
|
PAL_ACCESS_MASK = 7,
|
|
};
|
|
|
|
/*! Stream Sharing Flags */
|
|
// FIXME: These flags currently must correspond 1-1 to Linux flags, which is totally unportable.
|
|
// They should be redesigned when we'll be rewriting the filesystem layer.
|
|
enum PAL_SHARE {
|
|
PAL_SHARE_GLOBAL_X = 01,
|
|
PAL_SHARE_GLOBAL_W = 02,
|
|
PAL_SHARE_GLOBAL_R = 04,
|
|
PAL_SHARE_GROUP_X = 010,
|
|
PAL_SHARE_GROUP_W = 020,
|
|
PAL_SHARE_GROUP_R = 040,
|
|
PAL_SHARE_OWNER_X = 0100,
|
|
PAL_SHARE_OWNER_W = 0200,
|
|
PAL_SHARE_OWNER_R = 0400,
|
|
PAL_SHARE_STICKY = 01000,
|
|
PAL_SHARE_SET_GID = 02000,
|
|
PAL_SHARE_SET_UID = 04000,
|
|
|
|
PAL_SHARE_MASK = 07777,
|
|
};
|
|
|
|
/*! Stream Create Flags */
|
|
enum PAL_CREATE {
|
|
PAL_CREATE_TRY = 1, /*!< Create file if file does not exist */
|
|
PAL_CREATE_ALWAYS = 2, /*!< Create file and fail if file already exists */
|
|
PAL_CREATE_DUALSTACK = 4, /*!< Create dual-stack socket (opposite of IPV6_V6ONLY) */
|
|
|
|
PAL_CREATE_MASK = 7,
|
|
};
|
|
|
|
/*! Stream Option Flags */
|
|
enum PAL_OPTION {
|
|
PAL_OPTION_CLOEXEC = 1,
|
|
PAL_OPTION_EFD_SEMAPHORE = 2, /*!< specific to `eventfd` syscall */
|
|
PAL_OPTION_NONBLOCK = 4,
|
|
|
|
PAL_OPTION_MASK = 7,
|
|
};
|
|
|
|
/*! error value of read/write */
|
|
#define PAL_STREAM_ERROR ((PAL_NUM)-1L)
|
|
|
|
#define WITHIN_MASK(val, mask) (((val) | (mask)) == (mask))
|
|
|
|
/*!
|
|
* \brief Open/create a stream resource specified by `uri`
|
|
*
|
|
* \param uri is the URI of the stream to be opened/created
|
|
* \param access can be a combination of the #PAL_ACCESS flags
|
|
* \param share_flags can be a combination of the #PAL_SHARE flags
|
|
* \param create can be a combination of the #PAL_CREATE flags
|
|
* \param options can be a combination of the #PAL_OPTION flags
|
|
*
|
|
* \return If the resource is successfully opened or created, a PAL handle will be returned for
|
|
* further access such as reading or writing.
|
|
*
|
|
* Supported URI types:
|
|
* * `%file:...`, `dir:...`: Files or directories on the host file system. If #PAL_CREATE_TRY is
|
|
* given in `create` flags, the file/directory will be created.
|
|
* * `dev:...`: Open a device as a stream. For example, `dev:tty` represents the standard I/O.
|
|
* * `pipe.srv:<name>`, `pipe:<name>`, `pipe:`: Open a byte stream that can be used for RPC between
|
|
* processes. The server side of a pipe can accept any number of connections. If `pipe:` is given
|
|
* as the URI (i.e., without a name), it will open an anonymous bidirectional pipe.
|
|
* * `tcp.srv:<ADDR>:<PORT>`, `tcp:<ADDR>:<PORT>`: Open a TCP socket to listen or connect to
|
|
* a remote TCP socket.
|
|
* * `udp.srv:<ADDR>:<PORT>`, `udp:<ADDR>:<PORT>`: Open a UDP socket to listen or connect to
|
|
* a remote UDP socket.
|
|
*/
|
|
PAL_HANDLE DkStreamOpen(PAL_STR uri, PAL_FLG access, PAL_FLG share_flags, PAL_FLG create,
|
|
PAL_FLG options);
|
|
|
|
/*!
|
|
* \brief Blocks until a new connection is accepted and returns the PAL handle for the connection.
|
|
*
|
|
* This API is only available for handles that are opened with `pipe.srv:...`, `tcp.srv:...`, and
|
|
* `udp.srv:...`.
|
|
*/
|
|
PAL_HANDLE DkStreamWaitForClient(PAL_HANDLE handle);
|
|
|
|
/*!
|
|
* \brief Read data from an open stream.
|
|
*
|
|
* If the handle is a file, `offset` must be specified at each call of DkStreamRead. `source` and
|
|
* `size` can be used to return the remote socket address if the handle is a UDP socket. If the
|
|
* handle is a directory, DkStreamRead fills the buffer with the names (NULL-ended) of the files or
|
|
* subdirectories inside of this directory.
|
|
*/
|
|
PAL_NUM DkStreamRead(PAL_HANDLE handle, PAL_NUM offset, PAL_NUM count, PAL_PTR buffer,
|
|
PAL_PTR source, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief Write data to an open stream.
|
|
*
|
|
* If the handle is a file, `offset` must be specified at each call of DkStreamWrite. `dest` can be
|
|
* used to specify the remote socket address if the handle is a UDP socket.
|
|
*
|
|
* \return number of bytes written if succeeded, PAL_STREAM_ERROR on failure (in which case
|
|
* PAL_ERRNO() is set)
|
|
*/
|
|
PAL_NUM DkStreamWrite(PAL_HANDLE handle, PAL_NUM offset, PAL_NUM count, PAL_PTR buffer,
|
|
PAL_STR dest);
|
|
|
|
enum PAL_DELETE {
|
|
PAL_DELETE_RD = 1, /*!< shut down the read side only */
|
|
PAL_DELETE_WR = 2, /*!< shut down the write side only */
|
|
};
|
|
|
|
/*!
|
|
* \brief Delete files or directories on the host or shut down the connection of TCP/UDP sockets.
|
|
*
|
|
* \param access which side to shut down (#PAL_DELETE), or both if 0 is given.
|
|
*/
|
|
void DkStreamDelete(PAL_HANDLE handle, PAL_FLG access);
|
|
|
|
/*!
|
|
* \brief Map a file to a virtual memory address in the current process.
|
|
*
|
|
* \param address can be NULL or a valid address that is aligned at the allocation alignment.
|
|
* \param prot see #DkVirtualMemoryAlloc()
|
|
*
|
|
* `offset` and `size` have to be non-zero and aligned at the allocation alignment
|
|
*/
|
|
PAL_PTR DkStreamMap(PAL_HANDLE handle, PAL_PTR address, PAL_FLG prot, PAL_NUM offset, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief Unmap virtual memory that is backed by a file stream.
|
|
*
|
|
* `addr` and `size` must be aligned at the allocation alignment
|
|
*/
|
|
void DkStreamUnmap(PAL_PTR addr, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief Set the length of the file referenced by handle to `length`.
|
|
*
|
|
* \return Returns the 0 on success, a _positive_ errno on failure.
|
|
*/
|
|
PAL_NUM DkStreamSetLength(PAL_HANDLE handle, PAL_NUM length);
|
|
|
|
/*!
|
|
* \brief Flush the buffer of a file stream.
|
|
*/
|
|
PAL_BOL DkStreamFlush(PAL_HANDLE handle);
|
|
|
|
/*!
|
|
* \brief Send a PAL handle over another handle.
|
|
*
|
|
* Currently, the handle that is used to send cargo must be a process handle.
|
|
*
|
|
* \param cargo the handle being sent
|
|
*/
|
|
PAL_BOL DkSendHandle(PAL_HANDLE handle, PAL_HANDLE cargo);
|
|
|
|
/*!
|
|
* \brief This API receives a handle over another handle.
|
|
*/
|
|
PAL_HANDLE DkReceiveHandle(PAL_HANDLE handle);
|
|
|
|
/* stream attribute structure */
|
|
typedef struct _PAL_STREAM_ATTR {
|
|
PAL_IDX handle_type;
|
|
PAL_BOL disconnected;
|
|
PAL_BOL nonblocking;
|
|
PAL_BOL readable, writable, runnable;
|
|
PAL_FLG share_flags;
|
|
PAL_NUM pending_size;
|
|
PAL_IDX no_of_fds;
|
|
PAL_IDX fds[MAX_FDS];
|
|
union {
|
|
struct {
|
|
PAL_NUM linger;
|
|
PAL_NUM receivebuf, sendbuf;
|
|
PAL_NUM receivetimeout, sendtimeout;
|
|
PAL_BOL tcp_cork;
|
|
PAL_BOL tcp_keepalive;
|
|
PAL_BOL tcp_nodelay;
|
|
} socket;
|
|
};
|
|
} PAL_STREAM_ATTR;
|
|
|
|
/*!
|
|
* \brief Query the attributes of a named stream.
|
|
*
|
|
* This API only applies for URIs such as `%file:...`, `dir:...`, and `dev:...`.
|
|
*/
|
|
PAL_BOL DkStreamAttributesQuery(PAL_STR uri, PAL_STREAM_ATTR* attr);
|
|
|
|
/*!
|
|
* \brief Query the attributes of an open stream.
|
|
*
|
|
* This API applies to any stream handle.
|
|
*/
|
|
PAL_BOL DkStreamAttributesQueryByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr);
|
|
|
|
/*!
|
|
* \brief Set the attributes of an open stream.
|
|
*/
|
|
PAL_BOL DkStreamAttributesSetByHandle(PAL_HANDLE handle, PAL_STREAM_ATTR* attr);
|
|
|
|
/*!
|
|
* \brief Query the name of an open stream.
|
|
*/
|
|
PAL_NUM DkStreamGetName(PAL_HANDLE handle, PAL_PTR buffer, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief This API changes the name of an open stream.
|
|
*/
|
|
PAL_BOL DkStreamChangeName(PAL_HANDLE handle, PAL_STR uri);
|
|
|
|
/*
|
|
* Thread creation
|
|
*/
|
|
|
|
#define PAL_THREAD_MASK 0
|
|
|
|
/*!
|
|
* \brief Create a thread in the current process.
|
|
*
|
|
* \param addr is the address of an entry point of execution for the new thread
|
|
* \param param is the pointer argument that is passed to the new thread
|
|
*/
|
|
PAL_HANDLE DkThreadCreate(PAL_PTR addr, PAL_PTR param);
|
|
|
|
/*!
|
|
* \brief Suspend the current thread for a certain duration
|
|
*
|
|
* \param duration the duration in microseconds
|
|
*/
|
|
PAL_NUM DkThreadDelayExecution(PAL_NUM duration);
|
|
|
|
/*!
|
|
* \brief Yield the current thread such that the host scheduler can reschedule it.
|
|
*/
|
|
void DkThreadYieldExecution(void);
|
|
|
|
/*!
|
|
* \brief Terminate the current thread.
|
|
*
|
|
* \param clear_child_tid is the pointer to memory that is erased on thread exit
|
|
* to notify LibOS (which in turn notifies the parent thread if any); if
|
|
* `clear_child_tid` is NULL, then PAL doesn't do the clearing.
|
|
*/
|
|
noreturn void DkThreadExit(PAL_PTR clear_child_tid);
|
|
|
|
/*!
|
|
* \brief Resume a thread.
|
|
*/
|
|
PAL_BOL DkThreadResume(PAL_HANDLE thread);
|
|
|
|
/*!
|
|
* \brief Sets the CPU affinity of a thread.
|
|
*
|
|
* All bit positions exceeding the count of host CPUs are ignored. Returns an error if no CPUs were
|
|
* selected.
|
|
*
|
|
* \param thread PAL thread for which to set the CPU affinity.
|
|
* \param cpumask_size size in bytes of the bitmask pointed by \a cpu_mask.
|
|
* \param cpu_mask pointer to the new CPU mask.
|
|
*
|
|
* \return Returns 1 on success, 0 on failure. Use PAL_ERRNO() to get the actual error code.
|
|
*/
|
|
PAL_BOL DkThreadSetCpuAffinity(PAL_HANDLE thread, PAL_NUM cpumask_size, PAL_PTR cpu_mask);
|
|
|
|
/*!
|
|
* \brief Gets the CPU affinity of a thread.
|
|
*
|
|
* This function assumes that \a cpumask_size is valid and greater than 0. Also, \a cpumask_size
|
|
* must be able to fit all the processors in the host and must be aligned by sizeof(long). For
|
|
* example, if the host supports 4 CPUs, \a cpumask_size should be 8 bytes.
|
|
*
|
|
* \param thread PAL thread for which to get the CPU affinity.
|
|
* \param cpumask_size size in bytes of the bitmask pointed by \a cpu_mask.
|
|
* \param cpu_mask pointer to hold the current CPU mask.
|
|
*
|
|
* \return Returns 1 on success, 0 on failure. Use PAL_ERRNO() to get the actual error code.
|
|
*/
|
|
PAL_BOL DkThreadGetCpuAffinity(PAL_HANDLE thread, PAL_NUM cpumask_size, PAL_PTR cpu_mask);
|
|
|
|
/*
|
|
* Exception Handling
|
|
*/
|
|
|
|
enum PAL_EVENT {
|
|
/*! arithmetic error (div-by-zero, floating point exception, etc.) */
|
|
PAL_EVENT_ARITHMETIC_ERROR = 1,
|
|
/*! segmentation fault, protection fault, bus fault */
|
|
PAL_EVENT_MEMFAULT,
|
|
/*! illegal instructions */
|
|
PAL_EVENT_ILLEGAL,
|
|
/*! terminated by external program (see "sys.enable_sigterm_injection" manifest option) */
|
|
PAL_EVENT_QUIT,
|
|
/*! interrupted (usually internally to handle aync event) */
|
|
PAL_EVENT_INTERRUPTED,
|
|
/*! failure within PAL calls */
|
|
PAL_EVENT_FAILURE,
|
|
|
|
PAL_EVENT_NUM_BOUND,
|
|
};
|
|
|
|
/*!
|
|
* \brief Type of exception handlers (upcalls).
|
|
*
|
|
* \param is_in_pal `true` if the exception happened inside PAL
|
|
* \param addr address of the exception (meaningful only for sync exceptions)
|
|
* \param context CPU context at the moment of exception.
|
|
*/
|
|
typedef void (*PAL_EVENT_HANDLER)(bool is_in_pal, PAL_NUM addr, PAL_CONTEXT* context);
|
|
|
|
/*!
|
|
* \brief Set the handler for the specific exception event.
|
|
*
|
|
* \param event can be one of #PAL_EVENT values
|
|
*/
|
|
PAL_BOL DkSetExceptionHandler(PAL_EVENT_HANDLER handler, PAL_NUM event);
|
|
|
|
/*
|
|
* Synchronization
|
|
*/
|
|
|
|
/*!
|
|
* \brief Create a mutex with the given `initialCount`.
|
|
*
|
|
* Destroy a mutex using DkObjectClose.
|
|
*
|
|
* \param initialCount 0 is unlocked, 1 is locked
|
|
*/
|
|
PAL_HANDLE DkMutexCreate(PAL_NUM initialCount);
|
|
|
|
/*!
|
|
* \brief Unlock the given mutex.
|
|
*/
|
|
void DkMutexRelease(PAL_HANDLE mutexHandle);
|
|
|
|
/*!
|
|
* \brief Creates a notification event with the given `initialState`.
|
|
*
|
|
* The definition of notification events is the same as the WIN32 API. When
|
|
* a notification event is set to the signaled state it remains in that state
|
|
* until it is explicitly cleared.
|
|
*/
|
|
PAL_HANDLE DkNotificationEventCreate(PAL_BOL initialState);
|
|
|
|
/*!
|
|
* \brief Creates a synchronization event with the given `initialState`.
|
|
*
|
|
* The definition of synchronization events is the same as the WIN32 API. When
|
|
* a synchronization event is set to the signaled state, a single thread of
|
|
* execution that was waiting for the event is released, and the event is
|
|
* automatically reset to the not-signaled state.
|
|
*/
|
|
PAL_HANDLE DkSynchronizationEventCreate(PAL_BOL initialState);
|
|
|
|
/*!
|
|
* \brief Set (signal) a notification event or a synchronization event.
|
|
*/
|
|
void DkEventSet(PAL_HANDLE eventHandle);
|
|
|
|
/*!
|
|
* \brief Clear a notification event or a synchronization event.
|
|
*/
|
|
void DkEventClear(PAL_HANDLE eventHandle);
|
|
|
|
/*! block until the handle's event is triggered */
|
|
#define NO_TIMEOUT ((PAL_NUM)-1)
|
|
|
|
/*!
|
|
* \brief Wait on a synchronization handle.
|
|
*
|
|
* \param timeout_us is the maximum time that the API should wait (in
|
|
* microseconds), or #NO_TIMEOUT to indicate it is to be blocked until the
|
|
* handle's event is triggered.
|
|
* \return true if this handle's event was triggered, false otherwise
|
|
*/
|
|
PAL_BOL DkSynchronizationObjectWait(PAL_HANDLE handle, PAL_NUM timeout_us);
|
|
|
|
enum PAL_WAIT {
|
|
PAL_WAIT_SIGNAL = 1, /*!< ignored in events */
|
|
PAL_WAIT_READ = 2,
|
|
PAL_WAIT_WRITE = 4,
|
|
PAL_WAIT_ERROR = 8, /*!< ignored in events */
|
|
};
|
|
|
|
/*!
|
|
* \brief Poll
|
|
*
|
|
* \param count the number of items in the array
|
|
* \param handle_array
|
|
* \param events user-defined events
|
|
* \param[out] ret_events polled-handles' events in `ret_events`
|
|
* \param timeout_us is the maximum time that the API should wait (in
|
|
* microseconds), or `NO_TIMEOUT` to indicate it is to be blocked until at
|
|
* least one handle is ready.
|
|
* \return true if there was an event on at least one handle, false otherwise
|
|
*/
|
|
PAL_BOL DkStreamsWaitEvents(PAL_NUM count, PAL_HANDLE* handle_array, PAL_FLG* events,
|
|
PAL_FLG* ret_events, PAL_NUM timeout_us);
|
|
|
|
/*!
|
|
* \brief Close (deallocate) a PAL handle.
|
|
*/
|
|
void DkObjectClose(PAL_HANDLE objectHandle);
|
|
|
|
/*
|
|
* MISC
|
|
*/
|
|
|
|
/*!
|
|
* \brief Output a message to the debug stream.
|
|
*
|
|
* \return number of bytes written if succeeded, PAL_STREAM_ERROR on failure (in which case
|
|
* PAL_ERRNO() is set)
|
|
*/
|
|
PAL_NUM DkDebugLog(PAL_PTR buffer, PAL_NUM size);
|
|
|
|
/*!
|
|
* \brief Get the current time
|
|
* \return the current time in microseconds
|
|
*/
|
|
PAL_NUM DkSystemTimeQuery(void);
|
|
|
|
/*!
|
|
* \brief Cryptographically secure random.
|
|
*
|
|
* \param[out] buffer is filled with cryptographically-secure random values
|
|
* \param[in] size buffer size
|
|
* \return 0 on success, negative on failure
|
|
*/
|
|
PAL_NUM DkRandomBitsRead(PAL_PTR buffer, PAL_NUM size);
|
|
|
|
enum PAL_SEGMENT {
|
|
PAL_SEGMENT_FS = 1,
|
|
PAL_SEGMENT_GS,
|
|
};
|
|
|
|
/*!
|
|
* \brief Get segment register
|
|
*
|
|
* \param reg the register to get (#PAL_SEGMENT)
|
|
* \param addr the address where result will be stored
|
|
*
|
|
* \return true on success, false on error
|
|
*/
|
|
PAL_BOL DkSegmentRegisterGet(PAL_FLG reg, PAL_PTR* addr);
|
|
|
|
/*!
|
|
* \brief Set segment register
|
|
*
|
|
* \param reg the register to be set (#PAL_SEGMENT)
|
|
* \param addr the address to be set
|
|
*
|
|
* \return true on success, false on error
|
|
*/
|
|
PAL_BOL DkSegmentRegisterSet(PAL_FLG reg, PAL_PTR addr);
|
|
|
|
/*!
|
|
* \brief Return the amount of currently available memory for LibOS/application
|
|
* usage.
|
|
*/
|
|
PAL_NUM DkMemoryAvailableQuota(void);
|
|
|
|
/*!
|
|
* \brief Obtain the attestation report (local) with `user_report_data` embedded into it.
|
|
*
|
|
* Currently works only for Linux-SGX PAL, where `user_report_data` is a blob of exactly 64B,
|
|
* `target_info` is an SGX target_info struct of exactly 512B, and `report` is an SGX report
|
|
* obtained via the EREPORT instruction (exactly 432B). If `target_info` contains all zeros,
|
|
* then this function additionally returns this enclave's target info in `target_info`. Useful
|
|
* for local attestation.
|
|
*
|
|
* The caller may specify `*user_report_data_size`, `*target_info_size`, and `*report_size` as 0
|
|
* and other fields as NULL to get PAL-enforced sizes of these three structs.
|
|
*
|
|
* \param[in] user_report_data Report data with arbitrary contents (typically uniquely
|
|
* identifies this Graphene instance). Must be a 64B buffer
|
|
* in case of SGX PAL.
|
|
* \param[in,out] user_report_data_size Caller specifies size of `user_report_data`; on return,
|
|
* contains PAL-enforced size of `user_report_data` (64B in
|
|
* case of SGX PAL).
|
|
* \param[in,out] target_info Target info of target enclave for attestation. If it
|
|
* contains all zeros, it is populated with this enclave's
|
|
* target info. Must be a 512B buffer in case of SGX PAL.
|
|
* \param[in,out] target_info_size Caller specifies size of `target_info`; on return,
|
|
* contains PAL-enforced size of `target_info` (512B in case
|
|
* of SGX PAL).
|
|
* \param[out] report Attestation report with `user_report_data` embedded,
|
|
* targeted for an enclave with provided `target_info`. Must
|
|
* be a 432B buffer in case of SGX PAL.
|
|
* \param[in,out] report_size Caller specifies size of `report`; on return, contains
|
|
* PAL-enforced size of `report` (432B in case of SGX PAL).
|
|
*/
|
|
PAL_BOL DkAttestationReport(PAL_PTR user_report_data, PAL_NUM* user_report_data_size,
|
|
PAL_PTR target_info, PAL_NUM* target_info_size, PAL_PTR report,
|
|
PAL_NUM* report_size);
|
|
|
|
/*!
|
|
* \brief Obtain the attestation quote with `user_report_data` embedded into it.
|
|
*
|
|
* Currently works only for Linux-SGX PAL, where `user_report_data` is a blob of exactly 64B
|
|
* and `quote` is an SGX quote obtained from Quoting Enclave via AESM service.
|
|
*
|
|
* \param[in] user_report_data Report data with arbitrary contents (typically uniquely
|
|
* identifies this Graphene instance). Must be a 64B buffer
|
|
* in case of SGX PAL.
|
|
* \param[in] user_report_data_size Size in bytes of `user_report_data`. Must be exactly 64B
|
|
* in case of SGX PAL.
|
|
* \param[out] quote Attestation quote with `user_report_data` embedded.
|
|
* \param[in,out] quote_size Caller specifies maximum size allocated for `quote`; on
|
|
* return, contains actual size of obtained quote.
|
|
*/
|
|
PAL_BOL DkAttestationQuote(PAL_PTR user_report_data, PAL_NUM user_report_data_size, PAL_PTR quote,
|
|
PAL_NUM* quote_size);
|
|
|
|
/*!
|
|
* \brief Set wrap key (master key) for protected files.
|
|
*
|
|
* Currently works only for Linux-SGX PAL. This function is supposed to be called during
|
|
* remote attestation and secret provisioning, before the user application starts.
|
|
*
|
|
* \param[in] pf_key_hex Wrap key for protected files. Must be a 32-char null-terminated
|
|
* hex string in case of SGX PAL (AES-GCM encryption key).
|
|
*/
|
|
PAL_BOL DkSetProtectedFilesKey(PAL_PTR pf_key_hex);
|
|
|
|
#ifdef __GNUC__
|
|
#define symbol_version_default(real, name, version) \
|
|
__asm__(".symver " #real "," #name "@@" #version "\n")
|
|
#else
|
|
#define symbol_version_default(real, name, version)
|
|
#endif
|
|
|
|
#if defined(__i386__) || defined(__x86_64__)
|
|
/*!
|
|
* \brief Return CPUID information, based on the leaf/subleaf.
|
|
*
|
|
* \param[out] values the array of the results
|
|
*/
|
|
PAL_BOL DkCpuIdRetrieve(PAL_IDX leaf, PAL_IDX subleaf, PAL_IDX values[PAL_CPUID_WORD_NUM]);
|
|
#endif
|
|
|
|
#endif /* PAL_H */
|