arch: provide one vcpu_init per vcpu

Rather than having a single vcpu_init instance that is used for all
VCPUs, make vcpu_init into a Vec so it can store different initial state
for each VCPU. This allows us to set up e.g. bootstrap processor state
differently than other processors, and it also means that the VcpuInit
struct doesn't need to be Copy.

BUG=b:237095693
TEST=Boot Linux with >1 CPU

Change-Id: I0ebfdc2dbd84d0817e3f75c2c852e4320b9e77c5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3723798
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Daniel Verkamp 2022-06-23 17:50:13 -07:00 committed by Chromeos LUCI
parent 20085de68b
commit 1b7d5b8fba
7 changed files with 23 additions and 16 deletions

View file

@ -525,11 +525,13 @@ impl arch::LinuxArch for AArch64 {
)
.map_err(Error::CreateFdt)?;
let vcpu_init = vec![VcpuInitAArch64::default(); vcpu_count];
Ok(RunnableLinuxVm {
vm,
vcpu_count,
vcpus: Some(vcpus),
vcpu_init: VcpuInitAArch64 {},
vcpu_init,
vcpu_affinity: components.vcpu_affinity,
no_smt: components.no_smt,
irq_chip: irq_chip.try_box_clone().map_err(Error::CloneIrqChip)?,
@ -553,7 +555,7 @@ impl arch::LinuxArch for AArch64 {
_hypervisor: &dyn Hypervisor,
_irq_chip: &mut dyn IrqChipAArch64,
_vcpu: &mut dyn VcpuAArch64,
_vcpu_init: &VcpuInitAArch64,
_vcpu_init: VcpuInitAArch64,
_vcpu_id: usize,
_num_cpus: usize,
_has_bios: bool,

View file

@ -148,7 +148,8 @@ pub struct RunnableLinuxVm<V: VmArch, Vcpu: VcpuArch> {
pub suspend_evt: Event,
pub vcpu_affinity: Option<VcpuAffinity>,
pub vcpu_count: usize,
pub vcpu_init: VcpuInitArch,
/// Per-VCPU initialization data, indexed by vcpu_id.
pub vcpu_init: Vec<VcpuInitArch>,
/// If vcpus is None, then it's the responsibility of the vcpu thread to create vcpus.
/// If it's Some, then `build_vm` already created the vcpus.
pub vcpus: Option<Vec<Vcpu>>,
@ -244,7 +245,7 @@ pub trait LinuxArch {
hypervisor: &dyn HypervisorArch,
irq_chip: &mut dyn IrqChipArch,
vcpu: &mut dyn VcpuArch,
vcpu_init: &VcpuInitArch,
vcpu_init: VcpuInitArch,
vcpu_id: usize,
num_cpus: usize,
has_bios: bool,

View file

@ -122,7 +122,7 @@ pub trait VcpuAArch64: Vcpu {
impl_downcast!(VcpuAArch64);
/// Initial state for AArch64 VCPUs.
#[derive(Copy, Clone)]
#[derive(Clone, Default)]
pub struct VcpuInitAArch64 {}
// Convenience constructors for IrqRoutes

View file

@ -172,7 +172,7 @@ pub(crate) fn host_phys_addr_bits() -> u8 {
}
/// Initial state for x86_64 VCPUs.
#[derive(Copy, Clone, Default)]
#[derive(Clone, Default)]
pub struct VcpuInitX86_64 {
/// General-purpose registers.
pub regs: Regs,

View file

@ -1952,7 +1952,11 @@ fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
let guest_suspended_cvar = Arc::new((Mutex::new(false), Condvar::new()));
for (cpu_id, vcpu) in vcpus.into_iter().enumerate() {
// Architecture-specific code must supply a vcpu_init element for each VCPU.
assert_eq!(vcpus.len(), linux.vcpu_init.len());
for ((cpu_id, vcpu), vcpu_init) in vcpus.into_iter().enumerate().zip(linux.vcpu_init.drain(..))
{
let (to_vcpu_channel, from_main_channel) = mpsc::channel();
let vcpu_affinity = match linux.vcpu_affinity.clone() {
Some(VcpuAffinity::Global(v)) => v,
@ -1963,7 +1967,7 @@ fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
cpu_id,
vcpu_ids[cpu_id],
vcpu,
linux.vcpu_init,
vcpu_init,
linux.vm.try_clone().context("failed to clone vm")?,
linux
.irq_chip

View file

@ -133,7 +133,7 @@ pub fn runnable_vcpu<V>(
cpu_id: usize,
vcpu_id: usize,
vcpu: Option<V>,
vcpu_init: &VcpuInitArch,
vcpu_init: VcpuInitArch,
vm: impl VmArch,
irq_chip: &mut dyn IrqChipArch,
vcpu_count: usize,
@ -609,7 +609,7 @@ where
cpu_id,
vcpu_id,
vcpu,
&vcpu_init,
vcpu_init,
vm,
irq_chip.as_mut(),
vcpu_count,

View file

@ -698,7 +698,7 @@ impl arch::LinuxArch for X8664arch {
.map_err(Error::Cmdline)?;
}
let mut vcpu_init = VcpuInitX86_64::default();
let mut vcpu_init = vec![VcpuInitX86_64::default(); vcpu_count];
match components.vm_image {
VmImage::Bios(ref mut bios) => {
@ -724,11 +724,11 @@ impl arch::LinuxArch for X8664arch {
params,
)?;
// Configure the VCPU for the Linux/x86 64-bit boot protocol.
// Configure the bootstrap VCPU for the Linux/x86 64-bit boot protocol.
// <https://www.kernel.org/doc/html/latest/x86/boot.html>
vcpu_init.regs.rip = kernel_entry.offset();
vcpu_init.regs.rsp = BOOT_STACK_POINTER;
vcpu_init.regs.rsi = ZERO_PAGE_OFFSET;
vcpu_init[0].regs.rip = kernel_entry.offset();
vcpu_init[0].regs.rsp = BOOT_STACK_POINTER;
vcpu_init[0].regs.rsi = ZERO_PAGE_OFFSET;
}
}
@ -762,7 +762,7 @@ impl arch::LinuxArch for X8664arch {
hypervisor: &dyn HypervisorX86_64,
irq_chip: &mut dyn IrqChipX86_64,
vcpu: &mut dyn VcpuX86_64,
vcpu_init: &VcpuInitX86_64,
vcpu_init: VcpuInitX86_64,
vcpu_id: usize,
num_cpus: usize,
has_bios: bool,