Skip to content

Commit 6f0dafc

Browse files
committed
Remove per-VM lock
This drastically increases the granularity of the locking in most aspects of the hypervisor
1 parent 6266398 commit 6f0dafc

File tree

11 files changed

+165
-173
lines changed

11 files changed

+165
-173
lines changed

mythril/src/emulate/memio.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,17 @@ fn process_memio_op(
401401
.read_field(vmcs::VmcsField::VmExitInstructionLen)?;
402402
let ip = vcpu.vmcs.read_field(vmcs::VmcsField::GuestRip)?;
403403

404-
let mut vm = vcpu.vm.write();
405404
let ip_addr = memory::GuestVirtAddr::new(ip, &vcpu.vmcs)?;
406-
let view = memory::GuestAddressSpaceViewMut::from_vmcs(
405+
let view = memory::GuestAddressSpaceView::from_vmcs(
407406
&vcpu.vmcs,
408-
&mut vm.guest_space,
407+
&vcpu.vm.guest_space,
409408
)?;
410409

411410
let bytes = view.read_bytes(
412411
ip_addr,
413412
instruction_len as usize,
414413
memory::GuestAccess::Read(memory::PrivilegeLevel(0)),
415414
)?;
416-
drop(vm);
417415

418416
let efer = vcpu.vmcs.read_field(vmcs::VmcsField::GuestIa32Efer)?;
419417
// TODO: 16bit support
@@ -457,8 +455,7 @@ pub fn handle_ept_violation(
457455
event: DeviceEvent,
458456
responses: &mut ResponseEventArray,
459457
) -> Result<()> {
460-
let mut vm = vcpu.vm.write();
461-
vm.dispatch_event(addr, event, vcpu, responses)
458+
vcpu.vm.dispatch_event(addr, event, vcpu, responses)
462459
}
463460

464461
let addr = memory::GuestPhysAddr::new(

mythril/src/emulate/portio.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ fn emulate_outs(
1313
exit: vmexit::IoInstructionInformation,
1414
responses: &mut ResponseEventArray,
1515
) -> Result<()> {
16-
let mut vm = vcpu.vm.write();
17-
1816
let linear_addr =
1917
vcpu.vmcs.read_field(vmcs::VmcsField::GuestLinearAddress)?;
2018
let guest_addr = memory::GuestVirtAddr::new(linear_addr, &vcpu.vmcs)?;
@@ -23,9 +21,9 @@ fn emulate_outs(
2321
// assume that is requires supervisor
2422
let access = memory::GuestAccess::Read(memory::PrivilegeLevel(0));
2523

26-
let view = memory::GuestAddressSpaceViewMut::from_vmcs(
24+
let view = memory::GuestAddressSpaceView::from_vmcs(
2725
&vcpu.vmcs,
28-
&mut vm.guest_space,
26+
&vcpu.vm.guest_space,
2927
)?;
3028

3129
// FIXME: The direction we read is determined by the DF flag (I think)
@@ -39,7 +37,7 @@ fn emulate_outs(
3937
// FIXME: Actually test for REP
4038
for chunk in bytes.chunks_exact(exit.size as usize) {
4139
let request = PortWriteRequest::try_from(chunk)?;
42-
vm.dispatch_event(
40+
vcpu.vm.dispatch_event(
4341
port,
4442
DeviceEvent::PortWrite(port, request),
4543
vcpu,
@@ -59,8 +57,6 @@ fn emulate_ins(
5957
exit: vmexit::IoInstructionInformation,
6058
responses: &mut ResponseEventArray,
6159
) -> Result<()> {
62-
let mut vm = vcpu.vm.write();
63-
6460
let linear_addr =
6561
vcpu.vmcs.read_field(vmcs::VmcsField::GuestLinearAddress)?;
6662
let guest_addr = memory::GuestVirtAddr::new(linear_addr, &vcpu.vmcs)?;
@@ -69,17 +65,17 @@ fn emulate_ins(
6965
let mut bytes = vec![0u8; guest_cpu.rcx as usize];
7066
for chunk in bytes.chunks_exact_mut(exit.size as usize) {
7167
let request = PortReadRequest::try_from(chunk)?;
72-
vm.dispatch_event(
68+
vcpu.vm.dispatch_event(
7369
port,
7470
DeviceEvent::PortRead(port, request),
7571
vcpu,
7672
responses,
7773
)?;
7874
}
7975

80-
let mut view = memory::GuestAddressSpaceViewMut::from_vmcs(
76+
let view = memory::GuestAddressSpaceView::from_vmcs(
8177
&vcpu.vmcs,
82-
&mut vm.guest_space,
78+
&vcpu.vm.guest_space,
8379
)?;
8480
view.write_bytes(guest_addr, &bytes, access)?;
8581

@@ -98,12 +94,11 @@ pub fn emulate_portio(
9894
(exit.port, exit.input, exit.size, exit.string);
9995

10096
if !string {
101-
let mut vm = vcpu.vm.write();
10297
if !input {
10398
let arr = (guest_cpu.rax as u32).to_be_bytes();
10499
let request =
105100
PortWriteRequest::try_from(&arr[4 - size as usize..])?;
106-
vm.dispatch_event(
101+
vcpu.vm.dispatch_event(
107102
port,
108103
DeviceEvent::PortWrite(port, request),
109104
vcpu,
@@ -113,7 +108,7 @@ pub fn emulate_portio(
113108
let mut arr = [0u8; 4];
114109
let request =
115110
PortReadRequest::try_from(&mut arr[4 - size as usize..])?;
116-
vm.dispatch_event(
111+
vcpu.vm.dispatch_event(
117112
port,
118113
DeviceEvent::PortRead(port, request),
119114
vcpu,

mythril/src/kmain.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,16 @@ fn build_vm(
4040
cfg: &config::UserVmConfig,
4141
info: &BootInfo,
4242
add_uart: bool,
43-
) -> Arc<RwLock<vm::VirtualMachine>> {
43+
) -> Arc<vm::VirtualMachine> {
4444
let physical_config = if add_uart == false {
4545
vm::PhysicalDeviceConfig::default()
4646
} else {
4747
vm::PhysicalDeviceConfig {
48-
serial: Some(
48+
serial: RwLock::new(Some(
4949
physdev::com::Uart8250::new(0x3f8)
5050
.expect("Failed to create UART"),
51-
),
52-
ps2_keyboard: None,
51+
)),
52+
ps2_keyboard: RwLock::new(None),
5353
}
5454
};
5555

mythril/src/memory.rs

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use crate::vmcs;
33
use alloc::boxed::Box;
44
use alloc::vec::Vec;
55
use bitflags::bitflags;
6-
use core::borrow::{Borrow, BorrowMut};
76
use core::convert::TryFrom;
87
use core::default::Default;
98
use core::fmt;
109
use core::ops::{Add, Deref, Index, IndexMut};
1110
use num_enum::TryFromPrimitive;
11+
use spin::RwLock;
1212
use ux;
1313
use x86::bits64::paging::*;
1414
use x86::controlregs::Cr0;
@@ -255,7 +255,7 @@ impl HostPhysFrame {
255255
}
256256

257257
pub struct GuestAddressSpace {
258-
root: Box<EptPml4Table>,
258+
root: RwLock<Box<EptPml4Table>>,
259259
}
260260

261261
#[derive(Copy, Clone, Debug)]
@@ -271,21 +271,26 @@ pub enum GuestAccess {
271271
impl GuestAddressSpace {
272272
pub fn new() -> Result<Self> {
273273
Ok(GuestAddressSpace {
274-
root: Box::new(EptPml4Table::default()),
274+
root: RwLock::new(Box::new(EptPml4Table::default())),
275275
})
276276
}
277277

278278
pub fn map_frame(
279-
&mut self,
279+
&self,
280280
guest_addr: GuestPhysAddr,
281281
host_frame: HostPhysFrame,
282282
readonly: bool,
283283
) -> Result<()> {
284-
map_guest_memory(&mut self.root, guest_addr, host_frame, readonly)
284+
map_guest_memory(
285+
&mut self.root.write(),
286+
guest_addr,
287+
host_frame,
288+
readonly,
289+
)
285290
}
286291

287292
pub fn map_new_frame(
288-
&mut self,
293+
&self,
289294
guest_addr: GuestPhysAddr,
290295
readonly: bool,
291296
) -> Result<()> {
@@ -297,7 +302,7 @@ impl GuestAddressSpace {
297302

298303
pub fn eptp(&self) -> u64 {
299304
// //TODO: check available memory types
300-
(&*self.root as *const _ as u64) | (4 - 1) << 3 | 6
305+
(&*(*self.root.read()) as *const _ as u64) | (4 - 1) << 3 | 6
301306
}
302307

303308
pub fn translate_linear_address(
@@ -360,7 +365,7 @@ impl GuestAddressSpace {
360365
&self,
361366
addr: GuestPhysAddr,
362367
) -> Result<HostPhysFrame> {
363-
let ept_pml4e = &self.root[addr.p4_index()];
368+
let ept_pml4e = &self.root.read()[addr.p4_index()];
364369
if ept_pml4e.is_unused() {
365370
return Err(Error::InvalidValue(
366371
"No PML4 entry for GuestPhysAddr".into(),
@@ -440,7 +445,7 @@ impl GuestAddressSpace {
440445
}
441446

442447
pub fn write_bytes(
443-
&mut self,
448+
&self,
444449
cr3: GuestPhysAddr,
445450
addr: GuestVirtAddr,
446451
mut bytes: &[u8],
@@ -471,25 +476,20 @@ impl GuestAddressSpace {
471476
}
472477
}
473478

474-
pub type GuestAddressSpaceView<'a> =
475-
GuestAddressSpaceWrapper<&'a GuestAddressSpace>;
476-
pub type GuestAddressSpaceViewMut<'a> =
477-
GuestAddressSpaceWrapper<&'a mut GuestAddressSpace>;
478-
479-
pub struct GuestAddressSpaceWrapper<T> {
480-
space: T,
479+
pub struct GuestAddressSpaceView<'a> {
480+
space: &'a GuestAddressSpace,
481481
cr3: GuestPhysAddr,
482482
}
483483

484-
impl<T> GuestAddressSpaceWrapper<T>
485-
where
486-
T: Borrow<GuestAddressSpace>,
487-
{
488-
pub fn new(cr3: GuestPhysAddr, space: T) -> Self {
484+
impl<'a> GuestAddressSpaceView<'a> {
485+
pub fn new(cr3: GuestPhysAddr, space: &'a GuestAddressSpace) -> Self {
489486
Self { space, cr3 }
490487
}
491488

492-
pub fn from_vmcs(vmcs: &vmcs::ActiveVmcs, space: T) -> Result<Self> {
489+
pub fn from_vmcs(
490+
vmcs: &vmcs::ActiveVmcs,
491+
space: &'a GuestAddressSpace,
492+
) -> Result<Self> {
493493
let cr3 = vmcs.read_field(vmcs::VmcsField::GuestCr3)?;
494494
let cr3 = GuestPhysAddr::new(cr3);
495495
Ok(Self { space, cr3 })
@@ -500,7 +500,7 @@ where
500500
addr: GuestVirtAddr,
501501
access: GuestAccess,
502502
) -> Result<FrameIter> {
503-
self.space.borrow().frame_iter(self.cr3, addr, access)
503+
self.space.frame_iter(self.cr3, addr, access)
504504
}
505505

506506
pub fn read_bytes(
@@ -509,46 +509,32 @@ where
509509
length: usize,
510510
access: GuestAccess,
511511
) -> Result<Vec<u8>> {
512-
self.space
513-
.borrow()
514-
.read_bytes(self.cr3, addr, length, access)
512+
self.space.read_bytes(self.cr3, addr, length, access)
515513
}
516514

517515
pub fn translate_linear_address(
518516
&self,
519517
addr: GuestVirtAddr,
520518
access: GuestAccess,
521519
) -> Result<GuestPhysAddr> {
522-
self.space
523-
.borrow()
524-
.translate_linear_address(self.cr3, addr, access)
520+
self.space.translate_linear_address(self.cr3, addr, access)
525521
}
526-
}
527522

528-
impl<T> GuestAddressSpaceWrapper<T>
529-
where
530-
T: BorrowMut<GuestAddressSpace>,
531-
{
532523
pub fn write_bytes(
533-
&mut self,
524+
&self,
534525
addr: GuestVirtAddr,
535526
bytes: &[u8],
536527
access: GuestAccess,
537528
) -> Result<()> {
538-
self.space
539-
.borrow_mut()
540-
.write_bytes(self.cr3, addr, bytes, access)
529+
self.space.write_bytes(self.cr3, addr, bytes, access)
541530
}
542531
}
543532

544-
impl<T> Deref for GuestAddressSpaceWrapper<T>
545-
where
546-
T: Borrow<GuestAddressSpace>,
547-
{
548-
type Target = T;
533+
impl<'a> Deref for GuestAddressSpaceView<'a> {
534+
type Target = GuestAddressSpace;
549535

550-
fn deref(&self) -> &Self::Target {
551-
&self.space
536+
fn deref(&self) -> &'a Self::Target {
537+
self.space
552538
}
553539
}
554540

mythril/src/percore.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,12 @@ pub fn read_core_id() -> CoreId {
111111
}
112112

113113
#[doc(hidden)]
114-
pub unsafe fn get_pre_core_impl<T>(t: &T) -> &T {
114+
pub unsafe fn get_per_core_impl<T>(t: &T) -> &T {
115115
core::mem::transmute(per_core_address(t as *const T as *const u8))
116116
}
117117

118118
#[doc(hidden)]
119-
pub unsafe fn get_pre_core_mut_impl<T>(t: &mut T) -> &mut T {
119+
pub unsafe fn get_per_core_mut_impl<T>(t: &mut T) -> &mut T {
120120
core::mem::transmute(per_core_address(t as *const T as *const u8))
121121
}
122122

@@ -125,7 +125,7 @@ macro_rules! get_per_core {
125125
($name:ident) => {
126126
#[allow(unused_unsafe)]
127127
unsafe {
128-
$crate::percore::get_pre_core_impl(&mut $name)
128+
$crate::percore::get_per_core_impl(&$name)
129129
}
130130
};
131131
}
@@ -135,7 +135,7 @@ macro_rules! get_per_core_mut {
135135
($name:ident) => {
136136
#[allow(unused_unsafe)]
137137
unsafe {
138-
$crate::percore::get_pre_core_mut_impl(&mut $name)
138+
$crate::percore::get_per_core_mut_impl(&mut $name)
139139
}
140140
};
141141
}
@@ -150,6 +150,12 @@ macro_rules! __declare_per_core_internal {
150150

151151
declare_per_core!($($t)*);
152152
};
153+
($(#[$attr:meta])* ($($vis:tt)*) static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
154+
#[link_section = ".per_core"]
155+
$($vis)* static $N: $T = $e;
156+
157+
declare_per_core!($($t)*);
158+
};
153159
() => ()
154160
}
155161

@@ -165,5 +171,15 @@ macro_rules! declare_per_core {
165171
($(#[$attr:meta])* pub ($($vis:tt)+) static mut $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
166172
__declare_per_core_internal!($(#[$attr])* (pub ($($vis)+)) static mut $N : $T = $e; $($t)*);
167173
};
174+
// Rules for immutable variables
175+
($(#[$attr:meta])* static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
176+
__declare_per_core_internal!($(#[$attr])* () static $N : $T = $e; $($t)*);
177+
};
178+
($(#[$attr:meta])* pub static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
179+
__declare_per_core_internal!($(#[$attr])* (pub) static $N : $T = $e; $($t)*);
180+
};
181+
($(#[$attr:meta])* pub ($($vis:tt)+) static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
182+
__declare_per_core_internal!($(#[$attr])* (pub ($($vis)+)) static $N : $T = $e; $($t)*);
183+
};
168184
() => ()
169185
}

0 commit comments

Comments
 (0)