xref: /cloud-hypervisor/hypervisor/src/arch/x86/emulator/mod.rs (revision 9af2968a7dc47b89bf07ea9dc5e735084efcfa3a)
1 //
2 // Copyright © 2020 Intel Corporation
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
8 use crate::arch::x86::emulator::instructions::*;
9 use crate::arch::x86::regs::*;
10 use crate::arch::x86::*;
11 use crate::arch::x86::{Exception, SegmentRegisterOps};
12 use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters};
13 use anyhow::Context;
14 use iced_x86::*;
15 
16 #[macro_use]
17 mod instructions;
18 
19 /// x86 CPU modes
20 #[derive(Debug, PartialEq)]
21 pub enum CpuMode {
22     /// Real mode
23     Real,
24 
25     /// Virtual 8086 mode
26     Virtual8086,
27 
28     /// 16-bit protected mode
29     Protected16,
30 
31     /// 32-bit protected mode
32     Protected,
33 
34     /// 64-bit mode, a.k.a. long mode
35     Long,
36 }
37 
38 /// CpuStateManager manages an x86 CPU state.
39 ///
40 /// Instruction emulation handlers get a mutable reference to
41 /// a `CpuStateManager` implementation, representing the current state of the
42 /// CPU they have to emulate an instruction stream against. Usually those
43 /// handlers will modify the CPU state by modifying `CpuState` and it is up to
44 /// the handler caller to commit those changes back by invoking a
45 /// `PlatformEmulator` implementation `set_state()` method.
46 ///
47 pub trait CpuStateManager: Clone {
48     /// Reads a CPU register.
49     ///
50     /// # Arguments
51     ///
52     /// * `reg` - A general purpose, control or debug register.
53     fn read_reg(&self, reg: Register) -> Result<u64, PlatformError>;
54 
55     /// Write to a CPU register.
56     ///
57     /// # Arguments
58     ///
59     /// * `reg` - A general purpose, control or debug register.
60     /// * `val` - The value to load.
61     fn write_reg(&mut self, reg: Register, val: u64) -> Result<(), PlatformError>;
62 
63     /// Reads a segment register.
64     ///
65     /// # Arguments
66     ///
67     /// * `reg` - A segment register.
68     fn read_segment(&self, reg: Register) -> Result<SegmentRegister, PlatformError>;
69 
70     /// Write to a segment register.
71     ///
72     /// # Arguments
73     ///
74     /// * `reg` - A segment register.
75     /// * `segment_reg` - The segment register value to load.
76     fn write_segment(
77         &mut self,
78         reg: Register,
79         segment_reg: SegmentRegister,
80     ) -> Result<(), PlatformError>;
81 
82     /// Get the CPU instruction pointer.
83     fn ip(&self) -> u64;
84 
85     /// Set the CPU instruction pointer.
86     ///
87     /// # Arguments
88     ///
89     /// * `ip` - The CPU instruction pointer.
90     fn set_ip(&mut self, ip: u64);
91 
92     /// Get the CPU Extended Feature Enable Register.
93     fn efer(&self) -> u64;
94 
95     /// Set the CPU Extended Feature Enable Register.
96     ///
97     /// # Arguments
98     ///
99     /// * `efer` - The CPU EFER value.
100     fn set_efer(&mut self, efer: u64);
101 
102     /// Get the CPU flags.
103     fn flags(&self) -> u64;
104 
105     /// Set the CPU flags.
106     ///
107     /// # Arguments
108     ///
109     /// * `flags` - The CPU flags
110     fn set_flags(&mut self, flags: u64);
111 
112     /// Get the CPU mode.
113     fn mode(&self) -> Result<CpuMode, PlatformError>;
114 
115     /// Translate a logical (segmented) address into a linear (virtual) one.
116     ///
117     /// # Arguments
118     ///
119     /// * `segment` - Which segment to use for linearization
120     /// * `logical_addr` - The logical address to be translated
121     fn linearize(
122         &self,
123         segment: Register,
124         logical_addr: u64,
125         write: bool,
126     ) -> Result<u64, PlatformError> {
127         let segment_register = self.read_segment(segment)?;
128         let mode = self.mode()?;
129 
130         match mode {
131             CpuMode::Long => {
132                 // TODO Check that we got a canonical address.
133                 Ok(logical_addr
134                     .checked_add(segment_register.base)
135                     .ok_or_else(|| {
136                         PlatformError::InvalidAddress(anyhow!(
137                             "Logical address {:#x} can not be linearized with segment {:#x?}",
138                             logical_addr,
139                             segment_register
140                         ))
141                     })?)
142             }
143 
144             CpuMode::Protected | CpuMode::Real => {
145                 let segment_type = segment_register.segment_type();
146 
147                 // Must not write to a read-only segment.
148                 if segment_type_ro(segment_type) && write {
149                     return Err(PlatformError::InvalidAddress(anyhow!(
150                         "Can not write to a read-only segment"
151                     )));
152                 }
153 
154                 let logical_addr = logical_addr & 0xffff_ffffu64;
155                 let mut segment_limit: u32 = if segment_register.granularity() != 0 {
156                     (segment_register.limit << 12) | 0xfff
157                 } else {
158                     segment_register.limit
159                 };
160 
161                 // Expand-down segment
162                 if segment_type_expand_down(segment_type) {
163                     if logical_addr >= segment_limit.into() {
164                         return Err(PlatformError::InvalidAddress(anyhow!(
165                             "{:#x} is off limits {:#x} (expand down)",
166                             logical_addr,
167                             segment_limit
168                         )));
169                     }
170 
171                     if segment_register.db() != 0 {
172                         segment_limit = 0xffffffff
173                     } else {
174                         segment_limit = 0xffff
175                     }
176                 }
177 
178                 if logical_addr > segment_limit.into() {
179                     return Err(PlatformError::InvalidAddress(anyhow!(
180                         "{:#x} is off limits {:#x}",
181                         logical_addr,
182                         segment_limit
183                     )));
184                 }
185 
186                 Ok(logical_addr + segment_register.base)
187             }
188 
189             _ => Err(PlatformError::UnsupportedCpuMode(anyhow!("{:?}", mode))),
190         }
191     }
192 }
193 
194 const REGISTER_MASK_64: u64 = 0xffff_ffff_ffff_ffffu64;
195 const REGISTER_MASK_32: u64 = 0xffff_ffffu64;
196 const REGISTER_MASK_16: u64 = 0xffffu64;
197 const REGISTER_MASK_8: u64 = 0xffu64;
198 
199 macro_rules! set_reg {
200     ($reg:expr, $mask:expr, $value:expr) => {
201         $reg = ($reg & $mask) | $value
202     };
203 }
204 
205 #[derive(Clone, Default, Debug)]
206 /// A minimal, emulated CPU state.
207 ///
208 /// Hypervisors needing x86 emulation can choose to either use their own
209 /// CPU state structures and implement the CpuStateManager interface for it,
210 /// or use `EmulatorCpuState`. The latter implies creating a new state
211 /// `EmulatorCpuState` instance for each platform `cpu_state()` call, which
212 /// might be less efficient.
213 pub struct EmulatorCpuState {
214     pub regs: StandardRegisters,
215     pub sregs: SpecialRegisters,
216 }
217 
218 impl CpuStateManager for EmulatorCpuState {
219     fn read_reg(&self, reg: Register) -> Result<u64, PlatformError> {
220         let mut reg_value: u64 = match reg {
221             Register::RAX | Register::EAX | Register::AX | Register::AL | Register::AH => {
222                 self.regs.rax
223             }
224             Register::RBX | Register::EBX | Register::BX | Register::BL | Register::BH => {
225                 self.regs.rbx
226             }
227             Register::RCX | Register::ECX | Register::CX | Register::CL | Register::CH => {
228                 self.regs.rcx
229             }
230             Register::RDX | Register::EDX | Register::DX | Register::DL | Register::DH => {
231                 self.regs.rdx
232             }
233             Register::RSP | Register::ESP | Register::SP => self.regs.rsp,
234             Register::RBP | Register::EBP | Register::BP => self.regs.rbp,
235             Register::RSI | Register::ESI | Register::SI | Register::SIL => self.regs.rsi,
236             Register::RDI | Register::EDI | Register::DI | Register::DIL => self.regs.rdi,
237             Register::R8 | Register::R8D | Register::R8W | Register::R8L => self.regs.r8,
238             Register::R9 | Register::R9D | Register::R9W | Register::R9L => self.regs.r9,
239             Register::R10 | Register::R10D | Register::R10W | Register::R10L => self.regs.r10,
240             Register::R11 | Register::R11D | Register::R11W | Register::R11L => self.regs.r11,
241             Register::R12 | Register::R12D | Register::R12W | Register::R12L => self.regs.r12,
242             Register::R13 | Register::R13D | Register::R13W | Register::R13L => self.regs.r13,
243             Register::R14 | Register::R14D | Register::R14W | Register::R14L => self.regs.r14,
244             Register::R15 | Register::R15D | Register::R15W | Register::R15L => self.regs.r15,
245             Register::CR0 => self.sregs.cr0,
246             Register::CR2 => self.sregs.cr2,
247             Register::CR3 => self.sregs.cr3,
248             Register::CR4 => self.sregs.cr4,
249             Register::CR8 => self.sregs.cr8,
250 
251             r => {
252                 return Err(PlatformError::InvalidRegister(anyhow!(
253                     "read_reg invalid GPR {:?}",
254                     r
255                 )))
256             }
257         };
258 
259         reg_value = if reg.is_gpr64() || reg.is_cr() {
260             reg_value
261         } else if reg.is_gpr32() {
262             reg_value & REGISTER_MASK_32
263         } else if reg.is_gpr16() {
264             reg_value & REGISTER_MASK_16
265         } else if reg.is_gpr8() {
266             if reg == Register::AH
267                 || reg == Register::BH
268                 || reg == Register::CH
269                 || reg == Register::DH
270             {
271                 (reg_value >> 8) & REGISTER_MASK_8
272             } else {
273                 reg_value & REGISTER_MASK_8
274             }
275         } else {
276             return Err(PlatformError::InvalidRegister(anyhow!(
277                 "read_reg invalid GPR {:?}",
278                 reg
279             )));
280         };
281 
282         debug!("Register read: {:#x} from {:?}", reg_value, reg);
283 
284         Ok(reg_value)
285     }
286 
287     fn write_reg(&mut self, reg: Register, val: u64) -> Result<(), PlatformError> {
288         debug!("Register write: {:#x} to {:?}", val, reg);
289 
290         // SDM Vol 1 - 3.4.1.1
291         //
292         // 8-bit and 16-bit operands generate an 8-bit or 16-bit result.
293         // The upper 56 bits or 48 bits (respectively) of the destination
294         // general-purpose register are not modified by the operation.
295         let (reg_value, mask): (u64, u64) = if reg.is_gpr64() || reg.is_cr() {
296             (val, !REGISTER_MASK_64)
297         } else if reg.is_gpr32() {
298             (val & REGISTER_MASK_32, !REGISTER_MASK_64)
299         } else if reg.is_gpr16() {
300             (val & REGISTER_MASK_16, !REGISTER_MASK_16)
301         } else if reg.is_gpr8() {
302             if reg == Register::AH
303                 || reg == Register::BH
304                 || reg == Register::CH
305                 || reg == Register::DH
306             {
307                 ((val & REGISTER_MASK_8) << 8, !(REGISTER_MASK_8 << 8))
308             } else {
309                 (val & REGISTER_MASK_8, !REGISTER_MASK_8)
310             }
311         } else {
312             return Err(PlatformError::InvalidRegister(anyhow!(
313                 "write_reg invalid register {:?}",
314                 reg
315             )));
316         };
317 
318         match reg {
319             Register::RAX | Register::EAX | Register::AX | Register::AL | Register::AH => {
320                 set_reg!(self.regs.rax, mask, reg_value);
321             }
322             Register::RBX | Register::EBX | Register::BX | Register::BL | Register::BH => {
323                 set_reg!(self.regs.rbx, mask, reg_value);
324             }
325             Register::RCX | Register::ECX | Register::CX | Register::CL | Register::CH => {
326                 set_reg!(self.regs.rcx, mask, reg_value);
327             }
328             Register::RDX | Register::EDX | Register::DX | Register::DL | Register::DH => {
329                 set_reg!(self.regs.rdx, mask, reg_value);
330             }
331             Register::RSP | Register::ESP | Register::SP => {
332                 set_reg!(self.regs.rsp, mask, reg_value)
333             }
334             Register::RBP | Register::EBP | Register::BP => {
335                 set_reg!(self.regs.rbp, mask, reg_value)
336             }
337             Register::RSI | Register::ESI | Register::SI | Register::SIL => {
338                 set_reg!(self.regs.rsi, mask, reg_value)
339             }
340             Register::RDI | Register::EDI | Register::DI | Register::DIL => {
341                 set_reg!(self.regs.rdi, mask, reg_value)
342             }
343             Register::R8 | Register::R8D | Register::R8W | Register::R8L => {
344                 set_reg!(self.regs.r8, mask, reg_value)
345             }
346             Register::R9 | Register::R9D | Register::R9W | Register::R9L => {
347                 set_reg!(self.regs.r9, mask, reg_value)
348             }
349             Register::R10 | Register::R10D | Register::R10W | Register::R10L => {
350                 set_reg!(self.regs.r10, mask, reg_value)
351             }
352             Register::R11 | Register::R11D | Register::R11W | Register::R11L => {
353                 set_reg!(self.regs.r11, mask, reg_value)
354             }
355             Register::R12 | Register::R12D | Register::R12W | Register::R12L => {
356                 set_reg!(self.regs.r12, mask, reg_value)
357             }
358             Register::R13 | Register::R13D | Register::R13W | Register::R13L => {
359                 set_reg!(self.regs.r13, mask, reg_value)
360             }
361             Register::R14 | Register::R14D | Register::R14W | Register::R14L => {
362                 set_reg!(self.regs.r14, mask, reg_value)
363             }
364             Register::R15 | Register::R15D | Register::R15W | Register::R15L => {
365                 set_reg!(self.regs.r15, mask, reg_value)
366             }
367             Register::CR0 => set_reg!(self.sregs.cr0, mask, reg_value),
368             Register::CR2 => set_reg!(self.sregs.cr2, mask, reg_value),
369             Register::CR3 => set_reg!(self.sregs.cr3, mask, reg_value),
370             Register::CR4 => set_reg!(self.sregs.cr4, mask, reg_value),
371             Register::CR8 => set_reg!(self.sregs.cr8, mask, reg_value),
372             _ => {
373                 return Err(PlatformError::InvalidRegister(anyhow!(
374                     "write_reg invalid register {:?}",
375                     reg
376                 )))
377             }
378         }
379 
380         Ok(())
381     }
382 
383     fn read_segment(&self, reg: Register) -> Result<SegmentRegister, PlatformError> {
384         if !reg.is_segment_register() {
385             return Err(PlatformError::InvalidRegister(anyhow!(
386                 "read_segment {:?} is not a segment register",
387                 reg
388             )));
389         }
390 
391         match reg {
392             Register::CS => Ok(self.sregs.cs),
393             Register::DS => Ok(self.sregs.ds),
394             Register::ES => Ok(self.sregs.es),
395             Register::FS => Ok(self.sregs.fs),
396             Register::GS => Ok(self.sregs.gs),
397             Register::SS => Ok(self.sregs.ss),
398             r => Err(PlatformError::InvalidRegister(anyhow!(
399                 "read_segment invalid register {:?}",
400                 r
401             ))),
402         }
403     }
404 
405     fn write_segment(
406         &mut self,
407         reg: Register,
408         segment_register: SegmentRegister,
409     ) -> Result<(), PlatformError> {
410         if !reg.is_segment_register() {
411             return Err(PlatformError::InvalidRegister(anyhow!("{:?}", reg)));
412         }
413 
414         match reg {
415             Register::CS => self.sregs.cs = segment_register,
416             Register::DS => self.sregs.ds = segment_register,
417             Register::ES => self.sregs.es = segment_register,
418             Register::FS => self.sregs.fs = segment_register,
419             Register::GS => self.sregs.gs = segment_register,
420             Register::SS => self.sregs.ss = segment_register,
421             r => return Err(PlatformError::InvalidRegister(anyhow!("{:?}", r))),
422         }
423 
424         Ok(())
425     }
426 
427     fn ip(&self) -> u64 {
428         self.regs.rip
429     }
430 
431     fn set_ip(&mut self, ip: u64) {
432         self.regs.rip = ip;
433     }
434 
435     fn efer(&self) -> u64 {
436         self.sregs.efer
437     }
438 
439     fn set_efer(&mut self, efer: u64) {
440         self.sregs.efer = efer
441     }
442 
443     fn flags(&self) -> u64 {
444         self.regs.rflags
445     }
446 
447     fn set_flags(&mut self, flags: u64) {
448         self.regs.rflags = flags;
449     }
450 
451     fn mode(&self) -> Result<CpuMode, PlatformError> {
452         let efer = self.efer();
453         let cr0 = self.read_reg(Register::CR0)?;
454         let mut mode = CpuMode::Real;
455 
456         if (cr0 & CR0_PE) == CR0_PE {
457             mode = CpuMode::Protected;
458         }
459 
460         if (efer & EFER_LMA) == EFER_LMA {
461             if mode != CpuMode::Protected {
462                 return Err(PlatformError::InvalidState(anyhow!(
463                     "Protection must be enabled in long mode"
464                 )));
465             }
466 
467             mode = CpuMode::Long;
468         }
469 
470         Ok(mode)
471     }
472 }
473 
474 pub struct Emulator<'a, T: CpuStateManager> {
475     platform: &'a mut dyn PlatformEmulator<CpuState = T>,
476 }
477 
478 // Reduce repetition, see its invocation in get_handler().
479 macro_rules! gen_handler_match {
480     ($value: ident, $( ($module:ident, $code:ident) ),* ) => {
481         match $value {
482             $(
483                 Code::$code => Some(Box::new($module::$code)),
484             )*
485             _ => None,
486         }
487     };
488 }
489 
490 impl<'a, T: CpuStateManager> Emulator<'a, T> {
491     pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
492         Emulator { platform }
493     }
494 
495     fn get_handler(code: Code) -> Option<Box<dyn InstructionHandler<T>>> {
496         let handler: Option<Box<dyn InstructionHandler<T>>> = gen_handler_match!(
497             code,
498             // CMP
499             (cmp, Cmp_rm32_r32),
500             (cmp, Cmp_rm8_r8),
501             (cmp, Cmp_rm32_imm8),
502             (cmp, Cmp_rm64_r64),
503             // MOV
504             (mov, Mov_r8_rm8),
505             (mov, Mov_r8_imm8),
506             (mov, Mov_r16_imm16),
507             (mov, Mov_r16_rm16),
508             (mov, Mov_r32_imm32),
509             (mov, Mov_r32_rm32),
510             (mov, Mov_r64_imm64),
511             (mov, Mov_r64_rm64),
512             (mov, Mov_rm8_imm8),
513             (mov, Mov_rm8_r8),
514             (mov, Mov_rm16_imm16),
515             (mov, Mov_rm16_r16),
516             (mov, Mov_rm32_imm32),
517             (mov, Mov_rm32_r32),
518             (mov, Mov_rm64_imm32),
519             (mov, Mov_rm64_r64),
520             // MOVZX
521             (mov, Movzx_r16_rm8),
522             (mov, Movzx_r32_rm8),
523             (mov, Movzx_r64_rm8),
524             (mov, Movzx_r32_rm16),
525             (mov, Movzx_r64_rm16),
526             // MOVS
527             (movs, Movsd_m32_m32),
528             // OR
529             (or, Or_rm8_r8)
530         );
531 
532         handler
533     }
534 
535     fn emulate_insn_stream(
536         &mut self,
537         cpu_id: usize,
538         insn_stream: &[u8],
539         num_insn: Option<usize>,
540     ) -> EmulationResult<T, Exception> {
541         let mut state = self
542             .platform
543             .cpu_state(cpu_id)
544             .map_err(EmulationError::PlatformEmulationError)?;
545         let mut decoder = Decoder::new(64, insn_stream, DecoderOptions::NONE);
546         let mut insn = Instruction::default();
547         let mut num_insn_emulated: usize = 0;
548         let mut fetched_insn_stream: [u8; 16] = [0; 16];
549         let mut last_decoded_ip: u64 = state.ip();
550         let mut stop_emulation: bool = false;
551 
552         decoder.set_ip(state.ip());
553 
554         while decoder.can_decode() && !stop_emulation {
555             decoder.decode_out(&mut insn);
556 
557             if decoder.last_error() == DecoderError::NoMoreBytes {
558                 // The decoder is missing some bytes to decode the current
559                 // instruction, for example because the instruction stream
560                 // crosses a page boundary.
561                 // We fetch 16 more bytes from the instruction segment,
562                 // decode and emulate the failing instruction and terminate
563                 // the emulation loop.
564                 debug!(
565                     "Fetching {} bytes from {:#x}",
566                     fetched_insn_stream.len(),
567                     last_decoded_ip
568                 );
569 
570                 // fetched_insn_stream is 16 bytes long, enough to contain
571                 // any complete x86 instruction.
572                 self.platform
573                     .fetch(last_decoded_ip, &mut fetched_insn_stream)
574                     .map_err(EmulationError::PlatformEmulationError)?;
575 
576                 debug!("Fetched {:x?}", fetched_insn_stream);
577 
578                 // Once we have the new stream, we must create a new decoder
579                 // and emulate one last instruction from the last decoded IP.
580                 decoder = Decoder::new(64, &fetched_insn_stream, DecoderOptions::NONE);
581                 decoder.decode_out(&mut insn);
582                 if decoder.last_error() != DecoderError::None {
583                     return Err(EmulationError::InstructionFetchingError(anyhow!(
584                         "{:#x?}",
585                         insn_format!(insn)
586                     )));
587                 }
588 
589                 stop_emulation = true;
590             }
591 
592             // Emulate the decoded instruction
593             Emulator::get_handler(insn.code())
594                 .ok_or_else(|| {
595                     EmulationError::UnsupportedInstruction(anyhow!(
596                         "{:#x?} {:?} {:?}",
597                         insn_format!(insn),
598                         insn.mnemonic(),
599                         insn.code()
600                     ))
601                 })?
602                 .emulate(&insn, &mut state, self.platform)
603                 .context(anyhow!("Failed to emulate {:#x?}", insn_format!(insn)))?;
604 
605             last_decoded_ip = decoder.ip();
606             num_insn_emulated += 1;
607 
608             if let Some(num_insn) = num_insn {
609                 if num_insn_emulated >= num_insn {
610                     // Exit the decoding loop, do not decode the next instruction.
611                     stop_emulation = true;
612                 }
613             }
614         }
615 
616         state.set_ip(decoder.ip());
617         Ok(state)
618     }
619 
620     /// Emulate all instructions from the instructions stream.
621     pub fn emulate(&mut self, cpu_id: usize, insn_stream: &[u8]) -> EmulationResult<T, Exception> {
622         self.emulate_insn_stream(cpu_id, insn_stream, None)
623     }
624 
625     /// Only emulate the first instruction from the stream.
626     ///
627     /// This is useful for cases where we get readahead instruction stream
628     /// but implicitly must only emulate the first instruction, and then return
629     /// to the guest.
630     pub fn emulate_first_insn(
631         &mut self,
632         cpu_id: usize,
633         insn_stream: &[u8],
634     ) -> EmulationResult<T, Exception> {
635         self.emulate_insn_stream(cpu_id, insn_stream, Some(1))
636     }
637 }
638 
639 #[cfg(test)]
640 mod mock_vmm {
641     #![allow(unused_mut)]
642 
643     use super::*;
644     use crate::arch::emulator::{EmulationError, PlatformEmulator};
645     use crate::arch::x86::emulator::{Emulator, EmulatorCpuState as CpuState};
646     use crate::arch::x86::gdt::{gdt_entry, segment_from_gdt};
647     use crate::arch::x86::Exception;
648     use std::sync::{Arc, Mutex};
649 
650     #[derive(Debug, Clone)]
651     pub struct MockVmm {
652         memory: Vec<u8>,
653         state: Arc<Mutex<CpuState>>,
654     }
655 
656     unsafe impl Sync for MockVmm {}
657 
658     pub type MockResult = Result<(), EmulationError<Exception>>;
659 
660     impl MockVmm {
661         pub fn new(ip: u64, regs: Vec<(Register, u64)>, memory: Option<(u64, &[u8])>) -> MockVmm {
662             let _ = env_logger::try_init();
663             let cs_reg = segment_from_gdt(gdt_entry(0xc09b, 0, 0xffffffff), 1);
664             let ds_reg = segment_from_gdt(gdt_entry(0xc093, 0, 0xffffffff), 2);
665             let es_reg = segment_from_gdt(gdt_entry(0xc093, 0, 0xffffffff), 3);
666             let mut initial_state = CpuState::default();
667             initial_state.set_ip(ip);
668             initial_state.write_segment(Register::CS, cs_reg).unwrap();
669             initial_state.write_segment(Register::DS, ds_reg).unwrap();
670             initial_state.write_segment(Register::ES, es_reg).unwrap();
671             for (reg, value) in regs {
672                 initial_state.write_reg(reg, value).unwrap();
673             }
674 
675             let mut vmm = MockVmm {
676                 memory: vec![0; 8192],
677                 state: Arc::new(Mutex::new(initial_state)),
678             };
679 
680             if let Some(mem) = memory {
681                 vmm.write_memory(mem.0, mem.1).unwrap();
682             }
683 
684             vmm
685         }
686 
687         pub fn emulate_insn(
688             &mut self,
689             cpu_id: usize,
690             insn: &[u8],
691             num_insn: Option<usize>,
692         ) -> MockResult {
693             let ip = self.cpu_state(cpu_id).unwrap().ip();
694             let mut emulator = Emulator::new(self);
695 
696             let new_state = emulator.emulate_insn_stream(cpu_id, insn, num_insn)?;
697             if num_insn.is_none() {
698                 assert_eq!(ip + insn.len() as u64, new_state.ip());
699             }
700 
701             self.set_cpu_state(cpu_id, new_state).unwrap();
702 
703             Ok(())
704         }
705 
706         pub fn emulate_first_insn(&mut self, cpu_id: usize, insn: &[u8]) -> MockResult {
707             self.emulate_insn(cpu_id, insn, Some(1))
708         }
709     }
710 
711     impl PlatformEmulator for MockVmm {
712         type CpuState = CpuState;
713 
714         fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
715             debug!(
716                 "Memory read {} bytes from [{:#x} -> {:#x}]",
717                 data.len(),
718                 gva,
719                 gva + data.len() as u64 - 1
720             );
721             data.copy_from_slice(&self.memory[gva as usize..gva as usize + data.len()]);
722             Ok(())
723         }
724 
725         fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
726             debug!(
727                 "Memory write {} bytes at [{:#x} -> {:#x}]",
728                 data.len(),
729                 gva,
730                 gva + data.len() as u64 - 1
731             );
732             self.memory[gva as usize..gva as usize + data.len()].copy_from_slice(data);
733 
734             Ok(())
735         }
736 
737         fn cpu_state(&self, _cpu_id: usize) -> Result<CpuState, PlatformError> {
738             Ok(self.state.lock().unwrap().clone())
739         }
740 
741         fn set_cpu_state(
742             &self,
743             _cpu_id: usize,
744             state: Self::CpuState,
745         ) -> Result<(), PlatformError> {
746             *self.state.lock().unwrap() = state;
747             Ok(())
748         }
749 
750         fn gva_to_gpa(&self, gva: u64) -> Result<u64, PlatformError> {
751             Ok(gva)
752         }
753 
754         fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError> {
755             let rip = self
756                 .state
757                 .lock()
758                 .unwrap()
759                 .linearize(Register::CS, ip, false)?;
760             self.read_memory(rip, instruction_bytes)
761         }
762     }
763 }
764 
765 #[cfg(test)]
766 mod tests {
767     #![allow(unused_mut)]
768     use super::*;
769     use crate::arch::x86::emulator::mock_vmm::*;
770 
771     #[test]
772     // Emulate truncated instruction stream, which should cause a fetch.
773     //
774     // mov rax, 0x1000
775     // Test with a first instruction truncated.
776     fn test_fetch_first_instruction() {
777         let ip: u64 = 0x1000;
778         let cpu_id = 0;
779         let memory = [
780             // Code at IP
781             0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
782             0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
783             // Padding
784             0x00, 0x00, 0x00, 0x00, 0x00, // Padding is all zeroes
785             // Data at IP + 0x10 (0x1234567812345678 in LE)
786             0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
787         ];
788         let insn = [
789             // First instruction is truncated
790             0x48, 0xc7, 0xc0, 0x00, // mov rax, 0x1000 -- Missing bytes: 0x00, 0x10, 0x00, 0x00,
791         ];
792 
793         let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
794         assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
795 
796         let rax: u64 = vmm
797             .cpu_state(cpu_id)
798             .unwrap()
799             .read_reg(Register::RAX)
800             .unwrap();
801         assert_eq!(rax, ip);
802     }
803 
804     #[test]
805     // Emulate truncated instruction stream, which should cause a fetch.
806     //
807     // mov rax, 0x1000
808     // mov rbx, qword ptr [rax+10h]
809     // Test with a 2nd instruction truncated.
810     fn test_fetch_second_instruction() {
811         let target_rax: u64 = 0x1234567812345678;
812         let ip: u64 = 0x1000;
813         let cpu_id = 0;
814         let memory = [
815             // Code at IP
816             0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
817             0x48, 0x8b, 0x58, 0x10, // mov rbx, qword ptr [rax+10h]
818             // Padding
819             0x00, 0x00, 0x00, 0x00, 0x00, // Padding is all zeroes
820             // Data at IP + 0x10 (0x1234567812345678 in LE)
821             0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12,
822         ];
823         let insn = [
824             0x48, 0xc7, 0xc0, 0x00, 0x10, 0x00, 0x00, // mov rax, 0x1000
825             0x48, 0x8b, // Truncated mov rbx, qword ptr [rax+10h] -- missing [0x58, 0x10]
826         ];
827 
828         let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
829         assert!(vmm.emulate_insn(cpu_id, &insn, Some(2)).is_ok());
830 
831         let rbx: u64 = vmm
832             .cpu_state(cpu_id)
833             .unwrap()
834             .read_reg(Register::RBX)
835             .unwrap();
836         assert_eq!(rbx, target_rax);
837     }
838 
839     #[test]
840     // Emulate truncated instruction stream, which should cause a fetch.
841     //
842     // mov rax, 0x1000
843     // Test with a first instruction truncated and a bad fetched instruction.
844     // Verify that the instruction emulation returns an error.
845     fn test_fetch_bad_insn() {
846         let ip: u64 = 0x1000;
847         let cpu_id = 0;
848         let memory = [
849             // Code at IP
850             0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
851             0xff, 0xff,
852         ];
853         let insn = [
854             // First instruction is truncated
855             0x48, 0xc7, 0xc0, 0x00, // mov rax, 0x1000 -- Missing bytes: 0x00, 0x10, 0x00, 0x00,
856         ];
857 
858         let mut vmm = MockVmm::new(ip, vec![], Some((ip, &memory)));
859         assert!(vmm.emulate_first_insn(cpu_id, &insn).is_err());
860     }
861 }
862