Skip to content

Commit 5dd4ec8

Browse files
committed
Move emulated control register access to separate module
1 parent 31a2033 commit 5dd4ec8

File tree

3 files changed

+71
-48
lines changed

3 files changed

+71
-48
lines changed

mythril/src/emulate/controlreg.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use crate::error::{Error, Result};
2+
use crate::{vcpu, vmcs, vmexit, vmx};
3+
4+
pub fn emulate_access(
5+
vcpu: &mut vcpu::VCpu,
6+
guest_cpu: &mut vmexit::GuestCpuState,
7+
info: vmexit::CrInformation,
8+
) -> Result<()> {
9+
match info.cr_num {
10+
0 => match info.access_type {
11+
vmexit::CrAccessType::Clts => {
12+
let cr0 = vcpu.vmcs.read_field(vmcs::VmcsField::GuestCr0)?;
13+
vcpu.vmcs
14+
.write_field(vmcs::VmcsField::GuestCr0, cr0 & !0b1000)?;
15+
}
16+
vmexit::CrAccessType::MovToCr => {
17+
let reg = info.register.unwrap();
18+
let val = reg.read(&vcpu.vmcs, guest_cpu)?;
19+
vcpu.vmcs.write_field(vmcs::VmcsField::GuestCr0, val)?;
20+
}
21+
op => panic!("Unsupported MovToCr cr0 operation: {:?}", op),
22+
},
23+
3 => match info.access_type {
24+
vmexit::CrAccessType::MovToCr => {
25+
let reg = info.register.unwrap();
26+
let mut val = reg.read(&vcpu.vmcs, guest_cpu)?;
27+
28+
// If CR4.PCIDE = 1, bit 63 of the source operand to MOV to
29+
// CR3 determines whether the instruction invalidates entries
30+
// in the TLBs and the paging-structure caches. The instruction
31+
// does not modify bit 63 of CR3, which is reserved and always 0
32+
if val & (1 << 63) == 0 {
33+
// Some instructions invalidate all entries in the TLBs and
34+
// paging-structure caches—except for global translations.
35+
// An example is the MOV to CR3 instruction. Emulation of such
36+
// an instruction may require execution of the INVVPID instruction
37+
// as follows:
38+
// — The INVVPID type is single-context-retaining-globals (3).
39+
// — The VPID in the INVVPID descriptor is the one assigned to the
40+
// virtual processor whose execution is being emulated.
41+
let vpid = vcpu
42+
.vmcs
43+
.read_field(vmcs::VmcsField::VirtualProcessorId)?;
44+
vcpu.vmcs.vmx.invvpid(
45+
vmx::InvVpidMode::SingleContextRetainGlobal(
46+
vpid as u16,
47+
),
48+
)?;
49+
} else {
50+
val &= !(1 << 63);
51+
}
52+
53+
vcpu.vmcs.write_field(vmcs::VmcsField::GuestCr3, val)?;
54+
}
55+
vmexit::CrAccessType::MovFromCr => {
56+
let reg = info.register.unwrap();
57+
let val = vcpu.vmcs.read_field(vmcs::VmcsField::GuestCr3)?;
58+
reg.write(val, &mut vcpu.vmcs, guest_cpu)?;
59+
}
60+
op => panic!("Unsupported MovFromCr cr0 operation: {:?}", op),
61+
},
62+
_ => {
63+
return Err(Error::InvalidValue(format!(
64+
"Unsupported CR number access"
65+
)))
66+
}
67+
}
68+
Ok(())
69+
}

mythril/src/emulate/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod controlreg;
12
pub mod cpuid;
23
pub mod memio;
34
pub mod portio;

mythril/src/vcpu.rs

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -480,54 +480,7 @@ impl VCpu {
480480

481481
match exit.info {
482482
vmexit::ExitInformation::CrAccess(info) => {
483-
match info.cr_num {
484-
0 => match info.access_type {
485-
vmexit::CrAccessType::Clts => {
486-
let cr0 = self
487-
.vmcs
488-
.read_field(vmcs::VmcsField::GuestCr0)?;
489-
self.vmcs.write_field(
490-
vmcs::VmcsField::GuestCr0,
491-
cr0 & !0b1000,
492-
)?;
493-
}
494-
vmexit::CrAccessType::MovToCr => {
495-
let reg = info.register.unwrap();
496-
let val = reg.read(&self.vmcs, guest_cpu)?;
497-
self.vmcs
498-
.write_field(vmcs::VmcsField::GuestCr0, val)?;
499-
}
500-
op => panic!(
501-
"Unsupported MovToCr cr0 operation: {:?}",
502-
op
503-
),
504-
},
505-
3 => match info.access_type {
506-
vmexit::CrAccessType::MovToCr => {
507-
let reg = info.register.unwrap();
508-
let val = reg.read(&self.vmcs, guest_cpu)?;
509-
self.vmcs
510-
.write_field(vmcs::VmcsField::GuestCr3, val)?;
511-
}
512-
vmexit::CrAccessType::MovFromCr => {
513-
let reg = info.register.unwrap();
514-
let val = self
515-
.vmcs
516-
.read_field(vmcs::VmcsField::GuestCr3)?;
517-
reg.write(val, &mut self.vmcs, guest_cpu)?;
518-
}
519-
op => panic!(
520-
"Unsupported MovFromCr cr0 operation: {:?}",
521-
op
522-
),
523-
},
524-
_ => {
525-
return Err(Error::InvalidValue(format!(
526-
"Unsupported CR number access"
527-
)))
528-
}
529-
}
530-
483+
emulate::controlreg::emulate_access(self, guest_cpu, info)?;
531484
self.skip_emulated_instruction()?;
532485
}
533486

0 commit comments

Comments
 (0)