xref: /cloud-hypervisor/hypervisor/src/arch/x86/emulator/mod.rs (revision 0f4f30dbde1a2e7dd2154d6963918ca453cf2eaa)
1 //
2 // Copyright © 2020 Intel Corporation
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 extern crate iced_x86;
8 
9 use crate::arch::emulator::{EmulationError, EmulationResult, PlatformEmulator, PlatformError};
10 use crate::arch::x86::emulator::instructions::*;
11 use crate::arch::x86::Exception;
12 use crate::x86_64::{SegmentRegister, SpecialRegisters, StandardRegisters};
13 use iced_x86::*;
14 use std::sync::{Arc, Mutex};
15 
16 #[macro_use]
17 mod instructions;
18 
19 /// CpuStateManager manages an x86 CPU state.
20 ///
21 /// Instruction emulation handlers get a mutable reference to
22 /// a `CpuStateManager` implementation, representing the current state of the
23 /// CPU they have to emulate an instruction stream against. Usually those
24 /// handlers will modify the CPU state by modifying `CpuState` and it is up to
25 /// the handler caller to commit those changes back by invoking a
26 /// `PlatformEmulator` implementation `set_state()` method.
27 ///
28 pub trait CpuStateManager: Clone {
29     /// Reads a CPU register.
30     ///
31     /// # Arguments
32     ///
33     /// * `reg` - A general purpose, control or debug register.
34     fn read_reg(&self, reg: Register) -> Result<u64, PlatformError>;
35 
36     /// Write to a CPU register.
37     ///
38     /// # Arguments
39     ///
40     /// * `reg` - A general purpose, control or debug register.
41     /// * `val` - The value to load.
42     fn write_reg(&mut self, reg: Register, val: u64) -> Result<(), PlatformError>;
43 
44     /// Reads a segment register.
45     ///
46     /// # Arguments
47     ///
48     /// * `reg` - A segment register.
49     fn read_segment(&self, reg: Register) -> Result<SegmentRegister, PlatformError>;
50 
51     /// Write to a segment register.
52     ///
53     /// # Arguments
54     ///
55     /// * `reg` - A segment register.
56     /// * `segment_reg` - The segment register value to load.
57     fn write_segment(
58         &mut self,
59         reg: Register,
60         segment_reg: SegmentRegister,
61     ) -> Result<(), PlatformError>;
62 
63     /// Get the CPU instruction pointer.
64     fn ip(&self) -> u64;
65 
66     /// Set the CPU instruction pointer.
67     ///
68     /// # Arguments
69     ///
70     /// * `ip` - The CPU instruction pointer.
71     fn set_ip(&mut self, ip: u64);
72 
73     /// Get the CPU Extended Feature Enable Register.
74     fn efer(&self) -> u64;
75 
76     /// Set the CPU Extended Feature Enable Register.
77     ///
78     /// # Arguments
79     ///
80     /// * `efer` - The CPU EFER value.
81     fn set_efer(&mut self, efer: u64);
82 
83     /// Get the CPU flags.
84     fn flags(&self) -> u64;
85 
86     /// Set the CPU flags.
87     ///
88     /// # Arguments
89     ///
90     /// * `flags` - The CPU flags
91     fn set_flags(&mut self, flags: u64);
92 }
93 
94 const REGISTER_MASK_64: u64 = 0xffff_ffff_ffff_ffffu64;
95 const REGISTER_MASK_32: u64 = 0xffff_ffffu64;
96 const REGISTER_MASK_16: u64 = 0xffffu64;
97 const REGISTER_MASK_8: u64 = 0xffu64;
98 
99 macro_rules! set_reg {
100     ($reg:expr, $mask:expr, $value:expr) => {
101         $reg = ($reg & $mask) | $value
102     };
103 }
104 
105 #[derive(Clone, Default, Debug)]
106 /// A minimal, emulated CPU state.
107 ///
108 /// Hypervisors needing x86 emulation can choose to either use their own
109 /// CPU state structures and implement the CpuStateManager interface for it,
110 /// or use `EmulatorCpuState`. The latter implies creating a new state
111 /// `EmulatorCpuState` instance for each platform `cpu_state()` call, which
112 /// might be less efficient.
113 pub struct EmulatorCpuState {
114     pub regs: StandardRegisters,
115     pub sregs: SpecialRegisters,
116 }
117 
118 impl CpuStateManager for EmulatorCpuState {
119     fn read_reg(&self, reg: Register) -> Result<u64, PlatformError> {
120         let mut reg_value: u64 = match reg {
121             Register::RAX | Register::EAX | Register::AX | Register::AL | Register::AH => {
122                 self.regs.rax
123             }
124             Register::RBX | Register::EBX | Register::BX | Register::BL | Register::BH => {
125                 self.regs.rbx
126             }
127             Register::RCX | Register::ECX | Register::CX | Register::CL | Register::CH => {
128                 self.regs.rcx
129             }
130             Register::RDX | Register::EDX | Register::DX | Register::DL | Register::DH => {
131                 self.regs.rdx
132             }
133             Register::RSP | Register::ESP => self.regs.rsp,
134             Register::RBP | Register::EBP => self.regs.rbp,
135             Register::RSI | Register::ESI => self.regs.rsi,
136             Register::RDI | Register::EDI | Register::DI | Register::DIL => self.regs.rdi,
137             Register::R8 | Register::R8D => self.regs.r8,
138             Register::R9 | Register::R9D => self.regs.r9,
139             Register::R10 | Register::R10D => self.regs.r10,
140             Register::R11 | Register::R11D => self.regs.r11,
141             Register::R12 | Register::R12D => self.regs.r12,
142             Register::R13 | Register::R13D => self.regs.r13,
143             Register::R14 | Register::R14D => self.regs.r14,
144             Register::R15 | Register::R15D => self.regs.r15,
145             Register::CR0 => self.sregs.cr0,
146             Register::CR2 => self.sregs.cr2,
147             Register::CR3 => self.sregs.cr3,
148             Register::CR4 => self.sregs.cr4,
149             Register::CR8 => self.sregs.cr8,
150 
151             r => {
152                 return Err(PlatformError::InvalidRegister(anyhow!(
153                     "read_reg invalid GPR {:?}",
154                     r
155                 )))
156             }
157         };
158 
159         reg_value = if reg.is_gpr64() || reg.is_cr() {
160             reg_value
161         } else if reg.is_gpr32() {
162             reg_value & REGISTER_MASK_32
163         } else if reg.is_gpr16() {
164             reg_value & REGISTER_MASK_16
165         } else if reg.is_gpr8() {
166             if reg == Register::AH
167                 || reg == Register::BH
168                 || reg == Register::CH
169                 || reg == Register::DH
170             {
171                 (reg_value >> 8) & REGISTER_MASK_8
172             } else {
173                 reg_value & REGISTER_MASK_8
174             }
175         } else {
176             return Err(PlatformError::InvalidRegister(anyhow!(
177                 "read_reg invalid GPR {:?}",
178                 reg
179             )));
180         };
181 
182         debug!("Register read: {:#x} from {:?}", reg_value, reg);
183 
184         Ok(reg_value)
185     }
186 
187     fn write_reg(&mut self, reg: Register, val: u64) -> Result<(), PlatformError> {
188         debug!("Register write: {:#x} to {:?}", val, reg);
189 
190         // SDM Vol 1 - 3.4.1.1
191         //
192         // 8-bit and 16-bit operands generate an 8-bit or 16-bit result.
193         // The upper 56 bits or 48 bits (respectively) of the destination
194         // general-purpose register are not modified by the operation.
195         let (reg_value, mask): (u64, u64) = if reg.is_gpr64() || reg.is_cr() {
196             (val, !REGISTER_MASK_64)
197         } else if reg.is_gpr32() {
198             (val & REGISTER_MASK_32, !REGISTER_MASK_64)
199         } else if reg.is_gpr16() {
200             (val & REGISTER_MASK_16, !REGISTER_MASK_16)
201         } else if reg.is_gpr8() {
202             if reg == Register::AH
203                 || reg == Register::BH
204                 || reg == Register::CH
205                 || reg == Register::DH
206             {
207                 ((val & REGISTER_MASK_8) << 8, !(REGISTER_MASK_8 << 8))
208             } else {
209                 (val & REGISTER_MASK_8, !REGISTER_MASK_8)
210             }
211         } else {
212             return Err(PlatformError::InvalidRegister(anyhow!(
213                 "write_reg invalid register {:?}",
214                 reg
215             )));
216         };
217 
218         match reg {
219             Register::RAX | Register::EAX | Register::AX | Register::AL | Register::AH => {
220                 set_reg!(self.regs.rax, mask, reg_value);
221             }
222             Register::RBX | Register::EBX | Register::BX | Register::BL | Register::BH => {
223                 set_reg!(self.regs.rbx, mask, reg_value);
224             }
225             Register::RCX | Register::ECX | Register::CX | Register::CL | Register::CH => {
226                 set_reg!(self.regs.rcx, mask, reg_value);
227             }
228             Register::RDX | Register::EDX | Register::DX | Register::DL | Register::DH => {
229                 set_reg!(self.regs.rdx, mask, reg_value);
230             }
231             Register::RSP | Register::ESP => {
232                 set_reg!(self.regs.rsp, mask, reg_value)
233             }
234             Register::RBP | Register::EBP => {
235                 set_reg!(self.regs.rbp, mask, reg_value)
236             }
237             Register::RSI | Register::ESI => {
238                 set_reg!(self.regs.rsi, mask, reg_value)
239             }
240             Register::RDI | Register::EDI | Register::DI | Register::DIL => {
241                 set_reg!(self.regs.rdi, mask, reg_value)
242             }
243             Register::R8 | Register::R8D => {
244                 set_reg!(self.regs.r8, mask, reg_value)
245             }
246             Register::R9 | Register::R9D => {
247                 set_reg!(self.regs.r9, mask, reg_value)
248             }
249             Register::R10 | Register::R10D => {
250                 set_reg!(self.regs.r10, mask, reg_value)
251             }
252             Register::R11 | Register::R11D => {
253                 set_reg!(self.regs.r11, mask, reg_value)
254             }
255             Register::R12 | Register::R12D => {
256                 set_reg!(self.regs.r12, mask, reg_value)
257             }
258             Register::R13 | Register::R13D => {
259                 set_reg!(self.regs.r13, mask, reg_value)
260             }
261             Register::R14 | Register::R14D => {
262                 set_reg!(self.regs.r14, mask, reg_value)
263             }
264             Register::R15 | Register::R15D => {
265                 set_reg!(self.regs.r15, mask, reg_value)
266             }
267             Register::CR0 => set_reg!(self.sregs.cr0, mask, reg_value),
268             Register::CR2 => set_reg!(self.sregs.cr2, mask, reg_value),
269             Register::CR3 => set_reg!(self.sregs.cr3, mask, reg_value),
270             Register::CR4 => set_reg!(self.sregs.cr4, mask, reg_value),
271             Register::CR8 => set_reg!(self.sregs.cr8, mask, reg_value),
272             _ => {
273                 return Err(PlatformError::InvalidRegister(anyhow!(
274                     "write_reg invalid register {:?}",
275                     reg
276                 )))
277             }
278         }
279 
280         Ok(())
281     }
282 
283     fn read_segment(&self, reg: Register) -> Result<SegmentRegister, PlatformError> {
284         if !reg.is_segment_register() {
285             return Err(PlatformError::InvalidRegister(anyhow!(
286                 "read_segment {:?} is not a segment register",
287                 reg
288             )));
289         }
290 
291         match reg {
292             Register::CS => Ok(self.sregs.cs),
293             Register::DS => Ok(self.sregs.ds),
294             Register::ES => Ok(self.sregs.es),
295             Register::FS => Ok(self.sregs.fs),
296             Register::GS => Ok(self.sregs.gs),
297             Register::SS => Ok(self.sregs.ss),
298             r => Err(PlatformError::InvalidRegister(anyhow!(
299                 "read_segment invalid register {:?}",
300                 r
301             ))),
302         }
303     }
304 
305     fn write_segment(
306         &mut self,
307         reg: Register,
308         segment_register: SegmentRegister,
309     ) -> Result<(), PlatformError> {
310         if !reg.is_segment_register() {
311             return Err(PlatformError::InvalidRegister(anyhow!("{:?}", reg)));
312         }
313 
314         match reg {
315             Register::CS => self.sregs.cs = segment_register,
316             Register::DS => self.sregs.ds = segment_register,
317             Register::ES => self.sregs.es = segment_register,
318             Register::FS => self.sregs.fs = segment_register,
319             Register::GS => self.sregs.gs = segment_register,
320             Register::SS => self.sregs.ss = segment_register,
321             r => return Err(PlatformError::InvalidRegister(anyhow!("{:?}", r))),
322         }
323 
324         Ok(())
325     }
326 
327     fn ip(&self) -> u64 {
328         self.regs.rip
329     }
330 
331     fn set_ip(&mut self, ip: u64) {
332         self.regs.rip = ip;
333     }
334 
335     fn efer(&self) -> u64 {
336         self.sregs.efer
337     }
338 
339     fn set_efer(&mut self, efer: u64) {
340         self.sregs.efer = efer
341     }
342 
343     fn flags(&self) -> u64 {
344         self.regs.rflags
345     }
346 
347     fn set_flags(&mut self, flags: u64) {
348         self.regs.rflags = flags;
349     }
350 }
351 
352 pub struct Emulator<T: CpuStateManager> {
353     platform: Arc<Mutex<dyn PlatformEmulator<CpuState = T>>>,
354     insn_map: InstructionMap<T>,
355 }
356 
357 impl<T: CpuStateManager> Emulator<T> {
358     pub fn new(platform: Arc<Mutex<dyn PlatformEmulator<CpuState = T>>>) -> Emulator<T> {
359         let mut insn_map = InstructionMap::<T>::new();
360 
361         // MOV
362         insn_add!(insn_map, mov, Mov_r8_imm8);
363         insn_add!(insn_map, mov, Mov_r8_rm8);
364         insn_add!(insn_map, mov, Mov_r16_imm16);
365         insn_add!(insn_map, mov, Mov_r16_rm16);
366         insn_add!(insn_map, mov, Mov_r32_imm32);
367         insn_add!(insn_map, mov, Mov_r32_rm32);
368         insn_add!(insn_map, mov, Mov_r64_imm64);
369         insn_add!(insn_map, mov, Mov_r64_rm64);
370         insn_add!(insn_map, mov, Mov_rm8_imm8);
371         insn_add!(insn_map, mov, Mov_rm8_r8);
372         insn_add!(insn_map, mov, Mov_rm16_imm16);
373         insn_add!(insn_map, mov, Mov_rm16_r16);
374         insn_add!(insn_map, mov, Mov_rm32_imm32);
375         insn_add!(insn_map, mov, Mov_rm32_r32);
376         insn_add!(insn_map, mov, Mov_rm64_imm32);
377         insn_add!(insn_map, mov, Mov_rm64_r64);
378 
379         Emulator {
380             platform: Arc::clone(&platform),
381             insn_map,
382         }
383     }
384 
385     fn emulate_insn_stream(
386         &mut self,
387         cpu_id: usize,
388         insn_stream: &[u8],
389         num_insn: Option<usize>,
390     ) -> EmulationResult<T, Exception> {
391         let mut state = self
392             .platform
393             .lock()
394             .unwrap()
395             .cpu_state(cpu_id)
396             .map_err(EmulationError::PlatformEmulationError)?;
397         let mut decoder = Decoder::new(64, insn_stream, DecoderOptions::NONE);
398         decoder.set_ip(state.ip());
399 
400         for (index, insn) in &mut decoder.iter().enumerate() {
401             self.insn_map
402                 .instructions
403                 .get(&insn.code())
404                 .ok_or_else(|| {
405                     EmulationError::UnsupportedInstruction(anyhow!("{:?}", insn.mnemonic()))
406                 })?
407                 .emulate(&insn, &mut state, Arc::clone(&self.platform))?;
408 
409             if let Some(num_insn) = num_insn {
410                 if index + 1 >= num_insn {
411                     // Exit the decoding loop, do not decode the next instruction.
412                     break;
413                 }
414             }
415         }
416 
417         state.set_ip(decoder.ip());
418         Ok(state)
419     }
420 
421     /// Emulate all instructions from the instructions stream.
422     pub fn emulate(&mut self, cpu_id: usize, insn_stream: &[u8]) -> EmulationResult<T, Exception> {
423         self.emulate_insn_stream(cpu_id, insn_stream, None)
424     }
425 
426     /// Only emulate the first instruction from the stream.
427     ///
428     /// This is useful for cases where we get readahead instruction stream
429     /// but implicitly must only emulate the first instruction, and then return
430     /// to the guest.
431     pub fn emulate_first_insn(
432         &mut self,
433         cpu_id: usize,
434         insn_stream: &[u8],
435     ) -> EmulationResult<T, Exception> {
436         self.emulate_insn_stream(cpu_id, insn_stream, Some(1))
437     }
438 }
439