bareflank-hypervisor/example/default_rust/src/lib.rs
Rian Quinn 91886c75d9 Adds an example extension written in Rust and fixes a number of bugs
This patch:
- Adds a complete extension written in Rust, with all of the build
  system logic to support Rust development as well.
- Fixes an issues on Intel systems where the MSR bitmaps were not
  set up properly.
- Fixes a number of issues with UEFI.
- Fixes a number of issues with Windows, including a BSOD issue
  with narrow contracts.
2021-10-21 08:53:22 -06:00

371 lines
9.5 KiB
Rust

// @copyright
// Copyright (C) 2020 Assured Information Security, Inc.
//
// @copyright
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// @copyright
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// @copyright
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// -----------------------------------------------------------------------------
// Includes
// -----------------------------------------------------------------------------
#![no_std]
#![feature(thread_local)]
#![feature(panic_info_message)]
#[macro_use]
extern crate bsl;
extern crate syscall;
macro_rules! print_thread_id {
($($arg:tt)*) => {
unsafe {
print!(
" [{}{:04x}{}:{}{:04x}{}:{}{:04x}{}:{}{:04x}{}:{}{:04x}{}:{}US{}]",
bsl::cyn,
syscall::bf_tls_extid_impl(),
bsl::rst,
bsl::cyn,
syscall::bf_tls_vmid_impl(),
bsl::rst,
bsl::cyn,
syscall::bf_tls_vpid_impl(),
bsl::rst,
bsl::cyn,
syscall::bf_tls_vsid_impl(),
bsl::rst,
bsl::cyn,
syscall::bf_tls_ppid_impl(),
bsl::rst,
bsl::blu,
bsl::rst
);
}
};
}
#[path = "../include/allocated_status_t.rs"]
#[doc(hidden)]
pub mod allocated_status_t;
pub use allocated_status_t::*;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/gs_t.rs"]
#[doc(hidden)]
pub mod gs_t;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/gs_t.rs"]
#[doc(hidden)]
pub mod gs_t;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/tls_t.rs"]
#[doc(hidden)]
pub mod tls_t;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/tls_t.rs"]
#[doc(hidden)]
pub mod tls_t;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/intrinsic_t.rs"]
#[doc(hidden)]
pub mod intrinsic_t;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intrinsic_t.rs"]
#[doc(hidden)]
pub mod intrinsic_t;
pub use gs_t::*;
pub use intrinsic_t::*;
pub use tls_t::*;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/gs_initialize.rs"]
#[doc(hidden)]
pub mod gs_initialize;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/gs_initialize.rs"]
#[doc(hidden)]
pub mod gs_initialize;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/tls_initialize.rs"]
#[doc(hidden)]
pub mod tls_initialize;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/tls_initialize.rs"]
#[doc(hidden)]
pub mod tls_initialize;
pub use gs_initialize::*;
pub use tls_initialize::*;
#[path = "vp_t.rs"]
#[doc(hidden)]
pub mod vp_t;
pub use vp_t::*;
#[path = "vp_pool_t.rs"]
#[doc(hidden)]
pub mod vp_pool_t;
pub use vp_pool_t::*;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/vs_t.rs"]
#[doc(hidden)]
pub mod vs_t;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/vs_t.rs"]
#[doc(hidden)]
pub mod vs_t;
pub use vs_t::*;
#[path = "vs_pool_t.rs"]
#[doc(hidden)]
pub mod vs_pool_t;
pub use vs_pool_t::*;
#[path = "dispatch_bootstrap.rs"]
#[doc(hidden)]
pub mod dispatch_bootstrap;
pub use dispatch_bootstrap::*;
#[cfg(feature = "AuthenticAMD")]
#[path = "x64/amd/dispatch_vmexit.rs"]
#[doc(hidden)]
pub mod dispatch_vmexit;
#[cfg(feature = "GenuineIntel")]
#[path = "x64/intel/dispatch_vmexit.rs"]
#[doc(hidden)]
pub mod dispatch_vmexit;
pub use dispatch_vmexit::*;
#[path = "dispatch_fail.rs"]
#[doc(hidden)]
pub mod dispatch_fail;
pub use dispatch_fail::*;
// -----------------------------------------------------------------------------
// Globals
// -----------------------------------------------------------------------------
// TODO:
// - The use of globals requires the use of unsafe, which is not good. We
// should find a way to ensure that we can have global storage for all of
// entry points, but without the need for unsafe.
//
static mut G_SYS: syscall::BfSyscallT = syscall::BfSyscallT::new();
static mut G_INTRINSIC: crate::IntrinsicT = crate::IntrinsicT::new();
static mut G_VP_POOL: crate::VpPoolT = crate::VpPoolT::new();
static mut G_VS_POOL: crate::VsPoolT = crate::VsPoolT::new();
static mut G_GS: crate::GsT = crate::GsT::new();
#[thread_local]
static mut G_TLS: crate::TlsT = crate::TlsT::new();
// -----------------------------------------------------------------------------
// Entry Functions
// -----------------------------------------------------------------------------
#[no_mangle]
fn putchar(c: u8) {
unsafe {
syscall::bf_debug_op_write_c_impl(c);
}
}
#[no_mangle]
fn bootstrap_entry(ppid: u16) {
let ret: bsl::ErrcType;
// NOTE:
// - Call into the bootstrap handler. This entry point serves as a
// trampoline between C and C++. Specifically, the microkernel
// cannot call a member function directly, and can only call
// a C style function.
//
unsafe {
ret = dispatch_bootstrap(
&G_GS,
&mut G_TLS,
&mut G_SYS,
&G_INTRINSIC,
&mut G_VP_POOL,
&mut G_VS_POOL,
bsl::to_u16(ppid),
);
}
if !ret {
print_v!("{}", bsl::here());
syscall::bf_control_op_exit();
return;
}
// NOTE:
// - This code should never be reached. The bootstrap handler should
// always call one of the "run" ABIs to return back to the
// microkernel when a bootstrap is finished. If this is called, it
// is because the bootstrap handler returned with an error.
//
syscall::bf_control_op_exit();
}
#[no_mangle]
fn vmexit_entry(vsid: u16, exit_reason: u64) {
let ret: bsl::ErrcType;
// NOTE:
// - Call into the bootstrap handler. This entry point serves as a
// trampoline between C and C++. Specifically, the microkernel
// cannot call a member function directly, and can only call
// a C style function.
//
unsafe {
ret = dispatch_vmexit(
&G_GS,
&G_TLS,
&mut G_SYS,
&G_INTRINSIC,
&G_VP_POOL,
&G_VS_POOL,
bsl::to_u16(vsid),
bsl::to_u64(exit_reason),
);
}
if !ret {
print_v!("{}", bsl::here());
syscall::bf_control_op_exit();
return;
}
// NOTE:
// - This code should never be reached. The VMExit handler should
// always call one of the "run" ABIs to return back to the
// microkernel when a VMExit is finished. If this is called, it
// is because the VMExit handler returned with an error.
//
syscall::bf_control_op_exit();
}
#[no_mangle]
fn fail_entry(errc: u64, addr: u64) {
let ret: bsl::ErrcType;
// NOTE:
// - Call into the fast fail handler. This entry point serves as a
// trampoline between C and C++. Specifically, the microkernel
// cannot call a member function directly, and can only call
// a C style function.
//
unsafe {
ret = dispatch_fail(
&G_GS,
&G_TLS,
&G_SYS,
&G_INTRINSIC,
&G_VP_POOL,
&G_VS_POOL,
bsl::to_u64(errc),
bsl::to_u64(addr),
);
}
if !ret {
print_v!("{}", bsl::here());
syscall::bf_control_op_exit();
return;
}
// NOTE:
// - This code should never be reached. The fast fail handler should
// always call one of the "run" ABIs to return back to the
// microkernel when a fast fail is finished. If this is called, it
// is because the fast fail handler returned with an error.
//
syscall::bf_control_op_exit();
}
#[no_mangle]
pub fn ext_main_entry(version: u32) -> i32 {
let mut ret: bsl::ErrcType;
unsafe {
ret = G_SYS.initialize(
bsl::to_u32(version),
bootstrap_entry as bsl::CPtrT,
vmexit_entry as bsl::CPtrT,
fail_entry as bsl::CPtrT,
);
}
if !ret {
print_v!("{}", bsl::here());
syscall::bf_control_op_exit();
return bsl::exit_failure;
}
unsafe {
ret = gs_initialize(&mut G_GS, &G_SYS, &G_INTRINSIC);
}
if !ret {
print_v!("{}", bsl::here());
syscall::bf_control_op_exit();
return bsl::exit_failure;
}
unsafe {
G_VP_POOL.initialize(&G_GS, &G_TLS, &G_SYS, &G_INTRINSIC);
G_VS_POOL.initialize(&G_GS, &G_TLS, &G_SYS, &G_INTRINSIC);
}
syscall::bf_control_op_wait();
return bsl::exit_success;
}
#[panic_handler]
pub fn panic_implementation(info: &core::panic::PanicInfo<'_>) -> ! {
match info.message() {
Some(s) => print!("{}", s),
None => print!("unknown panic occurred\n"),
}
syscall::bf_control_op_exit();
loop {}
}