mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-03 11:25:20 +00:00
hypervisor: Add support for legacy I/O port emulation
Legacy port emulation requires reading RAX register from GHCB page for SEV-SNP guest. This is the major difference between a regular guest and SEV-SNP enabled guest. Signed-off-by: Jinank Jain <jinankjain@microsoft.com> Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
parent
e2288a8d2c
commit
7975207e0f
@ -848,6 +848,78 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
.gpa_write(&mut swei2_rw_gpa_arg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
|
||||
}
|
||||
SVM_EXITCODE_IOIO_PROT => {
|
||||
let exit_info1 =
|
||||
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1 as u32;
|
||||
let port_info = hv_sev_vmgexit_port_info {
|
||||
as_uint32: exit_info1,
|
||||
};
|
||||
|
||||
let port =
|
||||
// SAFETY: Accessing a union element from bindgen generated bindings.
|
||||
unsafe { port_info.__bindgen_anon_1.intercepted_port() };
|
||||
let mut len = 4;
|
||||
// SAFETY: Accessing a union element from bindgen generated bindings.
|
||||
unsafe {
|
||||
if port_info.__bindgen_anon_1.operand_size_16bit() == 1 {
|
||||
len = 2;
|
||||
} else if port_info.__bindgen_anon_1.operand_size_8bit()
|
||||
== 1
|
||||
{
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
let is_write =
|
||||
// SAFETY: Accessing a union element from bindgen generated bindings.
|
||||
unsafe { port_info.__bindgen_anon_1.access_type() == 0 };
|
||||
let mut rax_rw_gpa_arg: mshv_read_write_gpa =
|
||||
mshv_bindings::mshv_read_write_gpa {
|
||||
base_gpa: ghcb_gpa + GHCB_RAX_OFFSET,
|
||||
byte_count: std::mem::size_of::<u64>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
self.fd
|
||||
.gpa_read(&mut rax_rw_gpa_arg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GpaRead(e.into()))?;
|
||||
|
||||
if is_write {
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
vm_ops
|
||||
.pio_write(
|
||||
port.into(),
|
||||
&rax_rw_gpa_arg.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 rax_rw_gpa_arg.data[0..len],
|
||||
)
|
||||
.map_err(|e| {
|
||||
cpu::HypervisorCpuError::RunVcpu(e.into())
|
||||
})?;
|
||||
}
|
||||
|
||||
self.fd.gpa_write(&mut rax_rw_gpa_arg).map_err(|e| {
|
||||
cpu::HypervisorCpuError::GpaWrite(e.into())
|
||||
})?;
|
||||
}
|
||||
|
||||
// Clear the SW_EXIT_INFO1 register to indicate no error
|
||||
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
|
||||
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
|
||||
byte_count: std::mem::size_of::<u64>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
self.fd
|
||||
.gpa_write(&mut swei1_rw_gpa_arg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
|
||||
}
|
||||
_ => panic!(
|
||||
"GHCB_INFO_NORMAL: Unhandled exit code: {:0x}",
|
||||
exit_code
|
||||
|
@ -19,5 +19,6 @@ pub const ECDSA_SIG_Y_COMPONENT_END: usize =
|
||||
|
||||
// These constants are derived from GHCB spec Sect. 2.6 Table 3 GHCB Layout
|
||||
// Link: https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf
|
||||
pub const GHCB_RAX_OFFSET: u64 = 0x01F8;
|
||||
pub const GHCB_SW_EXITINFO1_OFFSET: u64 = 0x398;
|
||||
pub const GHCB_SW_EXITINFO2_OFFSET: u64 = 0x3A0;
|
||||
|
Loading…
Reference in New Issue
Block a user