Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor api.rs, using VmState on Vm #27

Merged
merged 33 commits into from
Aug 20, 2019
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9e930e5
Prevents C codes from accessing inner-struct fields. Instead, makes g…
efenniht Aug 16, 2019
7faac80
For consistent memory layout, preserves #[repr(C)] of VCpu. And typo …
efenniht Aug 16, 2019
86b96fc
Refactor api_debug_log.
efenniht Aug 16, 2019
cf42465
Oxidize api.rs.
efenniht Aug 16, 2019
deca8a1
Oxidize api.rs (cont'd)
efenniht Aug 16, 2019
fb88e1d
Bug fix, by giving better name `is_waiter_list_empty` instead of `any…
efenniht Aug 16, 2019
93f751c
Typo, and use `is_null()`
efenniht Aug 16, 2019
a6a4089
Mutability of Vm is now guranteed by SpinLock, thus change `*mut Vm` …
efenniht Aug 17, 2019
9e61ebc
Oxidizes `vcpu_handle_page_fault` and reduces `mut`.
efenniht Aug 19, 2019
8e47489
Removes lock_hypervisor_table and rustfmt.
efenniht Aug 19, 2019
426ff49
Initializes Mailbox in the same order of fields, and removes `mut` on…
efenniht Aug 19, 2019
1e3e8fa
Use is_{none, some}() rather than if let Some(_) and if let None.
efenniht Aug 19, 2019
d015065
Refactors to use Option::filter rather than verbose if.
efenniht Aug 19, 2019
ab3e8d0
Early returns and remove unnecessary type hint
efenniht Aug 19, 2019
32f9b4a
We don't need to struggle with vm's buffer.
efenniht Aug 19, 2019
b702cce
It is weird that Hafnium panics as the VM sends non-UTF8 bytes. Just …
efenniht Aug 19, 2019
d37feaa
Leaves TODO.
efenniht Aug 19, 2019
ff85cfc
Renames VmState to VmInner.
efenniht Aug 19, 2019
7eeee87
Write a comment about publicity of stack_bottom.
efenniht Aug 19, 2019
aa51119
Making a safe wrapper function to get the root of PageTable of Vm (no…
efenniht Aug 19, 2019
d82fe49
Add a kind comment
efenniht Aug 19, 2019
61c77e4
Improve comments.
efenniht Aug 20, 2019
479a241
is_none().
efenniht Aug 20, 2019
0749e40
TODO about spci_architected_message.c.
efenniht Aug 20, 2019
b86e4d9
Removes wrongly ported line (why did I write assert!(false)?)
efenniht Aug 20, 2019
020277a
Comments about forward declaration of vcpu and vm.
efenniht Aug 20, 2019
e844cb9
Edits wrong comments.
efenniht Aug 20, 2019
43f80ab
Returns Result<(), ()> rather than Option<()>.
efenniht Aug 20, 2019
c6d48d3
Comments about Result.
efenniht Aug 20, 2019
1708acd
Typo
efenniht Aug 20, 2019
653ef12
Use Result<(), ()> rather than Option<()>, in api.rs.
efenniht Aug 20, 2019
bec726a
Use inner for VmInner, rather than state.
efenniht Aug 20, 2019
79cdabe
TODO about making a trait generalizing MPool
efenniht Aug 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
910 changes: 182 additions & 728 deletions hfo2/src/api.rs

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions hfo2/src/arch/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use core::mem;

use crate::cpu::*;
use crate::types::*;

const FLOAT_REG_BYTES: usize = 16;
Expand Down Expand Up @@ -84,6 +85,26 @@ pub struct ArchRegs {
peripherals: ArchPeriRegs,
}

// from src/arch/aarch64/hypervisor/offset.h
// Note: always keep this constants same as ones in offset.h
const CPU_ID: usize = 0;
const CPU_STACK_BOTTOM: usize = 8;
const VCPU_REGS: usize = 32;
const REGS_LAZY: usize = 264;
const REGS_FREGS: usize = REGS_LAZY + 232;
//#[cfg(any(feature = "GIC_VERSION=3", feature = "GIC_VERSION=4"))]
const REGS_GIC: usize = REGS_FREGS + 528;

/// Checks above constants are correct.
pub fn arch_cpu_module_init() {
efenniht marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(offset_of!(Cpu, id), CPU_ID);
assert_eq!(offset_of!(Cpu, stack_bottom), CPU_STACK_BOTTOM);
assert_eq!(offset_of!(VCpu, regs), VCPU_REGS);
assert_eq!(offset_of!(ArchRegs, lazy), REGS_LAZY);
assert_eq!(offset_of!(ArchRegs, fp), REGS_FREGS);
assert_eq!(offset_of!(ArchRegs, gic_ich_hcr_el2), REGS_GIC);
}

#[repr(C)]
pub struct ArchSysRegs {
vmpidr_el2: uintreg_t,
Expand Down
4 changes: 4 additions & 0 deletions hfo2/src/arch/fake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@ pub struct ArchRegs {
vcpu_id: cpu_id_t,
virtual_interrupt: bool,
}

pub fn arch_cpu_module_init() {
// Do nothing.
}
57 changes: 42 additions & 15 deletions hfo2/src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ pub struct Cpu {
pub id: cpu_id_t,

/// Pointer to bottom of the stack.
stack_bottom: *mut c_void,
/// `pub` here is only required by `arch_cpu_module_init`.
pub stack_bottom: *mut c_void,
efenniht marked this conversation as resolved.
Show resolved Hide resolved

/// Enabling/disabling irqs are counted per-cpu. They are enabled when the count is zero, and
/// disabled when it's non-zero.
Expand Down Expand Up @@ -184,6 +185,8 @@ pub unsafe extern "C" fn cpu_module_init(cpu_ids: *mut cpu_id_t, count: usize) {
let boot_cpu_id: cpu_id_t = cpus.get_ref()[0].id;
let mut found_boot_cpu: bool = false;

arch_cpu_module_init();

cpu_count = count as u32;

// Initialize CPUs with the IDs from the configuration passed in. The
Expand Down Expand Up @@ -321,6 +324,36 @@ pub unsafe extern "C" fn vcpu_index(vcpu: *const VCpu) -> spci_vcpu_index_t {
index as u16
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_get_regs(vcpu: *mut VCpu) -> *mut ArchRegs {
&mut (*vcpu).regs
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_get_regs_const(vcpu: *const VCpu) -> *const ArchRegs {
&(*vcpu).regs
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_get_vm(vcpu: *mut VCpu) -> *mut Vm {
(*vcpu).vm
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_get_cpu(vcpu: *mut VCpu) -> *mut Cpu {
(*vcpu).cpu
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_set_cpu(vcpu: *mut VCpu, cpu: *mut Cpu) {
(*vcpu).cpu = cpu;
}

#[no_mangle]
pub unsafe extern "C" fn vcpu_get_interrupts(vcpu: *mut VCpu) -> *mut Interrupts {
&mut (*vcpu).interrupts
}

/// Check whether the given vcpu_state is an off state, for the purpose of
/// turning vCPUs on and off. Note that aborted still counts as on in this
/// context.
Expand Down Expand Up @@ -368,7 +401,7 @@ pub unsafe extern "C" fn vcpu_secondary_reset_and_start(
false,
(*vm).id,
vcpu_index(vcpu) as cpu_id_t,
(*vm).ptable.root,
(*vm).get_ptable_raw(),
);
vcpu_on(vcpu_execution_locked, entry, arg);
}
Expand All @@ -385,14 +418,11 @@ pub unsafe extern "C" fn vcpu_secondary_reset_and_start(
#[no_mangle]
pub unsafe extern "C" fn vcpu_handle_page_fault(
current: *const VCpu,
f: *mut VCpuFaultInfo,
f: *const VCpuFaultInfo,
) -> bool {
let vm = (*current).vm;
let mut mode = mem::uninitialized(); // to avoid use-of-uninitialized error
let mask = (*f).mode | Mode::INVALID;
let resume;

sl_lock(&(*vm).lock);
let vm_inner = (*vm).inner.lock();

// Check if this is a legitimate fault, i.e., if the page table doesn't
// allow the access attemped by the VM.
Expand All @@ -402,14 +432,11 @@ pub unsafe extern "C" fn vcpu_handle_page_fault(
// invalidations while holding the VM lock, so we don't need to do
// anything else to recover from it. (Acquiring/releasing the lock
// ensured that the invalidations have completed.)
resume = mm_vm_get_mode(
&mut (*vm).ptable,
(*f).ipaddr,
ipa_add((*f).ipaddr, 1),
&mut mode,
) && (mode & mask) == (*f).mode;

sl_unlock(&(*vm).lock);
let resume = vm_inner
.ptable
.get_mode((*f).ipaddr, ipa_add((*f).ipaddr, 1))
.map(|mode| mode & mask == (*f).mode)
.unwrap_or(false);

if !resume {
dlog!(
Expand Down
21 changes: 1 addition & 20 deletions hfo2/src/dlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use core::fmt;

use crate::spinlock::*;
use crate::vm::*;
use crate::types::*;

extern "C" {
fn plat_console_putchar(c: u8);
Expand Down Expand Up @@ -54,22 +54,3 @@ pub fn _print(args: fmt::Arguments) {
use core::fmt::Write;
WRITER.lock().write_fmt(args).unwrap();
}

/// Send the contents of the given VM's log buffer to the log, preceded by the
/// VM ID and followed by a newline.
pub unsafe extern "C" fn dlog_flush_vm_buffer(vm: VmLocked) {
use core::fmt::Write;
let mut writer = WRITER.lock();

writer.write_str("VM ");
writer.write_fmt(format_args!("{}", (*vm.vm).id));
writer.write_str(": ");

for i in 0..(*vm.vm).log_buffer_length {
plat_console_putchar((*vm.vm).log_buffer[i]);
(*vm.vm).log_buffer[i] = '\0' as u32 as u8;
}

(*vm.vm).log_buffer_length = 0;
plat_console_putchar('\n' as u32 as u8);
}
1 change: 1 addition & 0 deletions hfo2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![feature(maybe_uninit_ref)]
#![feature(ptr_offset_from)]
#![feature(const_raw_ptr_to_usize_cast)]
#![feature(bind_by_move_pattern_guards)]

#[macro_use]
extern crate bitflags;
Expand Down
18 changes: 15 additions & 3 deletions hfo2/src/mm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ bitflags! {
}
}

impl Mode {
/// Check that the mode indicates memory that is vaid, owned and exclusive.
pub fn valid_owned_and_exclusive(&self) -> bool {
(*self & (Mode::INVALID | Mode::UNOWNED | Mode::SHARED)).is_empty()
}
}

bitflags! {
/// Flags for memory management operations.
struct Flags: u32 {
Expand All @@ -160,7 +167,7 @@ type ptable_addr_t = uintvaddr_t;
const_assert_eq!(addr_size_eq; mem::size_of::<ptable_addr_t>(), mem::size_of::<uintpaddr_t>());

/// The hypervisor page table.
static HYPERVISOR_PAGE_TABLE: SpinLock<PageTable<Stage1>> =
pub static HYPERVISOR_PAGE_TABLE: SpinLock<PageTable<Stage1>> =
SpinLock::new(unsafe { PageTable::null() });

/// Is stage2 invalidation enabled?
Expand Down Expand Up @@ -801,8 +808,13 @@ impl<S: Stage> PageTable<S> {
mem::forget(self);
}

fn get_raw(&self) -> *const RawPage {
pa_addr(self.root) as *const RawPage
/// Returns the address of the root of this page table. The return type is
/// paddr_t, physically addressed raw pointer. That means calling this
/// method is safe but accessing the memory of returned address is unsafe.
/// TODO: Better return type is PAddr<RawPage> (meaning of *mut RawPage
/// which is address physically.)
pub fn as_raw(&self) -> paddr_t {
self.root
}

fn deref(&self) -> &[RawPageTable] {
Expand Down
17 changes: 17 additions & 0 deletions hfo2/src/spinlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,23 @@ impl<T> SpinLock<T> {
pub unsafe fn get_mut_unchecked(&self) -> &mut T {
&mut *self.data.get()
}

pub fn lock_both<'s>(
lhs: &'s Self,
rhs: &'s Self,
) -> (SpinLockGuard<'s, T>, SpinLockGuard<'s, T>) {
RawSpinLock::lock_both(&lhs.lock, &rhs.lock);
(
SpinLockGuard {
lock: lhs,
_marker: PhantomData,
},
SpinLockGuard {
lock: rhs,
_marker: PhantomData,
},
)
}
}

pub struct SpinLockGuard<'s, T> {
Expand Down
Loading