Handle cpuid and rdtsc instruction
Init support for cpuid and rdtsc instruction handling in occlum. This patch includes: 1. cpuid exception handler for all information leaves; 2. rdtsc exception handler; 3. handler registration; 4. cpuid test; 5. rdtsc test. Signed-off-by: 散樗 <kailun.qkl@antfin.com>
This commit is contained in:
parent
56c69b5f3c
commit
2553298b1d
@ -13,6 +13,14 @@ pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char
|
||||
}
|
||||
};
|
||||
|
||||
// register exception handlers (support CPUID for now)
|
||||
extern "C" {
|
||||
fn register_exception_handlers() -> ();
|
||||
}
|
||||
unsafe {
|
||||
register_exception_handlers();
|
||||
}
|
||||
|
||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||
panic::catch_unwind(|| {
|
||||
backtrace::__rust_begin_short_backtrace(|| match do_boot(&path, &args) {
|
||||
|
101
src/libos/src/exceptions.c
Normal file
101
src/libos/src/exceptions.c
Normal file
@ -0,0 +1,101 @@
|
||||
#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);
|
||||
uint64_t leaf;
|
||||
uint64_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 = info->cpu_context.rax;
|
||||
subleaf = 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);
|
||||
}
|
@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
||||
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||
TEST_DEPS := dev_null
|
||||
# Tests: need to be compiled and run by test-% target
|
||||
TESTS := empty argv hello_world malloc mmap file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit client server server_epoll unix_socket cout
|
||||
TESTS := empty argv hello_world malloc mmap file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit client server server_epoll unix_socket cout cpuid rdtsc
|
||||
# Benchmarks: need to be compiled and run by bench-% target
|
||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||
|
||||
|
5
test/cpuid/Makefile
Normal file
5
test/cpuid/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ../test_common.mk
|
||||
|
||||
EXTRA_C_FLAGS :=
|
||||
EXTRA_LINK_FLAGS :=
|
||||
BIN_ARGS :=
|
93
test/cpuid/main.c
Normal file
93
test/cpuid/main.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct t_cpuid {
|
||||
unsigned int eax;
|
||||
unsigned int ebx;
|
||||
unsigned int ecx;
|
||||
unsigned int edx;
|
||||
} t_cpuid_t;
|
||||
|
||||
static inline void native_cpuid(int leaf, int subleaf, t_cpuid_t *p)
|
||||
{
|
||||
/* ecx is often an input as well as an output. */
|
||||
asm volatile("cpuid"
|
||||
: "=a" (p->eax),
|
||||
"=b" (p->ebx),
|
||||
"=c" (p->ecx),
|
||||
"=d" (p->edx)
|
||||
: "a" (leaf), "c" (subleaf));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Gets CPUID information and tests the SGX support of the CPU */
|
||||
t_cpuid_t cpu = {0};
|
||||
int leaf = 1;
|
||||
int subleaf = 0;
|
||||
|
||||
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("Model %d\n", (cpu.eax >> 4) & 0xF); // Bit 7-4
|
||||
printf("Family %d\n", (cpu.eax >> 8) & 0xF); // Bit 11-8
|
||||
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 Family %d\n", (cpu.eax >> 20) & 0xFF); // Bit 27-20
|
||||
|
||||
// if smx (Safer Mode Extensions) set - SGX global enable is supported
|
||||
printf("smx: %d\n", (cpu.ecx >> 6) & 1); // CPUID.1:ECX.[bit6]
|
||||
|
||||
/* Extended feature bits (EAX=07H, ECX=0H)*/
|
||||
printf("\nExtended feature bits (EAX=07H, ECX=0H)\n");
|
||||
leaf = 7;
|
||||
subleaf = 0;
|
||||
cpu = {0};
|
||||
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,
|
||||
// Bit 02: SGX. Supports Intel® Software Guard Extensions (Intel® SGX Extensions) if 1.
|
||||
printf("SGX is available: %d\n", (cpu.ebx >> 2) & 0x1);
|
||||
|
||||
/* SGX has to be enabled in MSR.IA32_Feature_Control.SGX_Enable
|
||||
check with msr-tools: rdmsr -ax 0x3a
|
||||
SGX_Enable is Bit 18
|
||||
if SGX_Enable = 0 no leaf information will appear.
|
||||
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;
|
||||
cpu = {0};
|
||||
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 2 supported: %d\n", (cpu.eax >> 1) & 0x1);
|
||||
printf("MaxEnclaveSize_Not64: %x\n", cpu.edx & 0xFF);
|
||||
printf("MaxEnclaveSize_64: %x\n", (cpu.edx >> 8) & 0xFF);
|
||||
|
||||
/* CPUID Leaf 12H, Sub-Leaf 1 Enumeration of Intel SGX Capabilities (EAX=12H,ECX=1) */
|
||||
printf("\nCPUID Leaf 12H, Sub-Leaf 1 of Intel SGX Capabilities (EAX=12H,ECX=1)\n");
|
||||
leaf = 0x12;
|
||||
subleaf = 1;
|
||||
cpu = {0};
|
||||
native_cpuid(leaf, subleaf, &cpu);
|
||||
printf("eax: %x ebx: %x ecx: %x edx: %x\n", cpu.eax, cpu.ebx, cpu.ecx, cpu.edx);
|
||||
|
||||
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;
|
||||
cpu = {0};
|
||||
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;
|
||||
}
|
5
test/rdtsc/Makefile
Normal file
5
test/rdtsc/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ../test_common.mk
|
||||
|
||||
EXTRA_C_FLAGS :=
|
||||
EXTRA_LINK_FLAGS :=
|
||||
BIN_ARGS :=
|
19
test/rdtsc/main.c
Normal file
19
test/rdtsc/main.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint64_t native_rdtsc() {
|
||||
uint32_t hi, lo;
|
||||
asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return (( (uint64_t)lo)|( ((uint64_t)hi)<<32 ));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Gets rdtsc information and tests the SGX support of the rdtsc */
|
||||
uint64_t r;
|
||||
|
||||
r = native_rdtsc();
|
||||
printf("rdtsc: %lu\n", r);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user