Fix RDTSC emulation's changing app's TLS by mistake

This commit switches from user mode to kernel mode before handling
the exception caused by RDTSC instruction.
This commit is contained in:
LI Qing 2020-04-09 05:27:47 +00:00
parent 52cb897436
commit bbc3b8a467
4 changed files with 40 additions and 24 deletions

@ -1,16 +1,9 @@
use super::*;
use process::Task;
use crate::syscall::SyscallNum;
use sgx_types::*;
const RDTSC_OPCODE: u16 = 0x310F;
extern "C" {
fn occlum_ocall_rdtsc(low: *mut u32, high: *mut u32) -> sgx_status_t;
fn __get_current_task() -> *const Task;
fn switch_td_to_kernel(task: *const Task);
fn switch_td_to_user(task: *const Task);
}
#[no_mangle]
pub extern "C" fn handle_rdtsc_exception(info: *mut sgx_exception_info_t) -> u32 {
let info = unsafe { &mut *info };
@ -21,21 +14,21 @@ pub extern "C" fn handle_rdtsc_exception(info: *mut sgx_exception_info_t) -> u32
{
return EXCEPTION_CONTINUE_SEARCH;
}
unsafe {
let task = __get_current_task();
switch_td_to_kernel(task);
let (low, high) = {
let mut low = 0;
let mut high = 0;
let sgx_status = occlum_ocall_rdtsc(&mut low, &mut high);
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
(low, high)
};
info.cpu_context.rax = low as u64;
info.cpu_context.rdx = high as u64;
switch_td_to_user(task);
}
let (low, high) = {
let mut low = 0;
let mut high = 0;
let ret = unsafe { __occlum_syscall(SyscallNum::Rdtsc as u32, &mut low, &mut high) };
assert!(ret == 0);
(low, high)
};
info.cpu_context.rax = low as u64;
info.cpu_context.rdx = high as u64;
info.cpu_context.rip += 2;
EXCEPTION_CONTINUE_EXECUTION
}
extern "C" {
fn __occlum_syscall(num: u32, arg0: *mut u32, arg1: *mut u32) -> i64;
}

@ -67,7 +67,5 @@ mod untrusted;
mod util;
mod vm;
// Export system calls
pub use syscall::*;
// Export ECalls
pub use entry::*;

@ -393,6 +393,8 @@ macro_rules! process_syscall_table_with_callback {
// Occlum-specific sytem calls
(Spawn = 360) => do_spawn(child_pid_ptr: *mut u32, path: *const i8, argv: *const *const i8, envp: *const *const i8, fdop_list: *const FdOp),
// Exception handling
(Rdtsc = 361) => do_rdtsc(low_ptr: *mut u32, high_ptr: *mut u32),
}
};
}
@ -932,6 +934,18 @@ fn do_clock_gettime(clockid: clockid_t, ts_u: *mut timespec_t) -> Result<isize>
Ok(0)
}
fn do_rdtsc(low_ptr: *mut u32, high_ptr: *mut u32) -> Result<isize> {
check_mut_ptr(low_ptr)?;
check_mut_ptr(high_ptr)?;
let (low, high) = time::do_rdtsc()?;
debug!("do_rdtsc result {{ low: {:#x} high: {:#x}}}", low, high);
unsafe {
*low_ptr = low;
*high_ptr = high;
}
Ok(0)
}
// TODO: handle remainder
fn do_nanosleep(req_u: *const timespec_t, rem_u: *mut timespec_t) -> Result<isize> {
check_ptr(req_u)?;

@ -160,6 +160,17 @@ pub fn do_thread_getcpuclock() -> Result<timespec_t> {
Ok(tv)
}
pub fn do_rdtsc() -> Result<(u32, u32)> {
extern "C" {
fn occlum_ocall_rdtsc(low: *mut u32, high: *mut u32) -> sgx_status_t;
}
let mut low = 0;
let mut high = 0;
let sgx_status = unsafe { occlum_ocall_rdtsc(&mut low, &mut high) };
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
Ok((low, high))
}
// For SEFS
pub struct OcclumTimeProvider;