hypervisor x86: provide a generic LapicState structure

This requires making get/set_lapic_reg part of the type.

For the moment we cannot provide a default variant for the new type,
because picking one will be wrong for the other hypervisor, so I just
drop the test cases that requires LapicState::default().

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu
2022-07-18 15:47:51 +00:00
committed by Liu Wei
parent d461daa7fa
commit 05e5106b9b
10 changed files with 132 additions and 86 deletions

View File

@@ -254,3 +254,68 @@ pub struct FpuState {
pub xmm: [[u8; 16usize]; 16usize],
pub mxcsr: u32,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum LapicState {
#[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_lapic_state),
#[cfg(feature = "mshv")]
Mshv(mshv_bindings::LapicState),
}
#[cfg(any(feature = "kvm", feature = "mshv"))]
impl LapicState {
pub fn get_klapic_reg(&self, reg_offset: usize) -> u32 {
use byteorder::{LittleEndian, ReadBytesExt};
use std::io::Cursor;
use std::mem;
let sliceu8 = match self {
#[cfg(feature = "kvm")]
LapicState::Kvm(s) => unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
mem::transmute::<&[i8], &[u8]>(&s.regs[reg_offset..])
},
#[cfg(feature = "mshv")]
LapicState::Mshv(s) => unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
mem::transmute::<&[i8], &[u8]>(&s.regs[reg_offset..])
},
};
let mut reader = Cursor::new(sliceu8);
// Following call can't fail if the offsets defined above are correct.
reader
.read_u32::<LittleEndian>()
.expect("Failed to read klapic register")
}
pub fn set_klapic_reg(&mut self, reg_offset: usize, value: u32) {
use byteorder::{LittleEndian, WriteBytesExt};
use std::io::Cursor;
use std::mem;
let sliceu8 = match self {
#[cfg(feature = "kvm")]
LapicState::Kvm(s) => unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..])
},
#[cfg(feature = "mshv")]
LapicState::Mshv(s) => unsafe {
// This array is only accessed as parts of a u32 word, so interpret it as a u8 array.
// Cursors are only readable on arrays of u8, not i8(c_char).
mem::transmute::<&mut [i8], &mut [u8]>(&mut s.regs[reg_offset..])
},
};
let mut writer = Cursor::new(sliceu8);
// Following call can't fail if the offsets defined above are correct.
writer
.write_u32::<LittleEndian>(value)
.expect("Failed to write klapic register")
}
}