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