mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 17:44:10 +00:00
Merge with upstream 2022-06-30 2/2
8dd4be42
audio_streams: Add StreamSourceGenerator traitb9ddd723
virtio-vhost: Enable handler to be built and tested on Windowse5c6e657
devices: pit: remove clock_gettime() usageaeea40d6
crosvm: Fix android and gfxstream build errorse30f4fda
x86_64: move Fpu initialization to vcpu_init1b7d5b8f
arch: provide one vcpu_init per vcpu20085de6
hypervisor: fix capability confusion for TSC leaves.d8842cf3
virtio: vhost: user: handler: make sys module follow style guidelines04230748
fs: Fix compiler warnings for feature chromeos517bfb7acf..8dd4be42e9
BUG=b:237095693 BUG=chromium:908689 BUG=b:236873276 BUG=b:220649000 BUG=b:237011316 BUG=b:213152505 BUG=b:213149155 Change-Id: I35b495fa053c98abe6204830e2ac1f994ab5a086
This commit is contained in:
commit
3895458e50
24 changed files with 161 additions and 102 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -24,10 +24,22 @@ impl Clock {
|
|||
self.0.duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn checked_duration_since(&self, earlier: &Self) -> Option<Duration> {
|
||||
self.0.checked_duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn saturating_duration_since(&self, earlier: &Self) -> Duration {
|
||||
self.0.saturating_duration_since(earlier.0)
|
||||
}
|
||||
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
self.0.elapsed()
|
||||
}
|
||||
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
|
||||
Some(Clock(self.0.checked_add(duration)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
|
||||
Some(Clock(self.0.checked_sub(duration)?))
|
||||
}
|
||||
|
@ -71,8 +83,22 @@ impl FakeClock {
|
|||
|
||||
/// Get the duration since |earlier|, assuming that earlier < self.
|
||||
pub fn duration_since(&self, earlier: &Self) -> Duration {
|
||||
let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
|
||||
Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
|
||||
self.checked_duration_since(earlier).unwrap()
|
||||
}
|
||||
|
||||
/// Get the duration since |earlier|
|
||||
pub fn checked_duration_since(&self, earlier: &Self) -> Option<Duration> {
|
||||
let ns_diff = self.ns_since_epoch.checked_sub(earlier.ns_since_epoch)?;
|
||||
Some(Duration::new(
|
||||
ns_diff / NS_PER_SEC,
|
||||
(ns_diff % NS_PER_SEC) as u32,
|
||||
))
|
||||
}
|
||||
|
||||
/// Get the duration since |earlier|, or 0 if earlier < self.
|
||||
pub fn saturating_duration_since(&self, earlier: &Self) -> Duration {
|
||||
self.checked_duration_since(earlier)
|
||||
.unwrap_or(Duration::ZERO)
|
||||
}
|
||||
|
||||
/// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
|
||||
|
@ -80,6 +106,15 @@ impl FakeClock {
|
|||
self.now().duration_since(self)
|
||||
}
|
||||
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Self> {
|
||||
Some(FakeClock {
|
||||
ns_since_epoch: self
|
||||
.ns_since_epoch
|
||||
.checked_add(duration.as_nanos() as u64)?,
|
||||
deadlines: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
|
||||
Some(FakeClock {
|
||||
ns_since_epoch: self
|
||||
|
|
|
@ -139,6 +139,12 @@ pub enum Error {
|
|||
Unimplemented,
|
||||
}
|
||||
|
||||
/// `StreamSourceGenerator` is a trait used to abstract types that create [`StreamSource`].
|
||||
/// It can be used when multiple types of `StreamSource` are needed.
|
||||
pub trait StreamSourceGenerator: Sync + Send {
|
||||
fn generate(&self) -> Result<Box<dyn StreamSource>, BoxError>;
|
||||
}
|
||||
|
||||
/// `StreamSource` creates streams for playback or capture of audio.
|
||||
pub trait StreamSource: Send {
|
||||
/// Returns a stream control and buffer generator object. These are separate as the buffer
|
||||
|
@ -684,6 +690,22 @@ impl StreamSource for NoopStreamSource {
|
|||
}
|
||||
}
|
||||
|
||||
/// `NoopStreamSourceGenerator` is a struct that implements [`StreamSourceGenerator`]
|
||||
/// to generate [`NoopStreamSource`].
|
||||
pub struct NoopStreamSourceGenerator;
|
||||
|
||||
impl NoopStreamSourceGenerator {
|
||||
pub fn new() -> Self {
|
||||
NoopStreamSourceGenerator {}
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamSourceGenerator for NoopStreamSourceGenerator {
|
||||
fn generate(&self) -> Result<Box<dyn StreamSource>, BoxError> {
|
||||
Ok(Box::new(NoopStreamSource))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::async_api::test::TestExecutor;
|
||||
|
@ -916,4 +938,12 @@ mod tests {
|
|||
let ex = TestExecutor {};
|
||||
this_test(&ex).now_or_never();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_noop_stream_source() {
|
||||
let generator: Box<dyn StreamSourceGenerator> = Box::new(NoopStreamSourceGenerator::new());
|
||||
generator
|
||||
.generate()
|
||||
.expect("failed to generate stream source");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,9 @@ power_monitor = { path = "../power_monitor" }
|
|||
usb_util = { path = "../usb_util" }
|
||||
vfio_sys = { path = "../vfio_sys" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
tube_transporter = { path = "../tube_transporter" }
|
||||
|
||||
[dependencies.futures]
|
||||
version = "*"
|
||||
features = ["async-await", "std"]
|
||||
|
|
|
@ -10,6 +10,8 @@ mod bus;
|
|||
mod irq_event;
|
||||
pub mod irqchip;
|
||||
mod pci;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod pit;
|
||||
pub mod serial_device;
|
||||
mod sys;
|
||||
pub mod virtio;
|
||||
|
@ -28,6 +30,8 @@ pub use self::pci::{
|
|||
PciDeviceError, PciInterruptPin, PciRoot, PciVirtualConfigMmio, StubPciDevice,
|
||||
StubPciParameters,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub use self::pit::{Pit, PitError};
|
||||
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
|
||||
pub use self::vtpm_proxy::VtpmProxy;
|
||||
|
||||
|
@ -41,8 +45,6 @@ cfg_if::cfg_if! {
|
|||
#[cfg(feature = "direct")]
|
||||
pub mod direct_irq;
|
||||
mod i8042;
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
mod pit;
|
||||
pub mod pl030;
|
||||
mod platform;
|
||||
mod proxy;
|
||||
|
@ -80,8 +82,6 @@ cfg_if::cfg_if! {
|
|||
PvPanicCode, PcieRootPort, PcieHostPort,
|
||||
PvPanicPciDevice, VfioPciDevice, PciBridge,
|
||||
};
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub use self::pit::{Pit, PitError};
|
||||
pub use self::pl030::Pl030;
|
||||
pub use self::platform::VfioPlatformDevice;
|
||||
pub use self::proxy::Error as ProxyError;
|
||||
|
|
|
@ -435,21 +435,6 @@ fn adjust_count(count: u32) -> u32 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the current monotonic time of host in nanoseconds
|
||||
fn get_monotonic_time() -> u64 {
|
||||
let mut time = libc::timespec {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
// Safe because time struct is local to this function and we check the returncode
|
||||
let ret = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut time) };
|
||||
if ret != 0 {
|
||||
0
|
||||
} else {
|
||||
time.tv_sec as u64 * 1_000_000_000u64 + time.tv_nsec as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl PitCounter {
|
||||
fn new(
|
||||
counter_id: usize,
|
||||
|
@ -485,11 +470,8 @@ impl PitCounter {
|
|||
}
|
||||
|
||||
fn get_channel_state(&self) -> PitChannelState {
|
||||
// Crosvm Pit stores start as an Instant. We do our best to convert to the host's
|
||||
// monotonic clock by taking the current monotonic time and subtracting the elapsed
|
||||
// time since self.start.
|
||||
let load_time = match &self.start {
|
||||
Some(t) => get_monotonic_time() - t.elapsed().as_nanos() as u64,
|
||||
Some(t) => t.saturating_duration_since(&self.creation_time).as_nanos() as u64,
|
||||
None => 0,
|
||||
};
|
||||
|
||||
|
@ -566,16 +548,9 @@ impl PitCounter {
|
|||
self.read_low_byte = state.read_state == PitRWState::Word1;
|
||||
self.wrote_low_byte = state.write_state == PitRWState::Word1;
|
||||
|
||||
// To convert the count_load_time to an instant we have to convert it to a
|
||||
// duration by comparing it to get_monotonic_time. Then subtract that duration from
|
||||
// a "now" instant.
|
||||
self.start = self
|
||||
.clock
|
||||
.lock()
|
||||
.now()
|
||||
.checked_sub(std::time::Duration::from_nanos(
|
||||
get_monotonic_time() - state.count_load_time,
|
||||
));
|
||||
.creation_time
|
||||
.checked_add(Duration::from_nanos(state.count_load_time));
|
||||
}
|
||||
|
||||
fn get_access_mode(&self) -> Option<CommandAccess> {
|
||||
|
|
|
@ -1045,7 +1045,7 @@ impl PassthroughFs {
|
|||
let fd = unsafe { dbus::arg::OwnedFd::new(base::clone_descriptor(&*data)?) };
|
||||
match proxy.set_media_rwdata_file_project_id(fd, proto.write_to_bytes().unwrap()) {
|
||||
Ok(r) => {
|
||||
let r = protobuf::parse_from_bytes::<SetMediaRWDataFileProjectIdReply>(&r)
|
||||
let r = SetMediaRWDataFileProjectIdReply::parse_from_bytes(&r)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
if !r.success {
|
||||
return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
|
||||
|
@ -1140,10 +1140,8 @@ impl PassthroughFs {
|
|||
proto.write_to_bytes().unwrap(),
|
||||
) {
|
||||
Ok(r) => {
|
||||
let r = protobuf::parse_from_bytes::<
|
||||
SetMediaRWDataFileProjectInheritanceFlagReply,
|
||||
>(&r)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
let r = SetMediaRWDataFileProjectInheritanceFlagReply::parse_from_bytes(&r)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
if !r.success {
|
||||
return Ok(IoctlReply::Done(Err(io::Error::from_raw_os_error(
|
||||
r.error,
|
||||
|
|
|
@ -127,7 +127,13 @@ pub fn create_guest_memory(
|
|||
region.memory_size,
|
||||
GuestAddress(region.guest_phys_addr),
|
||||
region.mmap_offset,
|
||||
Arc::new(SharedMemory::from_safe_descriptor(SafeDescriptor::from(file), None).unwrap()),
|
||||
Arc::new(
|
||||
SharedMemory::from_safe_descriptor(
|
||||
SafeDescriptor::from(file),
|
||||
Some(region.memory_size),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
)
|
||||
.map_err(|e| {
|
||||
error!("failed to create a memory region: {}", e);
|
||||
|
@ -753,10 +759,12 @@ mod tests {
|
|||
fn stop_queue(&mut self, _idx: usize) {}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn temp_dir() -> TempDir {
|
||||
Builder::new().prefix("/tmp/vhost_test").tempdir().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_vhost_user_activate() {
|
||||
use vmm_vhost::{
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
mod unix;
|
||||
pub(crate) use self::unix::*;
|
||||
pub mod unix;
|
||||
use unix as platform;
|
||||
} else if #[cfg(windows)] {
|
||||
mod windows;
|
||||
pub(crate) use self::windows::*;
|
||||
pub mod windows;
|
||||
use windows as platform;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) use platform::*;
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
pub(crate) use base::SharedMemoryWindows as SharedMemorySys;
|
||||
|
||||
use std::fs::File;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::sync::Arc;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
mod handler;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
mod block;
|
||||
|
@ -11,7 +13,6 @@ cfg_if::cfg_if! {
|
|||
#[cfg(feature = "audio_cras")]
|
||||
mod cras_snd;
|
||||
mod fs;
|
||||
mod handler;
|
||||
mod net;
|
||||
mod vsock;
|
||||
mod vvu;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -66,6 +66,9 @@ impl Hypervisor for Haxm {
|
|||
fn check_capability(&self, cap: HypervisorCap) -> bool {
|
||||
match cap {
|
||||
HypervisorCap::UserMemory => true,
|
||||
// under haxm, guests rely on this leaf to calibrate their
|
||||
// clocksource.
|
||||
HypervisorCap::CalibratedTscLeafRequired => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,13 +182,8 @@ impl Vm for HaxmVm {
|
|||
})
|
||||
}
|
||||
|
||||
fn check_capability(&self, c: VmCap) -> bool {
|
||||
match c {
|
||||
// under haxm, guests rely on this leaf to calibrate their
|
||||
// clocksource.
|
||||
VmCap::CalibratedTscLeafRequired => true,
|
||||
_ => false,
|
||||
}
|
||||
fn check_capability(&self, _c: VmCap) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn get_memory(&self) -> &GuestMemory {
|
||||
|
|
|
@ -176,6 +176,8 @@ impl Hypervisor for Whpx {
|
|||
false
|
||||
})
|
||||
}
|
||||
// under whpx, guests rely on this leaf to calibrate their clocksource.
|
||||
HypervisorCap::CalibratedTscLeafRequired => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -375,8 +375,6 @@ impl Vm for WhpxVm {
|
|||
VmCap::Protected => false,
|
||||
// whpx initializes cpuid early during VM creation.
|
||||
VmCap::EarlyInitCpuid => true,
|
||||
// under whpx, guests rely on this leaf to calibrate their clocksource.
|
||||
VmCap::CalibratedTscLeafRequired => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -172,10 +172,13 @@ 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,
|
||||
|
||||
/// Floating-point registers.
|
||||
pub fpu: Fpu,
|
||||
}
|
||||
|
||||
/// A CpuId Entry contains supported feature information for the given processor.
|
||||
|
@ -651,7 +654,7 @@ pub struct Sregs {
|
|||
|
||||
/// State of a VCPU's floating point unit.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Fpu {
|
||||
pub fpr: [[u8; 16usize]; 8usize],
|
||||
pub fcw: u16,
|
||||
|
@ -664,6 +667,22 @@ pub struct Fpu {
|
|||
pub mxcsr: u32,
|
||||
}
|
||||
|
||||
impl Default for Fpu {
|
||||
fn default() -> Self {
|
||||
Fpu {
|
||||
fpr: Default::default(),
|
||||
fcw: 0x37f, // Intel SDM Vol. 1, 13.6
|
||||
fsw: 0,
|
||||
ftwx: 0,
|
||||
last_opcode: 0,
|
||||
last_ip: 0,
|
||||
last_dp: 0,
|
||||
xmm: Default::default(),
|
||||
mxcsr: 0x1f80, // Intel SDM Vol. 1, 11.6.4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State of a VCPU's debug registers.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -98,7 +98,7 @@ pub fn check_ac97_backend(
|
|||
// server is required for and exclusive to vios backend
|
||||
#[cfg(target_os = "android")]
|
||||
match ac97_params.backend {
|
||||
Ac97Backend::VIOS => {
|
||||
devices::Ac97Backend::VIOS => {
|
||||
if ac97_params.vios_server_path.is_none() {
|
||||
return Err(String::from("server argument is required for VIOS backend"));
|
||||
}
|
||||
|
@ -390,10 +390,10 @@ pub fn parse_gpu_options(s: &str) -> Result<GpuParameters, String> {
|
|||
gpu_params.gfxstream_use_syncfd = false;
|
||||
}
|
||||
_ => {
|
||||
return Err(argument::Error::InvalidValue {
|
||||
value: v.to_string(),
|
||||
expected: String::from("gpu parameter 'syncfd' should be a boolean"),
|
||||
});
|
||||
return Err(invalid_value_err(
|
||||
v,
|
||||
"gpu parameter 'syncfd' should be a boolean",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ pub fn parse_gpu_options(s: &str) -> Result<GpuParameters, String> {
|
|||
#[cfg(feature = "gfxstream")]
|
||||
{
|
||||
if !vulkan_specified && gpu_params.mode == GpuMode::ModeGfxstream {
|
||||
gpu_params.use_vulkan = sys::use_vulkan();
|
||||
gpu_params.use_vulkan = use_vulkan();
|
||||
}
|
||||
|
||||
if syncfd_specified || angle_specified {
|
||||
|
|
|
@ -184,7 +184,7 @@ pub enum Error {
|
|||
#[error("failed to set up cpuid: {0}")]
|
||||
SetupCpuid(cpuid::Error),
|
||||
#[error("failed to set up FPU: {0}")]
|
||||
SetupFpu(regs::Error),
|
||||
SetupFpu(base::Error),
|
||||
#[error("failed to set up guest memory: {0}")]
|
||||
SetupGuestMemory(GuestMemoryError),
|
||||
#[error("failed to set up mptable: {0}")]
|
||||
|
@ -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,
|
||||
|
@ -788,6 +788,8 @@ impl arch::LinuxArch for X8664arch {
|
|||
.map_err(Error::SetupCpuid)?;
|
||||
}
|
||||
|
||||
vcpu.set_fpu(&vcpu_init.fpu).map_err(Error::SetupFpu)?;
|
||||
|
||||
if has_bios {
|
||||
regs::set_reset_vector(vcpu).map_err(Error::SetupRegs)?;
|
||||
regs::reset_msrs(vcpu).map_err(Error::SetupMsrs)?;
|
||||
|
@ -797,7 +799,6 @@ impl arch::LinuxArch for X8664arch {
|
|||
let guest_mem = vm.get_memory();
|
||||
regs::setup_msrs(vm, vcpu, read_pci_mmio_before_32bit().start).map_err(Error::SetupMsrs)?;
|
||||
vcpu.set_regs(&vcpu_init.regs).map_err(Error::WriteRegs)?;
|
||||
regs::setup_fpu(vcpu).map_err(Error::SetupFpu)?;
|
||||
regs::setup_sregs(guest_mem, vcpu).map_err(Error::SetupSregs)?;
|
||||
interrupts::set_lint(vcpu_id, irq_chip).map_err(Error::SetLint)?;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use std::{mem, result};
|
||||
|
||||
use base::{self, warn};
|
||||
use hypervisor::{Fpu, Register, Sregs, VcpuX86_64, Vm};
|
||||
use hypervisor::{Register, Sregs, VcpuX86_64, Vm};
|
||||
use remain::sorted;
|
||||
use thiserror::Error;
|
||||
use vm_memory::{GuestAddress, GuestMemory};
|
||||
|
@ -15,9 +15,6 @@ use crate::gdt;
|
|||
#[sorted]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
/// Failed to configure the FPU.
|
||||
#[error("failed to configure the FPU: {0}")]
|
||||
FpuIoctlFailed(base::Error),
|
||||
/// Failed to get sregs for this cpu.
|
||||
#[error("failed to get sregs for this cpu: {0}")]
|
||||
GetSRegsIoctlFailed(base::Error),
|
||||
|
@ -204,21 +201,6 @@ pub fn setup_msrs(vm: &dyn Vm, vcpu: &dyn VcpuX86_64, pci_start: u64) -> Result<
|
|||
vcpu.set_msrs(&msrs).map_err(Error::MsrIoctlFailed)
|
||||
}
|
||||
|
||||
/// Configure FPU registers for x86
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `vcpu` - Structure for the vcpu that holds the vcpu fd.
|
||||
pub fn setup_fpu(vcpu: &dyn VcpuX86_64) -> Result<()> {
|
||||
let fpu = Fpu {
|
||||
fcw: 0x37f,
|
||||
mxcsr: 0x1f80,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
vcpu.set_fpu(&fpu).map_err(Error::FpuIoctlFailed)
|
||||
}
|
||||
|
||||
const X86_CR0_PE: u64 = 0x1;
|
||||
const X86_CR0_PG: u64 = 0x80000000;
|
||||
const X86_CR4_PAE: u64 = 0x20;
|
||||
|
|
|
@ -21,7 +21,7 @@ use vm_memory::{GuestAddress, GuestMemory};
|
|||
|
||||
use super::cpuid::setup_cpuid;
|
||||
use super::interrupts::set_lint;
|
||||
use super::regs::{setup_fpu, setup_msrs, setup_sregs};
|
||||
use super::regs::{setup_msrs, setup_sregs};
|
||||
use super::X8664arch;
|
||||
use super::{
|
||||
acpi, arch_memory_regions, bootparam, init_low_memory_layout, mptable,
|
||||
|
@ -265,7 +265,9 @@ where
|
|||
vcpu_regs.rcx = 0x0;
|
||||
vcpu.set_regs(&vcpu_regs).expect("set regs failed");
|
||||
|
||||
setup_fpu(&vcpu).unwrap();
|
||||
let vcpu_fpu_regs = Default::default();
|
||||
vcpu.set_fpu(&vcpu_fpu_regs).expect("set fpu regs failed");
|
||||
|
||||
setup_sregs(&guest_mem, &vcpu).unwrap();
|
||||
set_lint(0, &mut irq_chip).unwrap();
|
||||
|
||||
|
|
Loading…
Reference in a new issue