mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
hypervisor: mshv: refactor port I/O exits
Move scalar HVMSG_X64_IO_PORT_INTERCEPT handling into a helper so the string I/O implementation can build on the same dispatch path. Keep the existing fw_cfg/debug-port skip plus string/REP assertions in place. This is only code movement so later changes are easier to review. Signed-off-by: Wei Liu <liuwe@microsoft.com> Assisted-by: Copilot:GPT-5.5
This commit is contained in:
@@ -619,70 +619,7 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT => {
|
||||
let info = x.to_ioport_info().unwrap();
|
||||
let access_info = info.access_info;
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
let len = unsafe { access_info.__bindgen_anon_1.access_size() } as usize;
|
||||
let is_write = info.header.intercept_access_type == 1;
|
||||
let port = info.port_number;
|
||||
let mut data: [u8; 4] = [0; 4];
|
||||
let mut ret_rax = info.rax;
|
||||
|
||||
/*
|
||||
* XXX: Ignore QEMU fw_cfg (0x5xx) and debug console (0x402) ports.
|
||||
*
|
||||
* Cloud Hypervisor doesn't support fw_cfg at the moment. It does support 0x402
|
||||
* under the "fwdebug" feature flag. But that feature is not enabled by default
|
||||
* and is considered legacy.
|
||||
*
|
||||
* OVMF unconditionally pokes these IO ports with string IO.
|
||||
*
|
||||
* Instead of trying to implement string IO support now which does not do much
|
||||
* now, skip those ports explicitly to avoid panicking.
|
||||
*
|
||||
* Proper string IO support can be added once we gain the ability to translate
|
||||
* guest virtual addresses to guest physical addresses on MSHV.
|
||||
*/
|
||||
match port {
|
||||
0x402 | 0x510 | 0x511 | 0x514 => {
|
||||
self.advance_rip_update_rax(&info, ret_rax)?;
|
||||
return Ok(cpu::VmExit::Ignore);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
assert!(
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
(unsafe { access_info.__bindgen_anon_1.string_op() } != 1),
|
||||
"String IN/OUT not supported"
|
||||
);
|
||||
assert!(
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
(unsafe { access_info.__bindgen_anon_1.rep_prefix() } != 1),
|
||||
"Rep IN/OUT not supported"
|
||||
);
|
||||
|
||||
if is_write {
|
||||
let data = (info.rax as u32).to_le_bytes();
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
vm_ops
|
||||
.pio_write(port.into(), &data[0..len])
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||
}
|
||||
} else {
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
vm_ops
|
||||
.pio_read(port.into(), &mut data[0..len])
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||
}
|
||||
|
||||
let v = u32::from_le_bytes(data);
|
||||
/* Preserve high bits in EAX but clear out high bits in RAX */
|
||||
let mask = 0xffffffff >> (32 - len * 8);
|
||||
let eax = (info.rax as u32 & !mask) | (v & mask);
|
||||
ret_rax = eax as u64;
|
||||
}
|
||||
|
||||
self.advance_rip_update_rax(&info, ret_rax)?;
|
||||
self.handle_io_port_intercept(&info)?;
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -1785,6 +1722,74 @@ impl MshvVcpu {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn handle_io_port_intercept(&self, info: &hv_x64_io_port_intercept_message) -> cpu::Result<()> {
|
||||
let access_info = info.access_info;
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
let len = unsafe { access_info.__bindgen_anon_1.access_size() } as usize;
|
||||
let is_write = info.header.intercept_access_type == 1;
|
||||
let port = info.port_number;
|
||||
let mut data: [u8; 4] = [0; 4];
|
||||
let mut ret_rax = info.rax;
|
||||
|
||||
/*
|
||||
* XXX: Ignore QEMU fw_cfg (0x5xx) and debug console (0x402) ports.
|
||||
*
|
||||
* Cloud Hypervisor doesn't support fw_cfg at the moment. It does support 0x402
|
||||
* under the "fwdebug" feature flag. But that feature is not enabled by default
|
||||
* and is considered legacy.
|
||||
*
|
||||
* OVMF unconditionally pokes these IO ports with string IO.
|
||||
*
|
||||
* Instead of trying to implement string IO support now which does not do much
|
||||
* now, skip those ports explicitly to avoid panicking.
|
||||
*
|
||||
* Proper string IO support can be added once we gain the ability to translate
|
||||
* guest virtual addresses to guest physical addresses on MSHV.
|
||||
*/
|
||||
match port {
|
||||
0x402 | 0x510 | 0x511 | 0x514 => {
|
||||
self.advance_rip_update_rax(info, ret_rax)?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
assert!(
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
(unsafe { access_info.__bindgen_anon_1.string_op() } != 1),
|
||||
"String IN/OUT not supported"
|
||||
);
|
||||
assert!(
|
||||
// SAFETY: access_info is valid, otherwise we won't be here
|
||||
(unsafe { access_info.__bindgen_anon_1.rep_prefix() } != 1),
|
||||
"Rep IN/OUT not supported"
|
||||
);
|
||||
|
||||
if is_write {
|
||||
let data = (info.rax as u32).to_le_bytes();
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
vm_ops
|
||||
.pio_write(port.into(), &data[0..len])
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||
}
|
||||
} else {
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
vm_ops
|
||||
.pio_read(port.into(), &mut data[0..len])
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||
}
|
||||
|
||||
let v = u32::from_le_bytes(data);
|
||||
/* Preserve high bits in EAX but clear out high bits in RAX */
|
||||
let mask = 0xffffffff >> (32 - len * 8);
|
||||
let eax = (info.rax as u32 & !mask) | (v & mask);
|
||||
ret_rax = eax as u64;
|
||||
}
|
||||
|
||||
self.advance_rip_update_rax(info, ret_rax)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn advance_rip_update_rax(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user