Refactor EDL for adding custom C types easily

Before this commit, using custom C types in ECalls/OCalls defined in Occlum's
EDL is cumbersme. Now this issue is resolved by providing `occlum_edl_types.h`
header file. There are two versions of this file: one is under
`src/libos/include/edl/` for LibOS, the other is under
`src/pal/include/edl/` for PAL. So now to define a new custom C type, just
edit the two versions of `occlum_edl_types.h` to define the type.
This commit is contained in:
Tate, Hongliang Tian 2020-01-21 09:31:19 +00:00
parent 986d1d2e44
commit c3d042dcd0
11 changed files with 118 additions and 100 deletions

@ -47,7 +47,7 @@ install:
install -d $(OCCLUM_PREFIX)/src/libos/src/builtin/
install -t $(OCCLUM_PREFIX)/src/libos/src/builtin/ -m 444 src/libos/src/builtin/*
install -d $(OCCLUM_PREFIX)/include/
install -t $(OCCLUM_PREFIX)/include/ -m 444 src/pal/include/*
install -t $(OCCLUM_PREFIX)/include/ -m 444 src/pal/include/*.h
install -d $(OCCLUM_PREFIX)/etc/template/
install -t $(OCCLUM_PREFIX)/etc/template/ -m 444 etc/template/*

@ -7,6 +7,7 @@ enclave {
from "sgx_net.edl" import *;
include "sgx_quote.h"
include "occlum_edl_types.h"
trusted {
/*
@ -49,16 +50,24 @@ enclave {
*/
int occlum_ocall_exec_thread_async(int libos_tid);
void occlum_ocall_gettimeofday([out] long* sec, [out] long* us);
void occlum_ocall_clock_gettime(int clockid, [out] long* sec, [out] long* ns);
void occlum_ocall_gettimeofday([out] struct timeval* tv);
void occlum_ocall_clock_gettime(clockid_t clockid, [out] struct timespec* ts);
void occlum_ocall_nanosleep(long sec, long nsec);
void occlum_ocall_nanosleep([in] const struct timespec* req);
void occlum_ocall_sync(void);
void occlum_ocall_sched_yield(void);
int occlum_ocall_sched_getaffinity([out] int *error, int pid, size_t cpusize, [out, size=cpusize] unsigned char* buf);
int occlum_ocall_sched_setaffinity([out] int *error, int pid, size_t cpusize, [in, size=cpusize] const unsigned char* buf);
int occlum_ocall_sched_getaffinity(
int host_tid,
size_t cpusize,
[out, size=cpusize] unsigned char* buf
) propagate_errno;
int occlum_ocall_sched_setaffinity(
int host_tid,
size_t cpusize,
[in, size=cpusize] const unsigned char* buf
) propagate_errno;
sgx_status_t occlum_ocall_sgx_init_quote(
[out] sgx_target_info_t* target_info,

@ -125,7 +125,7 @@ $(LIBOS_CORE_RS_A): $(RUST_SRCS)
endif
$(BUILD_DIR)/src/libos/src/Enclave_t.o: $(BUILD_DIR)/src/libos/src/Enclave_t.c
@$(CC) $(C_FLAGS) -c $< -o $@
@$(CC) $(C_FLAGS) -Iinclude/edl -c $< -o $@
@echo "CC <= $@"
$(BUILD_DIR)/src/libos/src/Enclave_t.c: $(SGX_EDGER8R) ../Enclave.edl

@ -0,0 +1,13 @@
#ifndef __OCCLUM_EDL_TYPES_H__
#define __OCCLUM_EDL_TYPES_H__
typedef long time_t;
typedef long suseconds_t;
typedef int clockid_t;
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
#endif /* __OCCLUM_EDL_TYPES_H__ */

@ -1,23 +1,5 @@
use super::*;
extern "C" {
fn occlum_ocall_sched_getaffinity(
ret: *mut i32,
errno: *mut i32,
pid: i32,
cpusetsize: size_t,
mask: *mut c_uchar,
) -> sgx_status_t;
fn occlum_ocall_sched_setaffinity(
ret: *mut i32,
errno: *mut i32,
pid: i32,
cpusetsize: size_t,
mask: *const c_uchar,
) -> sgx_status_t;
fn occlum_ocall_sched_yield() -> sgx_status_t;
}
pub struct CpuSet {
vec: Vec<u8>,
}
@ -86,42 +68,37 @@ fn find_host_tid(pid: pid_t) -> Result<pid_t> {
Ok(host_tid)
}
pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result<i32> {
pub fn do_sched_getaffinity(pid: pid_t, cpu_set: &mut CpuSet) -> Result<usize> {
let host_tid = match pid {
0 => 0,
_ => find_host_tid(pid)?,
};
let buf = cpu_set.as_mut_ptr();
let cpusize = cpu_set.len();
let mut ret = 0;
let mut error = 0;
unsafe {
occlum_ocall_sched_getaffinity(&mut ret, &mut error, host_tid as i32, cpusize, buf);
}
if (ret < 0) {
let errno = Errno::from(error as u32);
return_errno!(errno, "occlum_ocall_sched_getaffinity failed");
}
Ok(ret)
let retval = try_libc!({
let mut retval = 0;
let sgx_status = occlum_ocall_sched_getaffinity(&mut retval, host_tid as i32, cpusize, buf);
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
retval
}) as usize;
// Note: the first retval bytes in CpuSet are valid
Ok(retval)
}
pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result<i32> {
pub fn do_sched_setaffinity(pid: pid_t, cpu_set: &CpuSet) -> Result<()> {
let host_tid = match pid {
0 => 0,
_ => find_host_tid(pid)?,
};
let buf = cpu_set.as_ptr();
let cpusize = cpu_set.len();
let mut ret = 0;
let mut error = 0;
unsafe {
occlum_ocall_sched_setaffinity(&mut ret, &mut error, host_tid as i32, cpusize, buf);
}
if (ret < 0) {
let errno = Errno::from(error as u32);
return_errno!(errno, "occlum_ocall_sched_setaffinity failed");
}
Ok(ret)
try_libc!({
let mut retval = 0;
let sgx_status = occlum_ocall_sched_setaffinity(&mut retval, host_tid as i32, cpusize, buf);
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
retval
});
Ok(())
}
pub fn do_sched_yield() {
@ -130,3 +107,19 @@ pub fn do_sched_yield() {
assert!(status == sgx_status_t::SGX_SUCCESS);
}
}
extern "C" {
fn occlum_ocall_sched_getaffinity(
ret: *mut i32,
host_tid: i32,
cpusetsize: size_t,
mask: *mut c_uchar,
) -> sgx_status_t;
fn occlum_ocall_sched_setaffinity(
ret: *mut i32,
host_tid: i32,
cpusetsize: size_t,
mask: *const c_uchar,
) -> sgx_status_t;
fn occlum_ocall_sched_yield() -> sgx_status_t;
}

@ -1046,11 +1046,10 @@ fn do_sched_getaffinity(pid: pid_t, cpusize: size_t, buf: *mut c_uchar) -> Resul
};
// Call the memory-safe do_sched_getaffinity
let mut cpuset = CpuSet::new(cpusize);
let ret = process::do_sched_getaffinity(pid, &mut cpuset)?;
debug!("sched_getaffinity cpuset: {:#x}", cpuset);
let retval = process::do_sched_getaffinity(pid, &mut cpuset)?;
// Copy from Rust types to C types
buf_slice.copy_from_slice(cpuset.as_slice());
Ok(ret as isize)
Ok(retval as isize)
}
fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Result<isize> {
@ -1067,8 +1066,8 @@ fn do_sched_setaffinity(pid: pid_t, cpusize: size_t, buf: *const c_uchar) -> Res
};
debug!("sched_setaffinity cpuset: {:#x}", cpuset);
// Call the memory-safe do_sched_setaffinity
let ret = process::do_sched_setaffinity(pid, &cpuset)?;
Ok(ret as isize)
process::do_sched_setaffinity(pid, &cpuset)?;
Ok(0)
}
fn do_socket(domain: c_int, socket_type: c_int, protocol: c_int) -> Result<isize> {

@ -21,18 +21,27 @@ impl timeval_t {
pub fn as_usec(&self) -> usize {
(self.sec * 1000000 + self.usec) as usize
}
pub fn validate(&self) -> Result<()> {
if self.sec >= 0 && self.usec >= 0 && self.usec < 1_000_000 {
Ok(())
} else {
return_errno!(EINVAL, "invalid value for timeval_t");
}
}
}
pub fn do_gettimeofday() -> timeval_t {
let mut tv: timeval_t = Default::default();
unsafe {
occlum_ocall_gettimeofday(&mut tv.sec as *mut time_t, &mut tv.usec as *mut suseconds_t);
}
tv
extern "C" {
fn occlum_ocall_gettimeofday(tv: *mut timeval_t) -> sgx_status_t;
}
extern "C" {
fn occlum_ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t;
let mut tv: timeval_t = Default::default();
unsafe {
occlum_ocall_gettimeofday(&mut tv as *mut timeval_t);
}
tv.validate().expect("ocall returned invalid timeval_t");
tv
}
#[repr(C)]
@ -51,6 +60,14 @@ impl timespec_t {
}
Ok(ts)
}
pub fn validate(&self) -> Result<()> {
if self.sec >= 0 && self.nsec >= 0 && self.nsec < 1_000_000_000 {
Ok(())
} else {
return_errno!(EINVAL, "invalid value for timespec_t");
}
}
}
#[allow(non_camel_case_types)]
@ -88,31 +105,23 @@ impl ClockID {
pub fn do_clock_gettime(clockid: ClockID) -> Result<timespec_t> {
extern "C" {
fn occlum_ocall_clock_gettime(
clockid: clockid_t,
sec: *mut time_t,
ns: *mut i64,
) -> sgx_status_t;
fn occlum_ocall_clock_gettime(clockid: clockid_t, tp: *mut timespec_t) -> sgx_status_t;
}
let mut sec = 0;
let mut nsec = 0;
let mut tv: timespec_t = Default::default();
unsafe {
occlum_ocall_clock_gettime(
clockid as clockid_t,
&mut sec as *mut time_t,
&mut nsec as *mut i64,
);
occlum_ocall_clock_gettime(clockid as clockid_t, &mut tv as *mut timespec_t);
}
Ok(timespec_t { sec, nsec })
tv.validate().expect("ocall returned invalid timespec");
Ok(tv)
}
pub fn do_nanosleep(req: &timespec_t) -> Result<()> {
extern "C" {
fn occlum_ocall_nanosleep(sec: time_t, nsec: i64) -> sgx_status_t;
fn occlum_ocall_nanosleep(req: *const timespec_t) -> sgx_status_t;
}
unsafe {
occlum_ocall_nanosleep(req.sec, req.nsec);
occlum_ocall_nanosleep(req as *const timespec_t);
}
Ok(())
}

@ -12,7 +12,7 @@ C_OBJS := $(addprefix $(BUILD_DIR)/src/pal/,$(C_SRCS:.c=.o))
CXX_SRCS := $(sort $(wildcard src/*.cpp src/*/*.cpp))
CXX_OBJS := $(addprefix $(BUILD_DIR)/src/pal/,$(CXX_SRCS:.cpp=.o))
C_COMMON_FLAGS := -I$(BUILD_DIR)/src/pal/src -Iinclude
C_COMMON_FLAGS := -I$(BUILD_DIR)/src/pal/src -Iinclude -Iinclude/edl
C_FLAGS := $(C_COMMON_FLAGS) $(SGX_CFLAGS_U)
CXX_FLAGS := $(C_COMMON_FLAGS) $(SGX_CXXFLAGS_U)
LINK_FLAGS := $(SGX_LFLAGS_U) -shared -L$(RUST_SGX_SDK_DIR)/sgx_ustdc/ -lsgx_ustdc -lsgx_uprotected_fs
@ -36,7 +36,10 @@ $(BUILD_DIR)/src/pal/src/Enclave_u.o: $(BUILD_DIR)/src/pal/src/Enclave_u.c
@echo "CC <= $@"
$(BUILD_DIR)/src/pal/src/Enclave_u.c: $(SGX_EDGER8R) ../Enclave.edl
@cd $(BUILD_DIR)/src/pal/src && $(SGX_EDGER8R) --untrusted $(CUR_DIR)/../Enclave.edl --search-path $(SGX_SDK)/include --search-path $(RUST_SGX_SDK_DIR)/edl/
@cd $(BUILD_DIR)/src/pal/src && \
$(SGX_EDGER8R) --untrusted $(CUR_DIR)/../Enclave.edl \
--search-path $(SGX_SDK)/include \
--search-path $(RUST_SGX_SDK_DIR)/edl/
@echo "GEN <= $@"
$(BUILD_DIR)/src/pal/%.o: %.c

@ -0,0 +1,7 @@
#ifndef __OCCLUM_EDL_TYPES__
#define __OCCLUM_EDL_TYPES__
#include <time.h> // import struct timespec
#include <sys/time.h> // import struct timeval
#endif /* __OCCLUM_EDL_TYPES__ */

@ -1,24 +1,16 @@
#define _GNU_SOURCE
#include <sched.h>
#include "ocalls.h"
int occlum_ocall_sched_getaffinity(int* error, int pid, size_t cpusize, unsigned char* buf) {
int ret = syscall(__NR_sched_getaffinity, pid, cpusize, buf);
if (error) {
*error = (ret == -1) ? errno : 0;
}
return ret;
int occlum_ocall_sched_getaffinity(int host_tid, size_t cpusize, unsigned char* buf) {
return syscall(__NR_sched_getaffinity, host_tid, cpusize, buf);
}
int occlum_ocall_sched_setaffinity(int* error, int pid, size_t cpusize, const unsigned char* buf) {
int ret = syscall(__NR_sched_setaffinity, pid, cpusize, buf);
if (error) {
*error = (ret == -1) ? errno : 0;
}
return ret;
int occlum_ocall_sched_setaffinity(int host_tid, size_t cpusize, const unsigned char* buf) {
return syscall(__NR_sched_setaffinity, host_tid, cpusize, buf);
}
/* In the Linux implementation, sched_yield() always succeeds */
void occlum_ocall_sched_yield(void) {
sched_yield();
}

@ -1,21 +1,14 @@
#include <sys/time.h>
#include "ocalls.h"
void occlum_ocall_gettimeofday(long* seconds, long* microseconds) {
struct timeval tv;
gettimeofday(&tv, NULL);
*seconds = tv.tv_sec;
*microseconds = tv.tv_usec;
void occlum_ocall_gettimeofday(struct timeval* tv) {
gettimeofday(tv, NULL);
}
void occlum_ocall_clock_gettime(int clockid, time_t* sec, long* ns) {
struct timespec ts;
clock_gettime(clockid, &ts);
*sec = ts.tv_sec;
*ns = ts.tv_nsec;
void occlum_ocall_clock_gettime(int clockid, struct timespec *tp) {
clock_gettime(clockid, tp);
}
void occlum_ocall_nanosleep(time_t sec, long nsec) {
struct timespec tv = { .tv_sec = sec, .tv_nsec = nsec };
nanosleep(&tv, NULL);
void occlum_ocall_nanosleep(const struct timespec* req) {
nanosleep(req, NULL);
}