mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-22 07:51:16 +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 cpu_id = 0;
|
||||||
let insn = [0x48, 0x89, 0xd8];
|
let insn = [0x48, 0x89, 0xd8];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![Register::RBX => rbx], None);
|
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
|
let rax: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -288,7 +288,7 @@ mod tests {
|
|||||||
let cpu_id = 0;
|
let cpu_id = 0;
|
||||||
let insn = [0x48, 0xb8, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11];
|
let insn = [0x48, 0xb8, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
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
|
let rax: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -314,7 +314,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax],
|
hashmap![Register::RAX => rax],
|
||||||
Some((rax + rax, &memory)),
|
Some((rax + rax, &memory)),
|
||||||
);
|
);
|
||||||
vmm.emulate_first_insn(cpu_id, &insn);
|
assert!(vmm.emulate_first_insn(cpu_id, &insn).is_ok());
|
||||||
|
|
||||||
rax = vmm
|
rax = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -334,7 +334,7 @@ mod tests {
|
|||||||
let cpu_id = 0;
|
let cpu_id = 0;
|
||||||
let insn = [0xb0, 0x11];
|
let insn = [0xb0, 0x11];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
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
|
let al = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -354,7 +354,7 @@ mod tests {
|
|||||||
let cpu_id = 0;
|
let cpu_id = 0;
|
||||||
let insn = [0xb8, 0x11, 0x00, 0x00, 0x00];
|
let insn = [0xb8, 0x11, 0x00, 0x00, 0x00];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
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
|
let eax = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -374,7 +374,7 @@ mod tests {
|
|||||||
let cpu_id = 0;
|
let cpu_id = 0;
|
||||||
let insn = [0x48, 0xc7, 0xc0, 0x44, 0x33, 0x22, 0x11];
|
let insn = [0x48, 0xc7, 0xc0, 0x44, 0x33, 0x22, 0x11];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], None);
|
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
|
let rax: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -399,7 +399,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax, Register::DH => dh.into()],
|
hashmap![Register::RAX => rax, Register::DH => dh.into()],
|
||||||
None,
|
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];
|
let mut memory: [u8; 1] = [0; 1];
|
||||||
vmm.read_memory(rax, &mut memory).unwrap();
|
vmm.read_memory(rax, &mut memory).unwrap();
|
||||||
@ -422,7 +422,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax, Register::ESI => esi.into()],
|
hashmap![Register::RAX => rax, Register::ESI => esi.into()],
|
||||||
None,
|
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];
|
let mut memory: [u8; 4] = [0; 4];
|
||||||
vmm.read_memory(rax, &mut memory).unwrap();
|
vmm.read_memory(rax, &mut memory).unwrap();
|
||||||
@ -446,7 +446,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax, Register::EDI => edi.into()],
|
hashmap![Register::RAX => rax, Register::EDI => edi.into()],
|
||||||
None,
|
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];
|
let mut memory: [u8; 4] = [0; 4];
|
||||||
vmm.read_memory(rax + displacement, &mut memory).unwrap();
|
vmm.read_memory(rax + displacement, &mut memory).unwrap();
|
||||||
@ -471,7 +471,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax],
|
hashmap![Register::RAX => rax],
|
||||||
Some((rax + displacement, &memory)),
|
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
|
let new_eax = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -498,7 +498,7 @@ mod tests {
|
|||||||
hashmap![Register::RAX => rax],
|
hashmap![Register::RAX => rax],
|
||||||
Some((rax + displacement, &memory)),
|
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
|
let new_al = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -525,7 +525,7 @@ mod tests {
|
|||||||
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
|
0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
|
||||||
];
|
];
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
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
|
let rbx: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -554,7 +554,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
||||||
// Only run the first instruction.
|
// 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());
|
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)));
|
let mut vmm = MockVMM::new(ip, hashmap![], Some((rax + displacement, &memory)));
|
||||||
// Run the 2 first instructions.
|
// 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());
|
assert_eq!(ip + 7 + 4 as u64, vmm.cpu_state(cpu_id).unwrap().ip());
|
||||||
|
|
||||||
|
@ -650,21 +650,26 @@ mod mock_vmm {
|
|||||||
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 ip = self.cpu_state(cpu_id).unwrap().ip();
|
||||||
let mut emulator = Emulator::new(self);
|
let mut emulator = Emulator::new(self);
|
||||||
|
|
||||||
let new_state = emulator
|
let new_state = emulator.emulate_insn_stream(cpu_id, &insn, num_insn)?;
|
||||||
.emulate_insn_stream(cpu_id, &insn, num_insn)
|
|
||||||
.unwrap();
|
|
||||||
if num_insn.is_none() {
|
if num_insn.is_none() {
|
||||||
assert_eq!(ip + insn.len() as u64, new_state.ip());
|
assert_eq!(ip + insn.len() as u64, new_state.ip());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_cpu_state(cpu_id, new_state).unwrap();
|
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))
|
self.emulate_insn(cpu_id, insn, Some(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,7 +765,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((ip, &memory)));
|
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
|
let rax: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -797,7 +802,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let mut vmm = MockVMM::new(ip, hashmap![], Some((ip, &memory)));
|
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
|
let rbx: u64 = vmm
|
||||||
.cpu_state(cpu_id)
|
.cpu_state(cpu_id)
|
||||||
@ -808,4 +813,29 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
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…
Reference in New Issue
Block a user