Rewrite cpuid and rdtsc exception handlers
1. Rewrite cpuid and rdtsc exception handle in Rust 2. Rewrite cpuid test cases 3. Update Dockerfile to install cpuid tool for test
This commit is contained in:
parent
ba78f09d1c
commit
f37eb34038
@ -1,4 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use exception::*;
|
||||||
use process::pid_t;
|
use process::pid_t;
|
||||||
use std::ffi::{CStr, CString, OsString};
|
use std::ffi::{CStr, CString, OsString};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -14,13 +15,8 @@ pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// register exception handlers (support CPUID for now)
|
// register exception handlers (support cpuid & rdtsc for now)
|
||||||
extern "C" {
|
register_exception_handlers();
|
||||||
fn register_exception_handlers() -> ();
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
register_exception_handlers();
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||||
panic::catch_unwind(|| {
|
panic::catch_unwind(|| {
|
||||||
|
278
src/libos/src/exception/cpuid.rs
Normal file
278
src/libos/src/exception/cpuid.rs
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
use super::*;
|
||||||
|
use sgx_types::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rsgx_cpuidex;
|
||||||
|
|
||||||
|
const CPUID_OPCODE: u16 = 0xA20F;
|
||||||
|
const CPUID_MIN_BASIC_LEAF: u32 = 0;
|
||||||
|
const CPUID_MAX_BASIC_LEAF: u32 = 0x17;
|
||||||
|
const CPUID_MIN_EXTEND_LEAF: u32 = 0x8000_0000;
|
||||||
|
const CPUID_MAX_EXTEND_LEAF: u32 = 0x8000_0008;
|
||||||
|
const CPUID_MAX_SUBLEAF: u32 = u32::max_value();
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
|
struct CpuIdInput {
|
||||||
|
leaf: u32,
|
||||||
|
subleaf: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
|
struct CpuIdResult {
|
||||||
|
eax: u32,
|
||||||
|
ebx: u32,
|
||||||
|
ecx: u32,
|
||||||
|
edx: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CpuIdCache {
|
||||||
|
inner: HashMap<CpuIdInput, CpuIdResult>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CpuId {
|
||||||
|
cache: CpuIdCache,
|
||||||
|
max_basic_leaf: u32,
|
||||||
|
max_extend_leaf: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuIdCache {
|
||||||
|
pub fn new(max_basic_leaf: u32, max_extend_leaf: u32) -> CpuIdCache {
|
||||||
|
let mut cache = CpuIdCache {
|
||||||
|
inner: HashMap::new(),
|
||||||
|
};
|
||||||
|
cache.generate_cpuid_cache(max_basic_leaf, max_extend_leaf);
|
||||||
|
cache
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup(&self, key: &CpuIdInput) -> Option<&CpuIdResult> {
|
||||||
|
self.inner.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert(&mut self, key: CpuIdInput, value: CpuIdResult) {
|
||||||
|
// If EAX/EBX/ECX/EDX return 0, dismiss it
|
||||||
|
if (value.eax | value.ebx | value.ecx | value.edx) != 0 {
|
||||||
|
self.inner.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_cpuid_cache(&mut self, max_basic_leaf: u32, max_extend_leaf: u32) {
|
||||||
|
let mut sgx_support: bool = false;
|
||||||
|
// Generate basic leaf cpuid cache
|
||||||
|
for leaf in CPUID_MIN_BASIC_LEAF..=max_basic_leaf {
|
||||||
|
// Intel SGX Capability Enumeration Leaf,
|
||||||
|
// Leaf 12H sub-leaf 0 is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1.
|
||||||
|
if leaf == 0x12 && !sgx_support {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut max_subleaf = 0;
|
||||||
|
for subleaf in (0..) {
|
||||||
|
let cpuid_input = CpuIdInput { leaf, subleaf };
|
||||||
|
let cpuid_result = get_cpuid_info_via_ocall(cpuid_input);
|
||||||
|
self.insert(cpuid_input, cpuid_result);
|
||||||
|
// Most leaf only supports (sub-leaf == 0), and many others can determine their
|
||||||
|
// maximum supported sub-leaf according to CPUID.(EAX=Leaf, ECX=0H).
|
||||||
|
if subleaf == 0 {
|
||||||
|
max_subleaf = match leaf {
|
||||||
|
// EAX Bits 31 - 00: Reports the maximum sub-leaf supported.
|
||||||
|
0x7 | 0x14 | 0x17 => cpuid_result.eax,
|
||||||
|
// Reports valid resource type starting at bit position 1 of EDX.
|
||||||
|
// EDX Bit 00: Reserved.
|
||||||
|
// Bit 01: Supports L3 Cache Intel RDT Monitoring if 1.
|
||||||
|
// Bits 31 - 02: Reserved.
|
||||||
|
0xF => cpuid_result.edx & 0x0000_0002 >> 1,
|
||||||
|
// Reports valid ResID starting at bit position 1 of EBX.
|
||||||
|
// EBX Bit 00: Reserved.
|
||||||
|
// Bit 01: Supports L3 Cache Allocation Technology if 1.
|
||||||
|
// Bit 02: Supports L2 Cache Allocation Technology if 1.
|
||||||
|
// Bits 31 - 03: Reserved.
|
||||||
|
0x10 => match cpuid_result.ebx & 0x0000_0006 {
|
||||||
|
0x0000_0006 => 2,
|
||||||
|
0x0000_0002 => 1,
|
||||||
|
_ => 0,
|
||||||
|
},
|
||||||
|
// Processor Extended State Enumeration, Sub-leaf n (0 ≤ n ≤ 63)
|
||||||
|
0xD => 63,
|
||||||
|
// (Sub-leaf == 0) can not decide max_subleaf for these leaf,
|
||||||
|
// later match expression will decide the max_subleaf.
|
||||||
|
0x4 | 0xB | 0x12 => CPUID_MAX_SUBLEAF,
|
||||||
|
// Default max_subleaf is 0.
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
if leaf == 0x7 {
|
||||||
|
// EBX Bit 02: Supports Intel® SGX Extensions if 1.
|
||||||
|
sgx_support = (cpuid_result.ebx & 0x0000_0004) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// These leafs determine the maximum supported sub-leaf according to
|
||||||
|
// the output of CPUID instruction at every iteration.
|
||||||
|
if max_subleaf == CPUID_MAX_SUBLEAF {
|
||||||
|
max_subleaf = match leaf {
|
||||||
|
// Deterministic Cache Parameters Leaf
|
||||||
|
// Sub-leaf index n+1 is invalid if subleaf n returns EAX[4:0] as 0.
|
||||||
|
0x4 if (cpuid_result.eax & 0x1F) == 0 => subleaf,
|
||||||
|
// Extended Topology Enumeration Leaf
|
||||||
|
// If an input value n in ECX returns the invalid level-type of 0 in ECX[15:8],
|
||||||
|
// other input values with ECX > n also return 0 in ECX[15:8].
|
||||||
|
0xB if (cpuid_result.ecx & 0x0000_FF00) == 0 => subleaf,
|
||||||
|
// Intel SGX EPC Enumeration Leaf
|
||||||
|
// EAX Bit 03 - 00: Sub-leaf Type.
|
||||||
|
// 0000b: Indicates this sub-leaf is invalid.
|
||||||
|
0x12 if subleaf >= 2 && (cpuid_result.eax & 0x0000000F) == 0 => subleaf,
|
||||||
|
// Condition not met.
|
||||||
|
_ => max_subleaf,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if subleaf == max_subleaf {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Generate extend leaf cpuid cache
|
||||||
|
for leaf in CPUID_MIN_EXTEND_LEAF..=max_extend_leaf {
|
||||||
|
let cpuid_input = CpuIdInput { leaf, subleaf: 0 };
|
||||||
|
let cpuid_result = get_cpuid_info_via_ocall(cpuid_input);
|
||||||
|
self.insert(cpuid_input, cpuid_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CpuId {
|
||||||
|
pub fn new() -> CpuId {
|
||||||
|
let max_basic_leaf = match rsgx_cpuidex(CPUID_MIN_BASIC_LEAF as i32, 0) {
|
||||||
|
Ok(sgx_cpuinfo) => {
|
||||||
|
if is_valid_cpuid_basic_leaf(sgx_cpuinfo[0] as u32) {
|
||||||
|
sgx_cpuinfo[0] as u32
|
||||||
|
} else {
|
||||||
|
panic!("invalid basic cpuid_level")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("failed to call sgx_cpuidex"),
|
||||||
|
};
|
||||||
|
let max_extend_leaf = match rsgx_cpuidex(CPUID_MIN_EXTEND_LEAF as i32, 0) {
|
||||||
|
Ok(sgx_cpuinfo) => {
|
||||||
|
if is_valid_cpuid_extend_leaf(sgx_cpuinfo[0] as u32) {
|
||||||
|
sgx_cpuinfo[0] as u32
|
||||||
|
} else {
|
||||||
|
panic!("invalid extend cpuid_xlevel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("failed to call sgx_cpuidex"),
|
||||||
|
};
|
||||||
|
let cpuid = CpuId {
|
||||||
|
cache: CpuIdCache::new(max_basic_leaf, max_extend_leaf),
|
||||||
|
max_basic_leaf,
|
||||||
|
max_extend_leaf,
|
||||||
|
};
|
||||||
|
cpuid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_cpuid_from_cache(&self, cpuid_input: CpuIdInput) -> Result<CpuIdResult, Error> {
|
||||||
|
self.cache
|
||||||
|
.lookup(&cpuid_input)
|
||||||
|
.map(|result| result.clone())
|
||||||
|
.ok_or_else(|| Error::new(Errno::ENOENT, "cpuid_result not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_max_basic_leaf(&self) -> u32 {
|
||||||
|
self.max_basic_leaf
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_max_extend_leaf(&self) -> u32 {
|
||||||
|
self.max_extend_leaf
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_cpuid_info(&self, leaf: u32, subleaf: u32) -> CpuIdResult {
|
||||||
|
// If a value entered for CPUID.EAX is higher than the maximum input value
|
||||||
|
// for basic or extended function for that processor then the data for the
|
||||||
|
// highest basic information leaf is returned.
|
||||||
|
let fixed_leaf = if (CPUID_MIN_BASIC_LEAF..=self.max_basic_leaf).contains(&leaf)
|
||||||
|
|| (CPUID_MIN_EXTEND_LEAF..=self.max_extend_leaf).contains(&leaf)
|
||||||
|
{
|
||||||
|
leaf
|
||||||
|
} else {
|
||||||
|
self.max_basic_leaf
|
||||||
|
};
|
||||||
|
let fixed_subleaf = if is_cpuid_leaf_has_subleaves(fixed_leaf) {
|
||||||
|
subleaf
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let cpuid_input = CpuIdInput {
|
||||||
|
leaf: fixed_leaf,
|
||||||
|
subleaf: fixed_subleaf,
|
||||||
|
};
|
||||||
|
let cpuid_result = match self.lookup_cpuid_from_cache(cpuid_input) {
|
||||||
|
Ok(cpuid_result) => cpuid_result,
|
||||||
|
// If a value entered for CPUID.EAX is less than or equal to the maximum input value
|
||||||
|
// and the leaf is not supported on that processor then 0 is returned in all the registers.
|
||||||
|
Err(error) => CpuIdResult {
|
||||||
|
eax: 0,
|
||||||
|
ebx: 0,
|
||||||
|
ecx: 0,
|
||||||
|
edx: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
cpuid_result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref CPUID: CpuId = CpuId::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_cpuid_basic_leaf(leaf: u32) -> bool {
|
||||||
|
(CPUID_MIN_BASIC_LEAF..=CPUID_MAX_BASIC_LEAF).contains(&leaf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid_cpuid_extend_leaf(leaf: u32) -> bool {
|
||||||
|
(CPUID_MIN_EXTEND_LEAF..=CPUID_MAX_EXTEND_LEAF).contains(&leaf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_cpuid_leaf_has_subleaves(leaf: u32) -> bool {
|
||||||
|
const CPUID_LEAF_WITH_SUBLEAF: [u32; 9] = [0x4, 0x7, 0xB, 0xD, 0xF, 0x10, 0x12, 0x14, 0x17];
|
||||||
|
CPUID_LEAF_WITH_SUBLEAF.contains(&leaf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We cannot do OCalls when handling exceptions. So this function is only useful
|
||||||
|
// when we call setup_cpuid_info to initialize the CPUID singleton,
|
||||||
|
// which caches cpuid info for use when handling cpuid exception.
|
||||||
|
fn get_cpuid_info_via_ocall(cpuid_input: CpuIdInput) -> CpuIdResult {
|
||||||
|
let cpuid_result = match rsgx_cpuidex(cpuid_input.leaf as i32, cpuid_input.subleaf as i32) {
|
||||||
|
Ok(sgx_cpuinfo) => CpuIdResult {
|
||||||
|
eax: sgx_cpuinfo[0] as u32,
|
||||||
|
ebx: sgx_cpuinfo[1] as u32,
|
||||||
|
ecx: sgx_cpuinfo[2] as u32,
|
||||||
|
edx: sgx_cpuinfo[3] as u32,
|
||||||
|
},
|
||||||
|
_ => panic!("failed to call sgx_cpuidex"),
|
||||||
|
};
|
||||||
|
cpuid_result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_cpuid_info() {
|
||||||
|
// Make lazy_static to be executed at runtime in order to be initialized
|
||||||
|
let max_basic_leaf = CPUID.get_max_basic_leaf();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn handle_cpuid_exception(info: *mut sgx_exception_info_t) -> u32 {
|
||||||
|
let info = unsafe { &mut *info };
|
||||||
|
let ip_opcode = unsafe { *(info.cpu_context.rip as *const u16) };
|
||||||
|
if info.exception_vector != sgx_exception_vector_t::SGX_EXCEPTION_VECTOR_UD
|
||||||
|
|| info.exception_type != sgx_exception_type_t::SGX_EXCEPTION_HARDWARE
|
||||||
|
|| ip_opcode != CPUID_OPCODE
|
||||||
|
{
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
let leaf = info.cpu_context.rax as u32;
|
||||||
|
let subleaf = info.cpu_context.rcx as u32;
|
||||||
|
let cpuid_result = CPUID.get_cpuid_info(leaf, subleaf);
|
||||||
|
info.cpu_context.rax = cpuid_result.eax as u64;
|
||||||
|
info.cpu_context.rbx = cpuid_result.ebx as u64;
|
||||||
|
info.cpu_context.rcx = cpuid_result.ecx as u64;
|
||||||
|
info.cpu_context.rdx = cpuid_result.edx as u64;
|
||||||
|
info.cpu_context.rip += 2;
|
||||||
|
|
||||||
|
EXCEPTION_CONTINUE_EXECUTION
|
||||||
|
}
|
15
src/libos/src/exception/mod.rs
Normal file
15
src/libos/src/exception/mod.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use self::cpuid::*;
|
||||||
|
use self::rdtsc::*;
|
||||||
|
use super::*;
|
||||||
|
use sgx_types::*;
|
||||||
|
|
||||||
|
pub fn register_exception_handlers() {
|
||||||
|
setup_cpuid_info();
|
||||||
|
unsafe {
|
||||||
|
sgx_register_exception_handler(1, handle_cpuid_exception);
|
||||||
|
sgx_register_exception_handler(1, handle_rdtsc_exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod cpuid;
|
||||||
|
mod rdtsc;
|
27
src/libos/src/exception/rdtsc.rs
Normal file
27
src/libos/src/exception/rdtsc.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use super::*;
|
||||||
|
use sgx_types::*;
|
||||||
|
|
||||||
|
const RDTSC_OPCODE: u16 = 0x310F;
|
||||||
|
static mut FAKE_RDTSC_VALUE: u64 = 0;
|
||||||
|
static FAKE_RDTSC_INC_VALUE: u64 = 1000;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn handle_rdtsc_exception(info: *mut sgx_exception_info_t) -> u32 {
|
||||||
|
let info = unsafe { &mut *info };
|
||||||
|
let ip_opcode = unsafe { *(info.cpu_context.rip as *const u16) };
|
||||||
|
if info.exception_vector != sgx_exception_vector_t::SGX_EXCEPTION_VECTOR_UD
|
||||||
|
|| info.exception_type != sgx_exception_type_t::SGX_EXCEPTION_HARDWARE
|
||||||
|
|| ip_opcode != RDTSC_OPCODE
|
||||||
|
{
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
// rdtsc support here is temporary, only for SKL, later CPU's will support this inside enclave
|
||||||
|
unsafe {
|
||||||
|
FAKE_RDTSC_VALUE += FAKE_RDTSC_INC_VALUE;
|
||||||
|
info.cpu_context.rax = (FAKE_RDTSC_VALUE & 0xFFFFFFFF);
|
||||||
|
info.cpu_context.rdx = (FAKE_RDTSC_VALUE >> 32);
|
||||||
|
}
|
||||||
|
info.cpu_context.rip += 2;
|
||||||
|
|
||||||
|
EXCEPTION_CONTINUE_EXECUTION
|
||||||
|
}
|
@ -1,101 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "sgx_cpuid.h"
|
|
||||||
#include "sgx_trts_exception.h"
|
|
||||||
|
|
||||||
#define CPUID_OPCODE 0xA20F
|
|
||||||
#define RDTSC_OPCODE 0x310F
|
|
||||||
#define SUPPORTED_CPUID_LEAF_NUM 30
|
|
||||||
// the maximum supported sub-leaves may vary between different leaves and
|
|
||||||
// processors, fix it to a constant for now
|
|
||||||
#define SUPPORTED_CPUID_SUBLEAF_NUM 4
|
|
||||||
|
|
||||||
int supported_cpuid_leaves[] = {
|
|
||||||
// Basic CPUID Information
|
|
||||||
0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
|
|
||||||
0x00000006, 0x00000007, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000D,
|
|
||||||
0x0000000F, 0x00000010, 0x00000012, 0x00000014, 0x00000015, 0x00000016,
|
|
||||||
0x00000017, 0x00000018, 0x0000001F,
|
|
||||||
// Extended Function CPUID Information
|
|
||||||
0x80000000, 0x80000001, 0x80000002, 0x80000003, 0x80000004, 0x80000005,
|
|
||||||
0x80000006, 0x80000007, 0x80000008,
|
|
||||||
};
|
|
||||||
|
|
||||||
// holds cached CPUID information
|
|
||||||
typedef struct _CpuidInfo {
|
|
||||||
int leaf;
|
|
||||||
int subleaf;
|
|
||||||
int reg[4];
|
|
||||||
} CpuidInfo;
|
|
||||||
CpuidInfo cpuid_info[SUPPORTED_CPUID_LEAF_NUM][SUPPORTED_CPUID_SUBLEAF_NUM];
|
|
||||||
|
|
||||||
// rdtsc support here is temporary, only for SKL, later CPU's will support this inside enclave
|
|
||||||
uint64_t fake_rdtsc_value = 0;
|
|
||||||
uint16_t fake_rdtsc_inc_value = 1000;
|
|
||||||
|
|
||||||
void setup_cpuid_info() {
|
|
||||||
for (int i = 0; i < SUPPORTED_CPUID_LEAF_NUM; i++) {
|
|
||||||
for (int j = 0; j < SUPPORTED_CPUID_SUBLEAF_NUM; j++) {
|
|
||||||
int index = supported_cpuid_leaves[i];
|
|
||||||
cpuid_info[i][j].leaf = index;
|
|
||||||
cpuid_info[i][j].subleaf = j;
|
|
||||||
if (sgx_cpuidex(cpuid_info[i][j].reg, index, j) != SGX_SUCCESS)
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle_cpuid_exception(sgx_exception_info_t *info) {
|
|
||||||
uint16_t ip_opcode = *(uint16_t *)(info->cpu_context.rip);
|
|
||||||
uint32_t leaf;
|
|
||||||
uint32_t subleaf;
|
|
||||||
|
|
||||||
if (info->exception_vector != SGX_EXCEPTION_VECTOR_UD ||
|
|
||||||
info->exception_type != SGX_EXCEPTION_HARDWARE ||
|
|
||||||
ip_opcode != CPUID_OPCODE) {
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
leaf = (uint32_t)info->cpu_context.rax;
|
|
||||||
subleaf = (uint32_t)info->cpu_context.rcx;
|
|
||||||
|
|
||||||
for (int i = 0; i < SUPPORTED_CPUID_LEAF_NUM; i++) {
|
|
||||||
for (int j = 0; j < SUPPORTED_CPUID_SUBLEAF_NUM; j++) {
|
|
||||||
if (cpuid_info[i][j].leaf == leaf &&
|
|
||||||
cpuid_info[i][j].subleaf == subleaf) {
|
|
||||||
info->cpu_context.rax = cpuid_info[i][j].reg[0];
|
|
||||||
info->cpu_context.rbx = cpuid_info[i][j].reg[1];
|
|
||||||
info->cpu_context.rcx = cpuid_info[i][j].reg[2];
|
|
||||||
info->cpu_context.rdx = cpuid_info[i][j].reg[3];
|
|
||||||
|
|
||||||
info->cpu_context.rip += 2;
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
int handle_rdtsc_exception(sgx_exception_info_t *info) {
|
|
||||||
uint16_t ip_opcode = *(uint16_t *)(info->cpu_context.rip);
|
|
||||||
|
|
||||||
if (info->exception_vector != SGX_EXCEPTION_VECTOR_UD ||
|
|
||||||
info->exception_type != SGX_EXCEPTION_HARDWARE ||
|
|
||||||
ip_opcode != RDTSC_OPCODE) {
|
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
fake_rdtsc_value += fake_rdtsc_inc_value;
|
|
||||||
info->cpu_context.rax = (uint32_t)(fake_rdtsc_value & 0xFFFFFFFF);
|
|
||||||
info->cpu_context.rdx = (uint32_t)(fake_rdtsc_value >> 32);
|
|
||||||
info->cpu_context.rip += 2;
|
|
||||||
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_exception_handlers() {
|
|
||||||
setup_cpuid_info();
|
|
||||||
sgx_register_exception_handler(true, handle_cpuid_exception);
|
|
||||||
sgx_register_exception_handler(true, handle_rdtsc_exception);
|
|
||||||
}
|
|
@ -42,6 +42,7 @@ mod prelude;
|
|||||||
mod config;
|
mod config;
|
||||||
mod entry;
|
mod entry;
|
||||||
mod errno;
|
mod errno;
|
||||||
|
mod exception;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod misc;
|
mod misc;
|
||||||
mod process;
|
mod process;
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
|
DEPS_FILE := test_cpuid.txt
|
||||||
include ../test_common.mk
|
include ../test_common.mk
|
||||||
|
|
||||||
EXTRA_C_FLAGS :=
|
EXTRA_C_FLAGS :=
|
||||||
EXTRA_LINK_FLAGS :=
|
EXTRA_LINK_FLAGS :=
|
||||||
BIN_ARGS :=
|
BIN_ARGS :=
|
||||||
|
|
||||||
|
test_cpuid.txt:
|
||||||
|
@/usr/bin/cpuid -r > $@
|
||||||
|
@mv $@ $(IMAGE_DIR)/$@
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper struct & functions for cpuid
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
typedef struct t_cpuid {
|
typedef struct t_cpuid {
|
||||||
unsigned int eax;
|
unsigned int eax;
|
||||||
@ -21,71 +29,254 @@ static inline void native_cpuid(int leaf, int subleaf, t_cpuid_t *p)
|
|||||||
: "a" (leaf), "c" (subleaf));
|
: "a" (leaf), "c" (subleaf));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
static bool is_cpuidinfo_equal(int leaf, t_cpuid_t *cpu, t_cpuid_t *cpu_sgx) {
|
||||||
{
|
/* Leaf 01H CPUID.EBX is related with logical processor. */
|
||||||
/* Gets CPUID information and tests the SGX support of the CPU */
|
if (leaf == 1) {
|
||||||
|
return ((cpu->eax == cpu_sgx->eax) &&
|
||||||
|
(cpu->ecx == cpu_sgx->ecx) &&
|
||||||
|
(cpu->edx == cpu_sgx->edx));
|
||||||
|
}
|
||||||
|
/* Leaf 0BH CPUID.EDX is related with logical processor. */
|
||||||
|
if (leaf == 0xB) {
|
||||||
|
return ((cpu->eax == cpu_sgx->eax) &&
|
||||||
|
(cpu->ebx == cpu_sgx->ebx) &&
|
||||||
|
(cpu->ecx == cpu_sgx->ecx));
|
||||||
|
}
|
||||||
|
return ((cpu->eax == cpu_sgx->eax) &&
|
||||||
|
(cpu->ebx == cpu_sgx->ebx) &&
|
||||||
|
(cpu->ecx == cpu_sgx->ecx) &&
|
||||||
|
(cpu->edx == cpu_sgx->edx));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int g_max_basic_leaf = 0;
|
||||||
|
static int g_max_extend_leaf = 0;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for cpuid
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int test_cpuid_with_basic_leaf_zero() {
|
||||||
t_cpuid_t cpu;
|
t_cpuid_t cpu;
|
||||||
int leaf = 1;
|
int leaf = 0;
|
||||||
|
int subleaf = 0;
|
||||||
|
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
// cpu should support sgx
|
||||||
|
if (cpu.eax < 0x12) {
|
||||||
|
throw_error("failed to call cpuid with eax=0");
|
||||||
|
}
|
||||||
|
g_max_basic_leaf = cpu.eax;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_basic_leaf_zero_with_subleaf() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0;
|
||||||
|
int subleaf = 256;
|
||||||
|
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax != g_max_basic_leaf) {
|
||||||
|
throw_error("failed to call cpuid with eax=0 and subleaf");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_extend_leaf_zero() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0x80000000;
|
||||||
|
int subleaf = 0;
|
||||||
|
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax < 0x80000000) {
|
||||||
|
throw_error("failed to call cpuid with eax=0x80000000");
|
||||||
|
}
|
||||||
|
g_max_extend_leaf = cpu.eax;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_extend_leaf_zero_with_subleaf() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0x80000000;
|
||||||
|
int subleaf = 256;
|
||||||
|
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax != g_max_extend_leaf) {
|
||||||
|
throw_error("failed to call cpuid with eax=0x80000000");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_basic_leaf_one() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0x1;
|
||||||
int subleaf = 0;
|
int subleaf = 0;
|
||||||
|
|
||||||
native_cpuid(leaf, subleaf, &cpu);
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
|
||||||
printf("Stepping %d\n", cpu.eax & 0xF); // Bit 3-0
|
printf("Stepping %d\n", cpu.eax & 0xF); // Bit 3-0
|
||||||
printf("Model %d\n", (cpu.eax >> 4) & 0xF); // Bit 7-4
|
printf("Model %d\n", (cpu.eax >> 4) & 0xF); // Bit 7-4
|
||||||
printf("Family %d\n", (cpu.eax >> 8) & 0xF); // Bit 11-8
|
printf("Family %d\n", (cpu.eax >> 8) & 0xF); // Bit 11-8
|
||||||
printf("Processor Type %d\n", (cpu.eax >> 12) & 0x3); // Bit 13-12
|
printf("Processor Type %d\n", (cpu.eax >> 12) & 0x3); // Bit 13-12
|
||||||
printf("Extended Model %d\n", (cpu.eax >> 16) & 0xF); // Bit 19-16
|
printf("Extended Model %d\n", (cpu.eax >> 16) & 0xF); // Bit 19-16
|
||||||
printf("Extended Family %d\n", (cpu.eax >> 20) & 0xFF); // Bit 27-20
|
printf("Extended Family %d\n", (cpu.eax >> 20) & 0xFF); // Bit 27-20
|
||||||
|
if (cpu.eax == 0) {
|
||||||
|
throw_error("faild to call cpuid with eax=1");
|
||||||
|
}
|
||||||
|
if (!((cpu.ecx >> 6) & 1)) {
|
||||||
|
throw_error("smx is not enabled");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// if smx (Safer Mode Extensions) set - SGX global enable is supported
|
static int test_cpuid_with_sgx_verify() {
|
||||||
printf("smx: %d\n", (cpu.ecx >> 6) & 1); // CPUID.1:ECX.[bit6]
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0x7;
|
||||||
|
int subleaf = 0;
|
||||||
|
|
||||||
/* Extended feature bits (EAX=07H, ECX=0H)*/
|
|
||||||
printf("\nExtended feature bits (EAX=07H, ECX=0H)\n");
|
|
||||||
leaf = 7;
|
|
||||||
subleaf = 0;
|
|
||||||
native_cpuid(leaf, subleaf, &cpu);
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
|
||||||
|
|
||||||
//CPUID.(EAX=07H, ECX=0H):EBX.SGX = 1,
|
//CPUID.(EAX=07H, ECX=0H):EBX.SGX = 1,
|
||||||
// Bit 02: SGX. Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1.
|
// Bit 02: SGX. Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1.
|
||||||
printf("SGX is available: %d\n", (cpu.ebx >> 2) & 0x1);
|
if (((cpu.ebx >> 2) & 0x1) != 1) {
|
||||||
|
throw_error("failed to call cpuid to verify sgx");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* SGX has to be enabled in MSR.IA32_Feature_Control.SGX_Enable
|
static int test_cpuid_with_sgx_enumeration() {
|
||||||
check with msr-tools: rdmsr -ax 0x3a
|
t_cpuid_t cpu;
|
||||||
SGX_Enable is Bit 18
|
int leaf = 0x12;
|
||||||
if SGX_Enable = 0 no leaf information will appear.
|
int subleaf = 0;
|
||||||
for more information check Intel Docs Architectures-software-developer-system-programming-manual - 35.1 Architectural MSRS
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* CPUID Leaf 12H, Sub-Leaf 0 Enumeration of Intel SGX Capabilities (EAX=12H,ECX=0) */
|
|
||||||
printf("\nCPUID Leaf 12H, Sub-Leaf 0 of Intel SGX Capabilities (EAX=12H,ECX=0)\n");
|
|
||||||
leaf = 0x12;
|
|
||||||
subleaf = 0;
|
|
||||||
native_cpuid(leaf, subleaf, &cpu);
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
|
||||||
|
|
||||||
printf("Sgx 1 supported: %d\n", cpu.eax & 0x1);
|
printf("Sgx 1 supported: %d\n", cpu.eax & 0x1);
|
||||||
printf("Sgx 2 supported: %d\n", (cpu.eax >> 1) & 0x1);
|
printf("Sgx 2 supported: %d\n", (cpu.eax >> 1) & 0x1);
|
||||||
printf("MaxEnclaveSize_Not64: %x\n", cpu.edx & 0xFF);
|
if (((cpu.eax & 0x1) | ((cpu.eax >> 1) & 0x1)) == 0) {
|
||||||
printf("MaxEnclaveSize_64: %x\n", (cpu.edx >> 8) & 0xFF);
|
throw_error("failed to call cpuid to get SGX Capbilities");
|
||||||
|
}
|
||||||
/* CPUID Leaf 12H, Sub-Leaf 1 Enumeration of Intel SGX Capabilities (EAX=12H,ECX=1) */
|
if (((cpu.edx & 0xFF) | ((cpu.edx >> 8) & 0xFF)) == 0) {
|
||||||
printf("\nCPUID Leaf 12H, Sub-Leaf 1 of Intel SGX Capabilities (EAX=12H,ECX=1)\n");
|
throw_error("get MaxEnclaveSize failed");
|
||||||
|
}
|
||||||
leaf = 0x12;
|
leaf = 0x12;
|
||||||
subleaf = 1;
|
subleaf = 1;
|
||||||
native_cpuid(leaf, subleaf, &cpu);
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
if ((cpu.eax | cpu.ebx | cpu.ecx | cpu.edx) == 0) {
|
||||||
|
throw_error("failed to call cpuid to get SGX Attributes");
|
||||||
int i;
|
|
||||||
for (i=2; i<4; i++) {
|
|
||||||
/* CPUID Leaf 12H, Sub-Leaf i Enumeration of Intel SGX Capabilities (EAX=12H,ECX=i) */
|
|
||||||
printf("\nCPUID Leaf 12H, Sub-Leaf %d of Intel SGX Capabilities (EAX=12H,ECX=%d)\n", i, i);
|
|
||||||
leaf = 0x12;
|
|
||||||
subleaf = i;
|
|
||||||
native_cpuid(leaf, subleaf, &cpu);
|
|
||||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_invalid_leaf() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = 0x8;
|
||||||
|
int subleaf = 0;
|
||||||
|
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax | cpu.ebx | cpu.ecx | cpu.edx) {
|
||||||
|
throw_error("faild to call cpuid with invalid leaf 0x8");
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf = 0xC;
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax | cpu.ebx | cpu.ecx | cpu.edx) {
|
||||||
|
throw_error("faild to call cpuid with invalid leaf 0xC");
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf = 0xE;
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax | cpu.ebx | cpu.ecx | cpu.edx) {
|
||||||
|
throw_error("faild to call cpuid with invalid leaf 0xE");
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf = 0x11;
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
if (cpu.eax | cpu.ebx | cpu.ecx | cpu.edx) {
|
||||||
|
throw_error("faild to call cpuid with invalid leaf 0x11");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_oversized_leaf() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
int leaf = g_max_extend_leaf + 1;
|
||||||
|
int subleaf = 1;
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
|
||||||
|
t_cpuid_t cpu_max;
|
||||||
|
leaf = g_max_basic_leaf;
|
||||||
|
subleaf = 1;
|
||||||
|
native_cpuid(leaf, subleaf, &cpu_max);
|
||||||
|
|
||||||
|
if ((cpu.eax != cpu_max.eax) || (cpu.ebx != cpu_max.ebx) ||
|
||||||
|
(cpu.ecx != cpu_max.ecx) || (cpu.edx != cpu_max.edx)) {
|
||||||
|
throw_error("failed to call cpuid with oversize leaf");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_cpuid_with_random_leaf() {
|
||||||
|
t_cpuid_t cpu;
|
||||||
|
srand((int)time(NULL));
|
||||||
|
int leaf = 0;
|
||||||
|
int subleaf = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
leaf = rand();
|
||||||
|
subleaf = rand();
|
||||||
|
native_cpuid(leaf, subleaf, &cpu);
|
||||||
|
printf("random leaf:%x, subleaf:%x \n", leaf, subleaf);
|
||||||
|
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BUFF_SIZE (1024)
|
||||||
|
static int test_cpuid_with_host_cpuidinfo() {
|
||||||
|
char buff[BUFF_SIZE] = {0};
|
||||||
|
FILE * fp = fopen("./test_cpuid.txt","r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
throw_error("failed to open host cpuid.txt");
|
||||||
|
}
|
||||||
|
while (fgets(buff, BUFF_SIZE, fp)) {
|
||||||
|
uint32_t leaf = 0;
|
||||||
|
uint32_t subleaf = 0;
|
||||||
|
t_cpuid_t cpu = {0};
|
||||||
|
int num = sscanf(buff, " %x %x: eax=%x ebx=%x ecx=%x edx=%x", &leaf, &subleaf,
|
||||||
|
&cpu.eax, &cpu.ebx, &cpu.ecx, &cpu.edx);
|
||||||
|
if (num != 6) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
t_cpuid_t cpu_sgx = {0};
|
||||||
|
native_cpuid(leaf, subleaf, &cpu_sgx);
|
||||||
|
if (!is_cpuidinfo_equal(leaf, &cpu, &cpu_sgx)) {
|
||||||
|
printf("leaf:0x%x subleaf:0x%x\n", leaf, subleaf);
|
||||||
|
printf("ori_eax:0x%x ori_ebx:0x%x ori_ecx:0x%x ori_edx:0x%x\n",
|
||||||
|
cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
||||||
|
printf("sgx_eax:0x%x sgx_ebx:0x%x sgx_ecx:0x%x sgx_edx:0x%x\n",
|
||||||
|
cpu_sgx.eax, cpu_sgx.ebx, cpu_sgx.ecx, cpu_sgx.edx);
|
||||||
|
throw_error("failed to check cpuid info");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_cpuid_with_basic_leaf_zero),
|
||||||
|
TEST_CASE(test_cpuid_with_basic_leaf_zero_with_subleaf),
|
||||||
|
TEST_CASE(test_cpuid_with_extend_leaf_zero),
|
||||||
|
TEST_CASE(test_cpuid_with_extend_leaf_zero_with_subleaf),
|
||||||
|
TEST_CASE(test_cpuid_with_basic_leaf_one),
|
||||||
|
TEST_CASE(test_cpuid_with_sgx_verify),
|
||||||
|
TEST_CASE(test_cpuid_with_sgx_enumeration),
|
||||||
|
TEST_CASE(test_cpuid_with_invalid_leaf),
|
||||||
|
TEST_CASE(test_cpuid_with_oversized_leaf),
|
||||||
|
TEST_CASE(test_cpuid_with_random_leaf),
|
||||||
|
TEST_CASE(test_cpuid_with_host_cpuidinfo),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
||||||
|
@ -27,7 +27,7 @@ LINK_FLAGS = $(C_FLAGS) -pie $(EXTRA_LINK_FLAGS)
|
|||||||
# Build
|
# Build
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
all: $(ALL_BUILD_SUBDIRS) $(BIN)
|
all: $(ALL_BUILD_SUBDIRS) $(BIN) $(DEPS_FILE)
|
||||||
|
|
||||||
$(ALL_BUILD_SUBDIRS):
|
$(ALL_BUILD_SUBDIRS):
|
||||||
@mkdir -p $@
|
@mkdir -p $@
|
||||||
@ -52,7 +52,6 @@ $(BUILD_DIR)/test/obj/$(TEST_NAME)/%.o: %.c
|
|||||||
$(BUILD_DIR)/test/obj/$(TEST_NAME)/%.o: %.cc
|
$(BUILD_DIR)/test/obj/$(TEST_NAME)/%.o: %.cc
|
||||||
@$(CXX) $(C_FLAGS) -c $< -o $@
|
@$(CXX) $(C_FLAGS) -c $< -o $@
|
||||||
@echo "CXX <= $@"
|
@echo "CXX <= $@"
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Test
|
# Test
|
||||||
#############################################################################
|
#############################################################################
|
||||||
@ -69,4 +68,4 @@ test-native:
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-$(RM) -f $(BIN) $(C_OBJS) $(CXX_OBJS)
|
@-$(RM) -f $(BIN) $(DEPS_FILE) $(C_OBJS) $(CXX_OBJS)
|
||||||
|
@ -38,6 +38,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install depend cpuid test tool
|
||||||
|
WORKDIR /tmp
|
||||||
|
RUN wget http://www.etallen.com/cpuid/cpuid-20180519.x86_64.tar.gz && \
|
||||||
|
tar -xf ./cpuid-20180519.x86_64.tar.gz && \
|
||||||
|
cp ./cpuid-20180519/cpuid /usr/bin/ && \
|
||||||
|
rm -rf /tmp/cpuid-20180519*
|
||||||
|
|
||||||
# Install SGX SDK
|
# Install SGX SDK
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
RUN git clone https://github.com/occlum/linux-sgx . && \
|
RUN git clone https://github.com/occlum/linux-sgx . && \
|
||||||
|
Loading…
Reference in New Issue
Block a user