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>
This commit is contained in:
Noah Gold 2022-05-20 11:13:59 -07:00 committed by Chromeos LUCI
parent 953670c3ea
commit ebb6efe266
2 changed files with 29 additions and 0 deletions

View file

@ -777,6 +777,7 @@ impl arch::LinuxArch for X8664arch {
}
if has_bios {
regs::set_reset_vector(vcpu).map_err(Error::SetupRegs)?;
return Ok(());
}

View file

@ -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(&regs).map_err(Error::SettingRegistersIoctl)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;