x86_64: set reset vector when using bios
BIOS expect all the cpus to be pointed at the i386 reset vector before
boot. We can't guarantee that a fresh vcpu will be pointed to the reset
vector by default, so we should set the reset vector when we're
configuring the vcpu when we're using a BIOS.
Cherrypick from downstream branch.
Actual author: Colin Downs-Razouk <colindr@google.com>.
TEST=builds
BUG=b:213152505
Change-Id: Idf4e0a200c8141adf5cbb83856cbd57362d84716
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3657811
Reviewed-by: Colin Downs-Razouk <colindr@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: Noah Gold <nkgold@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index 2fe9ad7..db941e1 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -777,6 +777,7 @@
}
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 82df5d9..7c950ad 100644
--- a/x86_64/src/regs.rs
+++ b/x86_64/src/regs.rs
@@ -21,6 +21,9 @@
/// 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 @@
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::*;