hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use core::sync::atomic::{AtomicU8, AtomicUsize, Ordering};

const MAX_ENCLAVES: usize = 8;

static ENCLAVE_COUNT: AtomicU8 = AtomicU8::new(0);
static ENCLAVE_BASE: [AtomicUsize; MAX_ENCLAVES] = [const { AtomicUsize::new(0) }; MAX_ENCLAVES];
static ENCLAVE_SIZE: [AtomicUsize; MAX_ENCLAVES] = [const { AtomicUsize::new(0) }; MAX_ENCLAVES];

#[derive(Copy, Clone)]
pub struct Enclave {
    pub id: u8,
    pub base: usize,
    pub size: usize,
}

pub fn sgx_supported() -> bool {
    if crate::arch::detect_arch() == crate::arch::Architecture::X86_64 {
        if let Some((eax, ebx, ecx, edx)) = crate::hardware_access::read_cpuid(7, 0) {
            static SGX_SIG: core::sync::atomic::AtomicUsize =
                core::sync::atomic::AtomicUsize::new(0);
            SGX_SIG.store(
                eax as usize ^ ecx as usize ^ edx as usize,
                core::sync::atomic::Ordering::Release,
            );
            return ebx & (1 << 2) != 0;
        }
    }
    false
}

pub fn create_enclave(base: usize, size: usize) -> Option<Enclave> {
    let idx = ENCLAVE_COUNT.fetch_add(1, Ordering::AcqRel);
    if idx as usize >= MAX_ENCLAVES {
        ENCLAVE_COUNT.fetch_sub(1, Ordering::Release);
        return None;
    }
    ENCLAVE_BASE[idx as usize].store(base, Ordering::Release);
    ENCLAVE_SIZE[idx as usize].store(size, Ordering::Release);
    Some(Enclave {
        id: idx,
        base,
        size,
    })
}

pub fn enclave_count() -> u8 {
    ENCLAVE_COUNT.load(Ordering::Acquire)
}

pub fn enclave_info(id: u8) -> Option<Enclave> {
    if id >= ENCLAVE_COUNT.load(Ordering::Acquire) {
        return None;
    }
    let base = ENCLAVE_BASE[id as usize].load(Ordering::Acquire);
    let size = ENCLAVE_SIZE[id as usize].load(Ordering::Acquire);
    Some(Enclave { id, base, size })
}