diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 2fe9ad7286..db941e19f2 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -777,6 +777,7 @@ impl arch::LinuxArch for X8664arch { } if has_bios { + regs::set_reset_vector(vcpu).map_err(Error::SetupRegs)?; return Ok(()); } diff --git a/x86_64/src/regs.rs b/x86_64/src/regs.rs index 82df5d99ca..7c950addcc 100644 --- a/x86_64/src/regs.rs +++ b/x86_64/src/regs.rs @@ -21,6 +21,9 @@ pub enum Error { /// Failed to get sregs for this cpu. #[error("failed to get sregs for this cpu: {0}")] GetSRegsIoctlFailed(base::Error), + /// Failed to get base registers for this cpu. + #[error("failed to get base registers for this cpu: {0}")] + GettingRegistersIoctl(base::Error), /// Setting up msrs failed. #[error("setting up msrs failed: {0}")] MsrIoctlFailed(base::Error), @@ -349,6 +352,31 @@ pub fn setup_sregs(mem: &GuestMemory, vcpu: &dyn VcpuX86_64) -> Result<()> { Ok(()) } +/// Configures a CPU to be pointed at the i386 reset vector. +/// +/// The reset vector is the default location a CPU will go to find the first instruction it will +/// execute after a reset. On i386, the reset vector means the RIP is set to 0xfff0 the CS base is +/// set to 0xffff0000, and the CS selector is set to 0xf000. +/// +/// When using a BIOS, each of the VCPUs should be pointed at the reset vector before execution +/// begins. +/// +/// # Arguments +/// * `vcpu` - the VCPU to configure. +pub fn set_reset_vector(vcpu: &dyn VcpuX86_64) -> Result<()> { + let mut sregs = vcpu.get_sregs().map_err(Error::GetSRegsIoctlFailed)?; + let mut regs = vcpu.get_regs().map_err(Error::GettingRegistersIoctl)?; + + regs.rip = 0xfff0; + sregs.cs.base = 0xffff0000; + sregs.cs.selector = 0xf000; + + vcpu.set_sregs(&sregs).map_err(Error::SetSRegsIoctlFailed)?; + vcpu.set_regs(®s).map_err(Error::SettingRegistersIoctl)?; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*;