mirror of
https://github.com/clearlinux/graphene.git
synced 2026-10-03 15:39:36 +00:00
[LibOS] Refactor checkpointing code
This commit still leaves checkpointing macros as-is; this will be fixed in a folow-up commit.
This commit is contained in:
@@ -2,47 +2,39 @@
|
||||
/* Copyright (C) 2014 Stony Brook University */
|
||||
|
||||
/*
|
||||
* shim_checkpoints.c
|
||||
* shim_checkpoint.h
|
||||
*
|
||||
* This file contains definitions and macros for checkpointing method.
|
||||
* This file contains definitions and macros for checkpointing.
|
||||
*/
|
||||
|
||||
#ifndef _SHIM_CHECKPOINT_H_
|
||||
#define _SHIM_CHECKPOINT_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <pal.h>
|
||||
#include <shim_defs.h>
|
||||
#include <shim_ipc.h>
|
||||
#include "pal.h"
|
||||
|
||||
#ifdef __i386__
|
||||
#error "x86-32 support is heavily broken."
|
||||
#endif
|
||||
|
||||
typedef uint64_t ptr_t;
|
||||
#include "shim_defs.h"
|
||||
#include "shim_ipc.h"
|
||||
|
||||
#define __attribute_migratable __attribute__((section(".migratable")))
|
||||
|
||||
extern char __migratable;
|
||||
extern char __migratable_end;
|
||||
|
||||
/* FIXME: Checkpointing must be de-macroed and simplified */
|
||||
|
||||
/* TSAI 7/11/2012:
|
||||
The checkpoint scheme we are expecting is to support an easy syntax to
|
||||
implement migration procedure. A migration procedure can be written
|
||||
in the following syntax:
|
||||
|
||||
BEGIN_CP_DEFINITION(exec)
|
||||
{
|
||||
BEGIN_CP_DEFINITION(exec) {
|
||||
DEFINE_CP(thread, ...);
|
||||
DEFINE_CP(handle_map, ...);
|
||||
}
|
||||
void * checkpoint = DO_CHECKPOINT(exec);
|
||||
|
||||
The structure of checkpoint data will be a counting-down stack-like
|
||||
memory segment, with enough space reserved below for 1. in case the
|
||||
dry run miscalculate the checkpoint size or 2. stack use for the new
|
||||
thread.
|
||||
void* checkpoint = DO_CHECKPOINT(exec);
|
||||
|
||||
Below is the figure for our checkpoint structure:
|
||||
|
||||
@@ -55,16 +47,11 @@ extern char __migratable_end;
|
||||
...
|
||||
checkpoint_entry[n] CP_NULL
|
||||
High Bytes ------------------------------------------------
|
||||
|
||||
|
||||
*/
|
||||
|
||||
struct shim_cp_entry {
|
||||
ptr_t cp_type; /* entry type */
|
||||
union {
|
||||
ptr_t cp_val; /* integer value */
|
||||
/* originally there is a pointer, now we don't need them */
|
||||
} cp_un;
|
||||
uintptr_t cp_type;
|
||||
uintptr_t cp_val;
|
||||
};
|
||||
|
||||
struct shim_mem_entry {
|
||||
@@ -72,8 +59,8 @@ struct shim_mem_entry {
|
||||
void* addr;
|
||||
size_t size;
|
||||
void** paddr;
|
||||
int prot; /*< Combination of PAL_PROT_* flags */
|
||||
void* data;
|
||||
int prot; /* combination of PAL_PROT_* flags */
|
||||
};
|
||||
|
||||
struct shim_palhdl_entry {
|
||||
@@ -88,25 +75,27 @@ struct shim_cp_store {
|
||||
void* cp_map;
|
||||
struct shim_handle* cp_file;
|
||||
|
||||
/* allocation method for check point area */
|
||||
void* (*alloc)(struct shim_cp_store*, void*, size_t);
|
||||
/* allocation method for checkpoint area */
|
||||
void* (*alloc)(void*, size_t);
|
||||
|
||||
/* check point area */
|
||||
ptr_t base, offset, bound;
|
||||
/* checkpoint area */
|
||||
uintptr_t base;
|
||||
size_t offset;
|
||||
size_t bound;
|
||||
|
||||
/* entries of out-of-band data */
|
||||
/* VMA entries */
|
||||
struct shim_mem_entry* last_mem_entry;
|
||||
int mem_nentries;
|
||||
size_t mem_entries_cnt;
|
||||
size_t mem_size;
|
||||
|
||||
/* entries of pal handles to send */
|
||||
/* PAL-handle entries */
|
||||
struct shim_palhdl_entry* last_palhdl_entry;
|
||||
int palhdl_nentries;
|
||||
size_t palhdl_entries_cnt;
|
||||
};
|
||||
|
||||
#define CP_FUNC_ARGS struct shim_cp_store* store, void* obj, size_t size, void** objp
|
||||
|
||||
#define RS_FUNC_ARGS struct shim_cp_entry* entry, ptr_t base, ptr_t* offset, long rebase
|
||||
#define RS_FUNC_ARGS struct shim_cp_entry* entry, uintptr_t base, size_t* offset, size_t rebase
|
||||
|
||||
#define DEFINE_CP_FUNC(name) int cp_##name(CP_FUNC_ARGS)
|
||||
#define DEFINE_RS_FUNC(name) int rs_##name(RS_FUNC_ARGS)
|
||||
@@ -120,7 +109,6 @@ extern const rs_func __rs_func;
|
||||
|
||||
enum {
|
||||
CP_NULL = 0,
|
||||
CP_IGNORE,
|
||||
CP_OOB,
|
||||
CP_ADDR,
|
||||
CP_SIZE,
|
||||
@@ -138,15 +126,15 @@ enum {
|
||||
|
||||
#define __ADD_CP_OFFSET(size) \
|
||||
({ \
|
||||
ptr_t _off = store->offset; \
|
||||
size_t _off = store->offset; \
|
||||
if (store->offset + (size) > store->bound) { \
|
||||
ptr_t new_bound = store->bound * 2; \
|
||||
size_t new_bound = store->bound * 2; \
|
||||
\
|
||||
while (store->offset + (size) > new_bound) \
|
||||
new_bound *= 2; \
|
||||
\
|
||||
void* buf = \
|
||||
store->alloc(store, (void*)store->base + store->bound, new_bound - store->bound); \
|
||||
store->alloc((void*)store->base + store->bound, new_bound - store->bound); \
|
||||
if (!buf) \
|
||||
return -ENOMEM; \
|
||||
\
|
||||
@@ -160,9 +148,7 @@ enum {
|
||||
({ \
|
||||
struct shim_cp_entry* tmp = (void*)base + __ADD_CP_OFFSET(sizeof(struct shim_cp_entry)); \
|
||||
tmp->cp_type = CP_##type; \
|
||||
tmp->cp_un.cp_val = (ptr_t)(value); \
|
||||
if (DEBUG_CHECKPOINT) \
|
||||
debug("ADD CP_" #type "(0x%08lx) >%ld\n", tmp->cp_un.cp_val, store->offset); \
|
||||
tmp->cp_val = (uintptr_t)(value); \
|
||||
tmp; \
|
||||
})
|
||||
|
||||
@@ -171,10 +157,8 @@ enum {
|
||||
size_t _size = ALIGN_UP(size, sizeof(void*)); \
|
||||
struct shim_cp_entry* oob = (void*)base + __ADD_CP_OFFSET(sizeof(struct shim_cp_entry)); \
|
||||
oob->cp_type = CP_OOB; \
|
||||
oob->cp_un.cp_val = (ptr_t)_size; \
|
||||
ptr_t _off = (ptr_t)__ADD_CP_OFFSET(_size); \
|
||||
if (DEBUG_CHECKPOINT) \
|
||||
debug("ADD OFFSET(%lu) >%ld\n", size, store->offset); \
|
||||
oob->cp_val = (uintptr_t)_size; \
|
||||
size_t _off = __ADD_CP_OFFSET(_size); \
|
||||
_off; \
|
||||
})
|
||||
|
||||
@@ -182,9 +166,7 @@ enum {
|
||||
({ \
|
||||
struct shim_cp_entry* tmp = (void*)base + __ADD_CP_OFFSET(sizeof(struct shim_cp_entry)); \
|
||||
tmp->cp_type = CP_FUNC_TYPE; \
|
||||
tmp->cp_un.cp_val = (ptr_t)(value); \
|
||||
if (DEBUG_CHECKPOINT) \
|
||||
debug("ADD %s(0x%08lx) >%ld\n", CP_FUNC_NAME, value, store->offset); \
|
||||
tmp->cp_val = (uintptr_t)(value); \
|
||||
tmp; \
|
||||
})
|
||||
|
||||
@@ -199,28 +181,24 @@ enum {
|
||||
} \
|
||||
*offset += sizeof(struct shim_cp_entry); \
|
||||
if (tmp->cp_type == CP_OOB) \
|
||||
*offset += tmp->cp_un.cp_val; \
|
||||
*offset += tmp->cp_val; \
|
||||
else \
|
||||
break; \
|
||||
} \
|
||||
tmp; \
|
||||
})
|
||||
|
||||
#define GET_CP_ENTRY(type) \
|
||||
({ \
|
||||
struct shim_cp_entry* tmp = NEXT_CP_ENTRY(); \
|
||||
\
|
||||
while (tmp->cp_type != CP_##type) \
|
||||
tmp = NEXT_CP_ENTRY(); \
|
||||
\
|
||||
/* debug("GET CP_" #type "(%p)\n",tmp->cp_un.cp_val); */ \
|
||||
tmp->cp_un.cp_val; \
|
||||
#define GET_CP_ENTRY(type) \
|
||||
({ \
|
||||
struct shim_cp_entry* tmp = NEXT_CP_ENTRY(); \
|
||||
while (tmp->cp_type != CP_##type) \
|
||||
tmp = NEXT_CP_ENTRY(); \
|
||||
tmp->cp_val; \
|
||||
})
|
||||
|
||||
#define GET_CP_FUNC_ENTRY() \
|
||||
({ \
|
||||
/* debug("GET CP_FUNC_%s(%p) :%d\n", CP_FUNC_NAME, entry->cp_un.cp_val); */ \
|
||||
entry->cp_un.cp_val; \
|
||||
#define GET_CP_FUNC_ENTRY() \
|
||||
({ \
|
||||
entry->cp_val; \
|
||||
})
|
||||
|
||||
#define BEGIN_CP_FUNC(name) \
|
||||
@@ -233,10 +211,10 @@ enum {
|
||||
DEFINE_CP_FUNC(name) { \
|
||||
int CP_FUNC_TYPE __attribute__((unused)) = CP_FUNC(name); \
|
||||
const char* CP_FUNC_NAME __attribute__((unused)) = #name; \
|
||||
ptr_t base __attribute__((unused)) = store->base;
|
||||
size_t base __attribute__((unused)) = store->base;
|
||||
|
||||
#define END_CP_FUNC(name) \
|
||||
return 0; \
|
||||
#define END_CP_FUNC(name) \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define END_CP_FUNC_NO_RS(name) \
|
||||
@@ -254,8 +232,8 @@ enum {
|
||||
int CP_FUNC_TYPE __attribute__((unused)) = CP_FUNC(name); \
|
||||
const char* CP_FUNC_NAME __attribute__((unused)) = #name;
|
||||
|
||||
#define END_RS_FUNC(name) \
|
||||
return 0; \
|
||||
#define END_RS_FUNC(name) \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define CP_REBASE(obj) \
|
||||
@@ -282,12 +260,11 @@ enum {
|
||||
|
||||
struct shim_cp_map_entry {
|
||||
void* addr;
|
||||
ptr_t off;
|
||||
size_t off;
|
||||
};
|
||||
|
||||
void* create_cp_map(void);
|
||||
void destroy_cp_map(void* map);
|
||||
|
||||
struct shim_cp_map_entry* get_cp_map_entry(void* map, void* addr, bool create);
|
||||
|
||||
#define GET_FROM_CP_MAP(obj) \
|
||||
@@ -304,8 +281,8 @@ struct shim_cp_map_entry* get_cp_map_entry(void* map, void* addr, bool create);
|
||||
|
||||
#define BEGIN_MIGRATION_DEF(name, ...) \
|
||||
int migrate_cp_##name(struct shim_cp_store* store, ##__VA_ARGS__) { \
|
||||
int ret = 0; \
|
||||
ptr_t base = store->base;
|
||||
int ret = 0; \
|
||||
size_t base = store->base;
|
||||
|
||||
#define END_MIGRATION_DEF(name) \
|
||||
ADD_CP_ENTRY(NULL, 0); \
|
||||
@@ -319,12 +296,11 @@ struct shim_cp_map_entry* get_cp_map_entry(void* map, void* addr, bool create);
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_RESUME 0
|
||||
#define DEBUG_CHECKPOINT 0
|
||||
#define DEBUG_RESUME 0
|
||||
|
||||
#if DEBUG_RESUME == 1
|
||||
#define DEBUG_RS(fmt, ...) \
|
||||
debug("GET %s(0x%08lx): " fmt "\n", CP_FUNC_NAME, entry->cp_un.cp_val, ##__VA_ARGS__)
|
||||
debug("GET %s(0x%08lx): " fmt "\n", CP_FUNC_NAME, entry->cp_val, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_RS(...) do {} while (0)
|
||||
#endif
|
||||
@@ -348,37 +324,47 @@ struct shim_cp_map_entry* get_cp_map_entry(void* map, void* addr, bool create);
|
||||
ret; \
|
||||
})
|
||||
|
||||
struct newproc_cp_header {
|
||||
struct cp_header {
|
||||
unsigned long size;
|
||||
void* addr;
|
||||
unsigned long offset;
|
||||
} hdr;
|
||||
struct mem_header {
|
||||
unsigned long entoffset;
|
||||
int nentries;
|
||||
} mem;
|
||||
struct palhdl_header {
|
||||
unsigned long entoffset;
|
||||
int nentries;
|
||||
} palhdl;
|
||||
struct checkpoint_hdr {
|
||||
void* addr;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
|
||||
size_t mem_offset;
|
||||
size_t mem_entries_cnt;
|
||||
|
||||
size_t palhdl_offset;
|
||||
size_t palhdl_entries_cnt;
|
||||
};
|
||||
|
||||
struct newproc_header {
|
||||
struct newproc_cp_header checkpoint;
|
||||
int failure;
|
||||
};
|
||||
typedef int (*migrate_func_t)(struct shim_cp_store*, struct shim_thread*, struct shim_process*,
|
||||
va_list);
|
||||
|
||||
struct newproc_response {
|
||||
IDTYPE child_vmid;
|
||||
int failure;
|
||||
};
|
||||
/*!
|
||||
* \brief Create child process and migrate current-process state to it.
|
||||
*
|
||||
* Called in parent process during fork/clone/execve.
|
||||
*
|
||||
* \param migrate_func Migration function defined by the caller.
|
||||
* \param exec Executable to load in the child process.
|
||||
* \param argv Arguments passed to the child process.
|
||||
* \param thread Main-thread handle to be migrated to the child process.
|
||||
*
|
||||
* The remaining arguments are passed into the migration function.
|
||||
*
|
||||
* \return 0 on success, negative POSIX error code on failure.
|
||||
*/
|
||||
int create_process_and_send_checkpoint(migrate_func_t migrate_func, struct shim_handle* exec,
|
||||
const char** argv, struct shim_thread* thread, ...);
|
||||
|
||||
int do_migration(struct newproc_cp_header* hdr, void** cpptr);
|
||||
int restore_checkpoint(struct cp_header* cphdr, struct mem_header* memhdr, ptr_t base, ptr_t type);
|
||||
int do_migrate_process(int (*migrate)(struct shim_cp_store*, struct shim_thread*,
|
||||
struct shim_process*, va_list),
|
||||
struct shim_handle* exec, const char** argv, struct shim_thread* thread,
|
||||
...);
|
||||
/*!
|
||||
* \brief Receive a checkpoint from parent process and restore state based on it.
|
||||
*
|
||||
* Called in child process during initialization.
|
||||
*
|
||||
* \param[in] hdr Checkpoint header already received from the parent.
|
||||
*
|
||||
* \return 0 on success, negative POSIX error code on failure.
|
||||
*/
|
||||
int receive_checkpoint_and_restore(struct checkpoint_hdr* hdr);
|
||||
|
||||
#endif /* _SHIM_CHECKPOINT_H_ */
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
#ifndef _SHIM_DEFS_H_
|
||||
#define _SHIM_DEFS_H_
|
||||
|
||||
/*
|
||||
* If enable CPSTORE_DERANDOMIZATION, the library OS will try to load the checkpoint (from the
|
||||
* parent) at the exact address it was created. Currently this option is disabled to prevent
|
||||
* internal fragmentation of virtual memory space.
|
||||
*/
|
||||
|
||||
#define CPSTORE_DERANDOMIZATION 1
|
||||
|
||||
#define DEFAULT_HEAP_MIN_SIZE (256 * 1024 * 1024) /* 256MB */
|
||||
#define DEFAULT_MEM_MAX_NPAGES (1024 * 1024) /* 4GB */
|
||||
#define DEFAULT_BRK_MAX_SIZE (256 * 1024) /* 256KB */
|
||||
|
||||
@@ -18,6 +18,18 @@ struct shim_handle;
|
||||
|
||||
void sysparser_printf(const char* fmt, ...);
|
||||
|
||||
/* quick hash function based on Robert Jenkins' hash algorithm */
|
||||
static inline uint64_t hash64(uint64_t key) {
|
||||
key = (~key) + (key << 21);
|
||||
key = key ^ (key >> 24);
|
||||
key = (key + (key << 3)) + (key << 8);
|
||||
key = key ^ (key >> 14);
|
||||
key = (key + (key << 2)) + (key << 4);
|
||||
key = key ^ (key >> 28);
|
||||
key = key + (key << 31);
|
||||
return key;
|
||||
}
|
||||
|
||||
/* string object */
|
||||
struct shim_str* get_str_obj(void);
|
||||
int free_str_obj(struct shim_str* str);
|
||||
|
||||
@@ -703,7 +703,7 @@ BEGIN_CP_FUNC(handle) {
|
||||
struct shim_handle* hdl = (struct shim_handle*)obj;
|
||||
struct shim_handle* new_hdl = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_handle));
|
||||
@@ -806,7 +806,7 @@ BEGIN_CP_FUNC(fd_handle) {
|
||||
struct shim_fd_handle* fdhdl = (struct shim_fd_handle*)obj;
|
||||
struct shim_fd_handle* new_fdhdl = NULL;
|
||||
|
||||
ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_fd_handle));
|
||||
size_t off = ADD_CP_OFFSET(sizeof(struct shim_fd_handle));
|
||||
new_fdhdl = (struct shim_fd_handle*)(base + off);
|
||||
memcpy(new_fdhdl, fdhdl, sizeof(struct shim_fd_handle));
|
||||
DO_CP(handle, fdhdl->handle, &new_fdhdl->handle);
|
||||
@@ -831,7 +831,7 @@ BEGIN_CP_FUNC(handle_map) {
|
||||
|
||||
size = sizeof(struct shim_handle_map) + (sizeof(struct shim_fd_handle*) * fd_size);
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(size);
|
||||
|
||||
@@ -529,7 +529,7 @@ BEGIN_CP_FUNC(signal_handles)
|
||||
struct shim_signal_handles* handles = (struct shim_signal_handles*)obj;
|
||||
struct shim_signal_handles* new_handles = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_signal_handles));
|
||||
@@ -576,7 +576,7 @@ BEGIN_CP_FUNC(thread)
|
||||
struct shim_thread * thread = (struct shim_thread *) obj;
|
||||
struct shim_thread * new_thread = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_thread));
|
||||
@@ -671,10 +671,10 @@ BEGIN_CP_FUNC(running_thread)
|
||||
struct shim_thread * new_thread = NULL;
|
||||
|
||||
DO_CP(thread, thread, &new_thread);
|
||||
ADD_CP_FUNC_ENTRY((ptr_t) new_thread - base);
|
||||
ADD_CP_FUNC_ENTRY((uintptr_t)new_thread - base);
|
||||
|
||||
if (thread->shim_tcb) {
|
||||
ptr_t toff = ADD_CP_OFFSET(sizeof(shim_tcb_t));
|
||||
size_t toff = ADD_CP_OFFSET(sizeof(shim_tcb_t));
|
||||
new_thread->shim_tcb = (void *)(base + toff);
|
||||
struct shim_tcb* new_tcb = new_thread->shim_tcb;
|
||||
memcpy(new_tcb, thread->shim_tcb, sizeof(*new_tcb));
|
||||
|
||||
@@ -1137,7 +1137,7 @@ BEGIN_CP_FUNC(vma)
|
||||
struct shim_vma_info* vma = (struct shim_vma_info*) obj;
|
||||
struct shim_vma_info* new_vma = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(*vma));
|
||||
|
||||
@@ -1605,7 +1605,7 @@ BEGIN_CP_FUNC(library) {
|
||||
struct link_map* map = (struct link_map*)obj;
|
||||
struct link_map* new_map;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct link_map));
|
||||
@@ -1708,7 +1708,7 @@ BEGIN_CP_FUNC(loaded_libraries) {
|
||||
map = map->l_next;
|
||||
}
|
||||
|
||||
ADD_CP_FUNC_ENTRY((ptr_t)new_interp_map);
|
||||
ADD_CP_FUNC_ENTRY((uintptr_t)new_interp_map);
|
||||
}
|
||||
END_CP_FUNC(loaded_libraries)
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ BEGIN_CP_FUNC(dentry) {
|
||||
struct shim_dentry* dent = (struct shim_dentry*)obj;
|
||||
struct shim_dentry* new_dent = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_dentry));
|
||||
|
||||
@@ -542,7 +542,7 @@ BEGIN_CP_FUNC(mount) {
|
||||
struct shim_mount* mount = (struct shim_mount*)obj;
|
||||
struct shim_mount* new_mount = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_mount));
|
||||
|
||||
@@ -443,7 +443,7 @@ BEGIN_CP_FUNC(ipc_info) {
|
||||
struct shim_ipc_info* info = (struct shim_ipc_info*)obj;
|
||||
struct shim_ipc_info* new_info = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_ipc_info));
|
||||
@@ -483,7 +483,7 @@ BEGIN_CP_FUNC(process) {
|
||||
struct shim_process* process = (struct shim_process*)obj;
|
||||
struct shim_process* new_process = NULL;
|
||||
|
||||
ptr_t off = GET_FROM_CP_MAP(obj);
|
||||
size_t off = GET_FROM_CP_MAP(obj);
|
||||
|
||||
if (!off) {
|
||||
off = ADD_CP_OFFSET(sizeof(struct shim_process));
|
||||
|
||||
+415
-545
File diff suppressed because it is too large
Load Diff
@@ -125,8 +125,8 @@ BEGIN_CP_FUNC(gdb_map) {
|
||||
struct gdb_link_map* newm = NULL;
|
||||
|
||||
while (m) {
|
||||
ptr_t off = ADD_CP_OFFSET(sizeof(struct gdb_link_map));
|
||||
newm = (struct gdb_link_map*)(base + off);
|
||||
size_t off = ADD_CP_OFFSET(sizeof(struct gdb_link_map));
|
||||
newm = (struct gdb_link_map*)(base + off);
|
||||
|
||||
memcpy(newm, m, sizeof(struct gdb_link_map));
|
||||
newm->l_prev = newm->l_next = NULL;
|
||||
|
||||
+14
-29
@@ -477,17 +477,6 @@ fail:
|
||||
(auxp) = _tmp + sizeof(char *); \
|
||||
} while (0)
|
||||
|
||||
static int init_newproc (struct newproc_header * hdr)
|
||||
{
|
||||
PAL_NUM bytes = DkStreamRead(PAL_CB(parent_process), 0,
|
||||
sizeof(struct newproc_header), hdr,
|
||||
NULL, 0);
|
||||
if (bytes == PAL_STREAM_ERROR)
|
||||
return -PAL_ERRNO();
|
||||
|
||||
return hdr->failure;
|
||||
}
|
||||
|
||||
#define CALL_INIT(func, args ...) func(args)
|
||||
|
||||
#define RUN_INIT(func, ...) \
|
||||
@@ -535,8 +524,6 @@ noreturn void* shim_init(int argc, void* args)
|
||||
/* call to figure out where the arguments are */
|
||||
FIND_ARG_COMPONENTS(args, argc, argv, envp, auxp);
|
||||
|
||||
struct newproc_header hdr;
|
||||
void * cpaddr = NULL;
|
||||
|
||||
RUN_INIT(init_vma);
|
||||
RUN_INIT(init_slab);
|
||||
@@ -550,17 +537,17 @@ noreturn void* shim_init(int argc, void* args)
|
||||
|
||||
debug("shim loaded at %p, ready to initialize\n", &__load_address);
|
||||
|
||||
if (!cpaddr && PAL_CB(parent_process)) {
|
||||
RUN_INIT(init_newproc, &hdr);
|
||||
if (hdr.checkpoint.hdr.size)
|
||||
RUN_INIT(do_migration, &hdr.checkpoint, &cpaddr);
|
||||
}
|
||||
if (PAL_CB(parent_process)) {
|
||||
struct checkpoint_hdr hdr;
|
||||
|
||||
PAL_NUM ret = DkStreamRead(PAL_CB(parent_process), 0, sizeof(hdr), &hdr, NULL, 0);
|
||||
if (ret == PAL_STREAM_ERROR || ret != sizeof(hdr))
|
||||
shim_do_exit(-PAL_ERRNO());
|
||||
|
||||
if (cpaddr) {
|
||||
thread_start_event = DkNotificationEventCreate(PAL_FALSE);
|
||||
RUN_INIT(restore_checkpoint,
|
||||
&hdr.checkpoint.hdr, &hdr.checkpoint.mem,
|
||||
(ptr_t) cpaddr, 0);
|
||||
|
||||
assert(hdr.size);
|
||||
RUN_INIT(receive_checkpoint_and_restore, &hdr);
|
||||
}
|
||||
|
||||
if (PAL_CB(manifest_handle))
|
||||
@@ -579,15 +566,13 @@ noreturn void* shim_init(int argc, void* args)
|
||||
|
||||
if (PAL_CB(parent_process)) {
|
||||
/* Notify the parent process */
|
||||
struct newproc_response res;
|
||||
res.child_vmid = cur_process.vmid;
|
||||
res.failure = 0;
|
||||
PAL_NUM ret = DkStreamWrite(PAL_CB(parent_process), 0,
|
||||
sizeof(struct newproc_response),
|
||||
&res, NULL);
|
||||
if (ret == PAL_STREAM_ERROR)
|
||||
IDTYPE child_vmid = cur_process.vmid;
|
||||
PAL_NUM ret = DkStreamWrite(PAL_CB(parent_process), 0, sizeof(child_vmid), &child_vmid,
|
||||
NULL);
|
||||
if (ret == PAL_STREAM_ERROR || ret != sizeof(child_vmid))
|
||||
shim_do_exit(-PAL_ERRNO());
|
||||
|
||||
/* FIXME: We shouldn't downgrade communication */
|
||||
/* Downgrade communication with parent to non-secure (only checkpoint recv is secure).
|
||||
* Currently only relevant to SGX PAL, other PALs ignore this. */
|
||||
PAL_STREAM_ATTR attr;
|
||||
|
||||
@@ -200,7 +200,7 @@ BEGIN_CP_FUNC(brk) {
|
||||
__UNUSED(obj);
|
||||
__UNUSED(size);
|
||||
__UNUSED(objp);
|
||||
ADD_CP_FUNC_ENTRY((ptr_t)brk_region.brk_start);
|
||||
ADD_CP_FUNC_ENTRY((uintptr_t)brk_region.brk_start);
|
||||
ADD_CP_ENTRY(SIZE, brk_region.brk_current - brk_region.brk_start);
|
||||
ADD_CP_ENTRY(SIZE, brk_region.brk_end - brk_region.brk_start);
|
||||
ADD_CP_ENTRY(SIZE, brk_region.data_segment_size);
|
||||
|
||||
@@ -357,7 +357,8 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
|
||||
add_thread(thread);
|
||||
set_as_child(self, thread);
|
||||
|
||||
ret = do_migrate_process(&migrate_fork, NULL, NULL, thread);
|
||||
ret = create_process_and_send_checkpoint(&migrate_fork, /*exec=*/NULL, /*argv=*/NULL,
|
||||
thread);
|
||||
thread->shim_tcb = NULL; /* cpu context of forked thread isn't
|
||||
* needed any more */
|
||||
if (parent_stack)
|
||||
|
||||
@@ -460,7 +460,7 @@ BEGIN_CP_FUNC(epoll_item) {
|
||||
INIT_LISTP(new_list);
|
||||
|
||||
LISTP_FOR_EACH_ENTRY(epoll_item, old_list, list) {
|
||||
ptr_t off = ADD_CP_OFFSET(sizeof(struct shim_epoll_item));
|
||||
size_t off = ADD_CP_OFFSET(sizeof(struct shim_epoll_item));
|
||||
|
||||
struct shim_epoll_item* new_epoll_item = (struct shim_epoll_item*)(base + off);
|
||||
|
||||
@@ -474,7 +474,7 @@ BEGIN_CP_FUNC(epoll_item) {
|
||||
DO_CP(handle, epoll_item->handle, &new_epoll_item->handle);
|
||||
}
|
||||
|
||||
ADD_CP_FUNC_ENTRY((ptr_t)objp - base);
|
||||
ADD_CP_FUNC_ENTRY((uintptr_t)objp - base);
|
||||
}
|
||||
END_CP_FUNC(epoll_item)
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ reopen:
|
||||
cur_thread->in_vm = false;
|
||||
unlock(&cur_thread->lock);
|
||||
|
||||
ret = do_migrate_process(&migrate_execve, exec, argv, cur_thread, envp);
|
||||
ret = create_process_and_send_checkpoint(&migrate_execve, exec, argv, cur_thread, envp);
|
||||
|
||||
lock(&cur_thread->lock);
|
||||
cur_thread->stack = stack;
|
||||
|
||||
@@ -71,7 +71,9 @@ int shim_do_fork(void) {
|
||||
add_thread(new_thread);
|
||||
set_as_child(cur_thread, new_thread);
|
||||
|
||||
if ((ret = do_migrate_process(&migrate_fork, NULL, NULL, new_thread)) < 0) {
|
||||
ret = create_process_and_send_checkpoint(&migrate_fork, /*exec=*/NULL, /*argv=*/NULL,
|
||||
new_thread);
|
||||
if (ret < 0) {
|
||||
put_thread(new_thread);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user