Enable MPX
This commit is contained in:
parent
9389b702ba
commit
e5d3ab3cf9
@ -21,7 +21,6 @@ extern crate lazy_static;
|
||||
use std::ffi::CStr; // a borrowed C string
|
||||
use std::backtrace::{self, PrintFormat};
|
||||
use std::panic;
|
||||
|
||||
use sgx_types::*;
|
||||
use sgx_trts::libc;
|
||||
|
||||
@ -32,27 +31,28 @@ mod fs;
|
||||
mod process;
|
||||
mod syscall;
|
||||
mod vm;
|
||||
mod util;
|
||||
|
||||
use prelude::*;
|
||||
|
||||
/// Export system calls
|
||||
pub use syscall::*;
|
||||
|
||||
// TODO: return meaningful exit code
|
||||
#[no_mangle]
|
||||
pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 {
|
||||
let path_str = unsafe {
|
||||
CStr::from_ptr(path_buf).to_string_lossy().into_owned()
|
||||
};
|
||||
println!("LibOS boots: {}", path_str);
|
||||
|
||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||
panic::catch_unwind(||{
|
||||
backtrace::__rust_begin_short_backtrace(||{
|
||||
let argv = std::vec::Vec::new();
|
||||
let envp = std::vec::Vec::new();
|
||||
process::do_spawn(&path_str, &argv, &envp);
|
||||
match do_boot(&path_str) {
|
||||
Ok(()) => 0,
|
||||
Err(err) => err.errno.as_retval() /* Normal error */,
|
||||
}
|
||||
})
|
||||
}).ok();
|
||||
|
||||
0
|
||||
}).unwrap_or(-1 /* Fatal error */)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -60,10 +60,28 @@ pub extern "C" fn libos_run() -> i32 {
|
||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||
panic::catch_unwind(||{
|
||||
backtrace::__rust_begin_short_backtrace(||{
|
||||
let _ = process::run_task();
|
||||
match do_run() {
|
||||
Ok(()) => 0,
|
||||
Err(err) => err.errno.as_retval() /* Normal error */,
|
||||
}
|
||||
})
|
||||
}).ok();
|
||||
|
||||
0
|
||||
}).unwrap_or(-1 /* Fatal error */)
|
||||
}
|
||||
|
||||
|
||||
// TODO: make sure do_boot can only be called once
|
||||
fn do_boot(path_str: &str) -> Result<(), Error> {
|
||||
util::mpx_enable()?;
|
||||
|
||||
let argv = std::vec::Vec::new();
|
||||
let envp = std::vec::Vec::new();
|
||||
process::do_spawn(&path_str, &argv, &envp)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: make sure do_run() cannot be called before do_boot()
|
||||
fn do_run() -> Result<(), Error> {
|
||||
process::run_task()?;
|
||||
Ok(())
|
||||
}
|
||||
|
5
src/libos/src/util/mod.rs
Normal file
5
src/libos/src/util/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
use prelude::*;
|
||||
|
||||
pub use self::mpx_util::{*};
|
||||
|
||||
mod mpx_util;
|
100
src/libos/src/util/mpx_util.c
Normal file
100
src/libos/src/util/mpx_util.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include "mpx_util.h"
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Define data structures for the part of XSAVE area that are relevant
|
||||
* to enabling MPX
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint64_t xstate_bv;
|
||||
uint64_t __irrelevant[2];
|
||||
uint64_t __reserved[5];
|
||||
} __attribute__ ((packed)) xsave_header_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t __irrelevant[8];
|
||||
} __attribute__ ((packed)) bndreg_t ;
|
||||
|
||||
typedef struct {
|
||||
uint64_t enable: 1;
|
||||
uint64_t bndpreserve: 1;
|
||||
uint64_t __reserved: 10;
|
||||
uint64_t __irrelevant: 52;
|
||||
} __attribute__ ((packed)) bndcfgu_t;
|
||||
|
||||
typedef struct {
|
||||
bndcfgu_t bndcfgu;
|
||||
uint64_t __irrelevant;
|
||||
} __attribute__((packed)) bndcsr_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t __irrelevant0[512];
|
||||
xsave_header_t header;
|
||||
uint8_t __irrelevant1[256];
|
||||
uint8_t __irrelevant2[128];
|
||||
bndreg_t bndreg;
|
||||
bndcsr_t bndcsr;
|
||||
} __attribute__ ((packed, __aligned__(64))) xsave_area_t ;
|
||||
|
||||
|
||||
/*
|
||||
* Restore the state components of CPU specified in rfbm from xsave_area.
|
||||
*
|
||||
* rfbm is the requested-feature bitmap, whose bits specifies which state
|
||||
* components are to restored by this instruction.
|
||||
*/
|
||||
static void xrstor(xsave_area_t* xsave_area, uint64_t rfbm) {
|
||||
uint32_t rfbm_l= rfbm;
|
||||
uint32_t rfbm_h = rfbm >> 32;
|
||||
|
||||
#define REX_PREFIX "0x48, "
|
||||
#define XRSTOR64 REX_PREFIX "0x0f,0xae,0x2f "
|
||||
|
||||
__asm__ __volatile__ (
|
||||
".byte " XRSTOR64 "\n\t"
|
||||
:
|
||||
: "D" (xsave_area), "m" (*xsave_area), "a" (rfbm), "d" (rfbm)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* The state component bitmaps for MPX
|
||||
*
|
||||
* The state component 3 (i.e., bit 3) is BNDREG state, which consists of the
|
||||
* four MPX bound registers BND0-BND3.
|
||||
*
|
||||
* The state component 4 (i.e., bit 4) is BNDCSR state, which consists of the
|
||||
* one MPX configuration register BNDCFGU and one MPX status register
|
||||
* BNDSTATUS.
|
||||
* */
|
||||
#define MPX_BNDREG_COMPONENT_MASK (0x08UL)
|
||||
#define MPX_BNDCSR_COMPONENT_MASK (0x10UL)
|
||||
#define MPX_ALL_COMPONENT_MASK (MPX_BNDCSR_COMPONENT_MASK | \
|
||||
MPX_BNDREG_COMPONENT_MASK)
|
||||
|
||||
int __mpx_enable(void) {
|
||||
xsave_area_t xsave_area;
|
||||
memset(&xsave_area, 0, sizeof(xsave_area));
|
||||
|
||||
/* Initialize MPX states
|
||||
*
|
||||
* xrestor initializes state component i if rfbm[i] = 1 and
|
||||
* xsave_area.header.xstate_bv[i] = 0 */
|
||||
uint64_t rfbm = MPX_ALL_COMPONENT_MASK;
|
||||
xrstor(&xsave_area, rfbm);
|
||||
|
||||
/* xrestor updates state component i if rfbm[i] = 1 and
|
||||
* xsave_area.header.xstate_bv[i] = 1 */
|
||||
xsave_area.header.xstate_bv = MPX_BNDCSR_COMPONENT_MASK;
|
||||
/* Set enable bit to 1 to enable MPX */
|
||||
xsave_area.bndcsr.bndcfgu.enable = 1;
|
||||
/* Set bndpreserve bit to 1 so that BND0-BND3 remain unchanged upon
|
||||
* control flow transfer instructions (e.g., call, jmp, etc.). */
|
||||
xsave_area.bndcsr.bndcfgu.bndpreserve = 1;
|
||||
/* Set BNDCSR state component so that MPX is enabled. */
|
||||
rfbm = MPX_BNDCSR_COMPONENT_MASK;
|
||||
xrstor(&xsave_area, rfbm);
|
||||
|
||||
return 0;
|
||||
}
|
34
src/libos/src/util/mpx_util.h
Normal file
34
src/libos/src/util/mpx_util.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef __MPX_UTIL__
|
||||
#define __MPX_UTIL__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enable the use of MPX bound registers bnd0-bnd3 and bound instructions
|
||||
* bndmk, bndcl and bndcu. */
|
||||
int __mpx_enable(void);
|
||||
|
||||
/* Make a new bound in bnd<i>*/
|
||||
void __mpx_bndmk0(unsigned long base, unsigned long size);
|
||||
void __mpx_bndmk1(unsigned long base, unsigned long size);
|
||||
void __mpx_bndmk2(unsigned long base, unsigned long size);
|
||||
void __mpx_bndmk3(unsigned long base, unsigned long size);
|
||||
|
||||
/* Check x against the lower bound of bnd<i>*/
|
||||
void __mpx_bndcl0(unsigned long x);
|
||||
void __mpx_bndcl1(unsigned long x);
|
||||
void __mpx_bndcl2(unsigned long x);
|
||||
void __mpx_bndcl3(unsigned long x);
|
||||
|
||||
/* Check x against the upper bound of bnd<i> */
|
||||
void __mpx_bndcu0(unsigned long x);
|
||||
void __mpx_bndcu1(unsigned long x);
|
||||
void __mpx_bndcu2(unsigned long x);
|
||||
void __mpx_bndcu3(unsigned long x);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MPX_UTIL__ */
|
66
src/libos/src/util/mpx_util.rs
Normal file
66
src/libos/src/util/mpx_util.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use super::*;
|
||||
|
||||
pub fn mpx_enable() -> Result<(), Error> {
|
||||
match unsafe { __mpx_enable () } {
|
||||
0 => { Ok(()) }
|
||||
_ => { errno!(EPERM, "MPX cannot be enabled") }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MpxReg {
|
||||
BND0,
|
||||
BND1,
|
||||
BND2,
|
||||
BND3,
|
||||
}
|
||||
|
||||
pub fn mpx_bndmk(bndreg: MpxReg, base: usize, size: usize) -> Result<(), Error> {
|
||||
/* Check whether the upper bound overflows the max of 64-bit */
|
||||
if base.checked_add(size).is_none() {
|
||||
return errno!(ERANGE, "Upper bound overflows");
|
||||
}
|
||||
|
||||
match bndreg {
|
||||
MpxReg::BND0 => unsafe { __mpx_bndmk0(base, size) },
|
||||
MpxReg::BND1 => unsafe { __mpx_bndmk1(base, size) },
|
||||
MpxReg::BND2 => unsafe { __mpx_bndmk2(base, size) },
|
||||
MpxReg::BND3 => unsafe { __mpx_bndmk3(base, size) },
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mpx_bndcl(bndreg: MpxReg, addr: usize) {
|
||||
match bndreg {
|
||||
MpxReg::BND0 => unsafe { __mpx_bndcl0(addr) },
|
||||
MpxReg::BND1 => unsafe { __mpx_bndcl1(addr) },
|
||||
MpxReg::BND2 => unsafe { __mpx_bndcl2(addr) },
|
||||
MpxReg::BND3 => unsafe { __mpx_bndcl3(addr) },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mpx_bndcu(bndreg: MpxReg, addr: usize) {
|
||||
match bndreg {
|
||||
MpxReg::BND0 => unsafe { __mpx_bndcu0(addr) },
|
||||
MpxReg::BND1 => unsafe { __mpx_bndcu1(addr) },
|
||||
MpxReg::BND2 => unsafe { __mpx_bndcu2(addr) },
|
||||
MpxReg::BND3 => unsafe { __mpx_bndcu3(addr) },
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern {
|
||||
// See mpx_util.h
|
||||
fn __mpx_enable() -> i32;
|
||||
fn __mpx_bndmk0(base: usize, size: usize);
|
||||
fn __mpx_bndmk1(base: usize, size: usize);
|
||||
fn __mpx_bndmk2(base: usize, size: usize);
|
||||
fn __mpx_bndmk3(base: usize, size: usize);
|
||||
fn __mpx_bndcl0(x: usize);
|
||||
fn __mpx_bndcl1(x: usize);
|
||||
fn __mpx_bndcl2(x: usize);
|
||||
fn __mpx_bndcl3(x: usize);
|
||||
fn __mpx_bndcu0(x: usize);
|
||||
fn __mpx_bndcu1(x: usize);
|
||||
fn __mpx_bndcu2(x: usize);
|
||||
fn __mpx_bndcu3(x: usize);
|
||||
}
|
81
src/libos/src/util/mpx_util_x86-64.S
Normal file
81
src/libos/src/util/mpx_util_x86-64.S
Normal file
@ -0,0 +1,81 @@
|
||||
.file "mpx_util_x86-64.S"
|
||||
|
||||
/* For bnd0 */
|
||||
|
||||
.global __mpx_bndmk0
|
||||
.type __mpx_bndmk0, @function
|
||||
__mpx_bndmk0:
|
||||
bndmk (%rdi, %rsi, 1), %bnd0
|
||||
ret
|
||||
|
||||
.global __mpx_bndcl0
|
||||
.type __mpx_bndcl0, @function
|
||||
__mpx_bndcl0:
|
||||
bndcl %rdi, %bnd0
|
||||
ret
|
||||
|
||||
.global __mpx_bndcu0
|
||||
.type __mpx_bndcu0, @function
|
||||
__mpx_bndcu0:
|
||||
bndcu %rdi, %bnd0
|
||||
ret
|
||||
|
||||
/* For bnd1 */
|
||||
|
||||
.global __mpx_bndmk1
|
||||
.type __mpx_bndmk1, @function
|
||||
__mpx_bndmk1:
|
||||
bndmk (%rdi, %rsi, 1), %bnd1
|
||||
ret
|
||||
|
||||
.global __mpx_bndcl1
|
||||
.type __mpx_bndcl1, @function
|
||||
__mpx_bndcl1:
|
||||
bndcl %rdi, %bnd1
|
||||
ret
|
||||
|
||||
.global __mpx_bndcu1
|
||||
.type __mpx_bndcu1, @function
|
||||
__mpx_bndcu1:
|
||||
bndcu %rdi, %bnd1
|
||||
ret
|
||||
|
||||
/* For bnd2 */
|
||||
|
||||
.global __mpx_bndmk2
|
||||
.type __mpx_bndmk2, @function
|
||||
__mpx_bndmk2:
|
||||
bndmk (%rdi, %rsi, 1), %bnd2
|
||||
ret
|
||||
|
||||
.global __mpx_bndcl2
|
||||
.type __mpx_bndcl2, @function
|
||||
__mpx_bndcl2:
|
||||
bndcl %rdi, %bnd2
|
||||
ret
|
||||
|
||||
.global __mpx_bndcu2
|
||||
.type __mpx_bndcu2, @function
|
||||
__mpx_bndcu2:
|
||||
bndcu %rdi, %bnd2
|
||||
ret
|
||||
|
||||
/* For bnd3 */
|
||||
|
||||
.global __mpx_bndmk3
|
||||
.type __mpx_bndmk3, @function
|
||||
__mpx_bndmk3:
|
||||
bndmk (%rdi, %rsi, 1), %bnd3
|
||||
ret
|
||||
|
||||
.global __mpx_bndcl3
|
||||
.type __mpx_bndcl3, @function
|
||||
__mpx_bndcl3:
|
||||
bndcl %rdi, %bnd3
|
||||
ret
|
||||
|
||||
.global __mpx_bndcu3
|
||||
.type __mpx_bndcu3, @function
|
||||
__mpx_bndcu3:
|
||||
bndcu %rdi, %bnd3
|
||||
ret
|
Loading…
Reference in New Issue
Block a user