mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
hypervisor: mshv: handle cross-page access in emulator
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
@@ -35,12 +35,7 @@ impl MshvEmulatorContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_memory_flags(
|
||||
&self,
|
||||
gva: u64,
|
||||
data: &mut [u8],
|
||||
flags: u32,
|
||||
) -> Result<(), PlatformError> {
|
||||
fn r(&self, gva: u64, data: &mut [u8], flags: u32) -> Result<(), PlatformError> {
|
||||
let gpa = self.translate(gva, flags)?;
|
||||
debug!(
|
||||
"mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]",
|
||||
@@ -59,17 +54,38 @@ impl MshvEmulatorContext<'_> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Platform emulation for Hyper-V
|
||||
impl PlatformEmulator for MshvEmulatorContext<'_> {
|
||||
type CpuState = EmulatorCpuState;
|
||||
fn read_memory_flags(
|
||||
&self,
|
||||
gva: u64,
|
||||
data: &mut [u8],
|
||||
flags: u32,
|
||||
) -> Result<(), PlatformError> {
|
||||
let mut len = data.len() as u64;
|
||||
|
||||
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
|
||||
self.read_memory_flags(gva, data, HV_TRANSLATE_GVA_VALIDATE_READ)
|
||||
// Compare the page number of the first and last byte. If they are different, this is a
|
||||
// cross-page access.
|
||||
let pg1 = gva >> HV_HYP_PAGE_SHIFT;
|
||||
let pg2 = (gva + len - 1) >> HV_HYP_PAGE_SHIFT;
|
||||
let cross_page = pg1 != pg2;
|
||||
|
||||
if cross_page {
|
||||
// We only handle one page cross-page access
|
||||
assert!(pg1 + 1 == pg2);
|
||||
let n = (gva + len) & HV_HYP_PAGE_MASK as u64;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
self.r(gva, &mut data[..len as usize], flags)?;
|
||||
|
||||
if cross_page {
|
||||
self.r(gva + len, &mut data[len as usize..], flags)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
|
||||
fn w(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
|
||||
let gpa = self.translate(gva, HV_TRANSLATE_GVA_VALIDATE_WRITE)?;
|
||||
debug!(
|
||||
"mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]",
|
||||
@@ -88,6 +104,40 @@ impl PlatformEmulator for MshvEmulatorContext<'_> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Platform emulation for Hyper-V
|
||||
impl PlatformEmulator for MshvEmulatorContext<'_> {
|
||||
type CpuState = EmulatorCpuState;
|
||||
|
||||
fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> {
|
||||
self.read_memory_flags(gva, data, HV_TRANSLATE_GVA_VALIDATE_READ)
|
||||
}
|
||||
|
||||
fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> {
|
||||
let mut len = data.len() as u64;
|
||||
|
||||
// Compare the page number of the first and last byte. If they are different, this is a
|
||||
// cross-page access.
|
||||
let pg1 = gva >> HV_HYP_PAGE_SHIFT;
|
||||
let pg2 = (gva + len - 1) >> HV_HYP_PAGE_SHIFT;
|
||||
let cross_page = pg1 != pg2;
|
||||
|
||||
if cross_page {
|
||||
// We only handle one page cross-page access
|
||||
assert!(pg1 + 1 == pg2);
|
||||
let n = (gva + len) & HV_HYP_PAGE_MASK as u64;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
self.w(gva, &data[..len as usize])?;
|
||||
|
||||
if cross_page {
|
||||
self.w(gva + len, &data[len as usize..])?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cpu_state(&self, cpu_id: usize) -> Result<Self::CpuState, PlatformError> {
|
||||
if cpu_id != self.vcpu.vp_index as usize {
|
||||
|
||||
Reference in New Issue
Block a user