From 1c7997c5c3c0473177f6c4278b9f29896aeb1842 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Fri, 9 Aug 2024 03:24:11 +0000 Subject: [PATCH] hypervisor: x86: emulate MOVSQ Signed-off-by: Wei Liu --- .../arch/x86/emulator/instructions/movs.rs | 41 ++++++++++++++++++- hypervisor/src/arch/x86/emulator/mod.rs | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hypervisor/src/arch/x86/emulator/instructions/movs.rs b/hypervisor/src/arch/x86/emulator/instructions/movs.rs index 330ebce81..f660bd5a7 100644 --- a/hypervisor/src/arch/x86/emulator/instructions/movs.rs +++ b/hypervisor/src/arch/x86/emulator/instructions/movs.rs @@ -40,7 +40,7 @@ macro_rules! movs { let len = std::mem::size_of::<$bound>(); while count > 0 { - let mut memory: [u8; 4] = [0; 4]; + let mut memory: [u8; 8] = [0; 8]; let src = state .linearize(Register::DS, rsi, false) @@ -83,6 +83,11 @@ macro_rules! movs { }; } +pub struct Movsq_m64_m64; +impl InstructionHandler for Movsq_m64_m64 { + movs!(u64); +} + pub struct Movsd_m32_m32; impl InstructionHandler for Movsd_m32_m32 { movs!(u32); @@ -103,6 +108,40 @@ mod tests { use super::*; use crate::arch::x86::emulator::mock_vmm::*; + #[test] + fn test_rep_movsq_m64_m64() { + let ip: u64 = 0x1000; + let memory: [u8; 32] = [ + 0x78, 0x56, 0x34, 0x12, // 0x12345678 + 0xdd, 0xcc, 0xbb, 0xaa, // 0xaabbccdd + 0xa5, 0x5a, 0xa5, 0x5a, // 0x5aa55aa5 + 0xcd, 0xcd, 0xcd, 0xcd, // 0xcdcdcdcd + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + 0x00, 0x00, 0x00, 0x00, // 0x00000000 + ]; + let insn = [0xf3, 0x48, 0xa5]; // rep movsq + let regs = vec![ + (Register::ECX, 2), + (Register::ESI, 0), + (Register::EDI, 0x10), + ]; + let mut data = [0u8; 8]; + + let mut vmm = MockVmm::new(ip, regs, Some((0, &memory))); + + assert!(vmm.emulate_first_insn(0, &insn).is_ok()); + + vmm.read_memory(0x10, &mut data).unwrap(); + assert_eq!(0xaabbccdd12345678, ::from_le_bytes(data)); + vmm.read_memory(0x18, &mut data).unwrap(); + assert_eq!(0xcdcdcdcd5aa55aa5, ::from_le_bytes(data)); + // The rest should be default value 0 from MockVmm + vmm.read_memory(0x20, &mut data).unwrap(); + assert_eq!(0x0, ::from_le_bytes(data)); + } + #[test] fn test_rep_movsd_m32_m32() { let ip: u64 = 0x1000; diff --git a/hypervisor/src/arch/x86/emulator/mod.rs b/hypervisor/src/arch/x86/emulator/mod.rs index 9153aec71..d08ab5b90 100644 --- a/hypervisor/src/arch/x86/emulator/mod.rs +++ b/hypervisor/src/arch/x86/emulator/mod.rs @@ -532,6 +532,7 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> { (mov, Mov_moffs64_RAX), (mov, Mov_RAX_moffs64), // MOVS + (movs, Movsq_m64_m64), (movs, Movsd_m32_m32), (movs, Movsw_m16_m16), (movs, Movsb_m8_m8),