mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
hypervisor: emulator: Add a negative instruction fetch unit test
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
251434862f
commit
f6892f2ede
@ -268,7 +268,7 @@ mod tests {
|
||||
let cpu_id = 0;
|
||||
let insn = [0x48, 0x89, 0xd8];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![Register::RBX => rbx], None);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let rax: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -288,7 +288,7 @@ mod tests {
|
||||
let cpu_id = 0;
|
||||
let insn = [0x48, 0xb8, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let rax: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -314,7 +314,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax],
|
||||
Some((rax + rax, &memory)),
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
rax = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -334,7 +334,7 @@ mod tests {
|
||||
let cpu_id = 0;
|
||||
let insn = [0xb0, 0x11];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let al = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -354,7 +354,7 @@ mod tests {
|
||||
let cpu_id = 0;
|
||||
let insn = [0xb8, 0x11, 0x00, 0x00, 0x00];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let eax = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -374,7 +374,7 @@ mod tests {
|
||||
let cpu_id = 0;
|
||||
let insn = [0x48, 0xc7, 0xc0, 0x44, 0x33, 0x22, 0x11];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let rax: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -399,7 +399,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax, Register::DH => dh.into()],
|
||||
None,
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let mut memory: [u8; 1] = [0; 1];
|
||||
vmm.read_memory(rax, &mut memory).unwrap();
|
||||
@ -422,7 +422,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax, Register::ESI => esi.into()],
|
||||
None,
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let mut memory: [u8; 4] = [0; 4];
|
||||
vmm.read_memory(rax, &mut memory).unwrap();
|
||||
@ -446,7 +446,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax, Register::EDI => edi.into()],
|
||||
None,
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let mut memory: [u8; 4] = [0; 4];
|
||||
vmm.read_memory(rax + displacement, &mut memory).unwrap();
|
||||
@ -471,7 +471,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax],
|
||||
Some((rax + displacement, &memory)),
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let new_eax = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -498,7 +498,7 @@ mod tests {
|
||||
hashmap![Register::RAX => rax],
|
||||
Some((rax + displacement, &memory)),
|
||||
);
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
let new_al = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -525,7 +525,7 @@ mod tests {
|
||||
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
|
||||
];
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
||||
vmm.emulate_insn(cpu_id, &insn, Some(2));
|
||||
assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
|
||||
|
||||
let rbx: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -554,7 +554,7 @@ mod tests {
|
||||
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
||||
// Only run the first instruction.
|
||||
vmm.emulate_first_insn(cpu_id, &insn);
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||
|
||||
assert_eq!(ip + 7 as u64, vmm.cpu_state(cpu_id).unwrap().ip());
|
||||
|
||||
@ -587,7 +587,7 @@ mod tests {
|
||||
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
||||
// Run the 2 first instructions.
|
||||
vmm.emulate_insn(cpu_id, &insn, Some(2));
|
||||
assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
|
||||
|
||||
assert_eq!(ip + 7 + 4 as u64, vmm.cpu_state(cpu_id).unwrap().ip());
|
||||
|
||||
|
@ -650,21 +650,26 @@ mod mock_vmm {
|
||||
vmm
|
||||
}
|
||||
|
||||
pub fn emulate_insn(&mut self, cpu_id: usize, insn: &[u8], num_insn: Option<usize>) {
|
||||
pub fn emulate_insn(
|
||||
&mut self,
|
||||
cpu_id: usize,
|
||||
insn: &[u8],
|
||||
num_insn: Option<usize>,
|
||||
) -> MockResult {
|
||||
let ip = self.cpu_state(cpu_id).unwrap().ip();
|
||||
let mut emulator = Emulator::new(self);
|
||||
|
||||
let new_state = emulator
|
||||
.emulate_insn_stream(cpu_id, &insn, num_insn)
|
||||
.unwrap();
|
||||
let new_state = emulator.emulate_insn_stream(cpu_id, &insn, num_insn)?;
|
||||
if num_insn.is_none() {
|
||||
assert_eq!(ip + insn.len() as u64, new_state.ip());
|
||||
}
|
||||
|
||||
self.set_cpu_state(cpu_id, new_state).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn emulate_first_insn(&mut self, cpu_id: usize, insn: &[u8]) {
|
||||
pub fn emulate_first_insn(&mut self, cpu_id: usize, insn: &[u8]) -> MockResult {
|
||||
self.emulate_insn(cpu_id, insn, Some(1))
|
||||
}
|
||||
}
|
||||
@ -760,7 +765,7 @@ mod tests {
|
||||
];
|
||||
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((ip, &memory)));
|
||||
vmm.emulate_insn(cpu_id, &insn, Some(2));
|
||||
assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
|
||||
|
||||
let rax: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -797,7 +802,7 @@ mod tests {
|
||||
];
|
||||
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((ip, &memory)));
|
||||
vmm.emulate_insn(cpu_id, &insn, Some(2));
|
||||
assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
|
||||
|
||||
let rbx: u64 = vmm
|
||||
.cpu_state(cpu_id)
|
||||
@ -808,4 +813,29 @@ mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Emulate truncated instruction stream, which should cause a fetch.
|
||||
//
|
||||
// mov rax, 0x1000
|
||||
// Test with a first instruction truncated and a bad fetched instruction.
|
||||
// Verify that the instruction emulation returns an error.
|
||||
fn test_fetch_bad_insn() -> MockResult {
|
||||
let ip: u64 = 0x1000;
|
||||
let cpu_id = 0;
|
||||
let memory = [
|
||||
// Code at IP
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
];
|
||||
let insn = [
|
||||
// First instruction is truncated
|
||||
0x48, 0xc7, 0xc0, 0x00, // mov rax, 0x1000 -- Missing bytes: 0x00, 0x10, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((ip, &memory)));
|
||||
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user