diff --git a/src/dragonball/Cargo.toml b/src/dragonball/Cargo.toml index 3cc17de1dd..d1b87beda4 100644 --- a/src/dragonball/Cargo.toml +++ b/src/dragonball/Cargo.toml @@ -51,9 +51,11 @@ hotplug = ["virtio-vsock"] virtio-vsock = ["dbs-virtio-devices/virtio-vsock", "virtio-queue"] [patch.'crates-io'] -dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } -dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } -dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } -dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } -dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } -dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" } +dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-boot = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } +dbs-arch = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" } diff --git a/src/dragonball/src/vcpu/aarch64.rs b/src/dragonball/src/vcpu/aarch64.rs index 8e78efdc10..759774a620 100644 --- a/src/dragonball/src/vcpu/aarch64.rs +++ b/src/dragonball/src/vcpu/aarch64.rs @@ -8,15 +8,18 @@ use std::sync::mpsc::{channel, Sender}; use std::sync::Arc; +use std::ops::Deref; use crate::IoManagerCached; use dbs_utils::time::TimestampUs; +use dbs_arch::regs; +use dbs_boot::get_fdt_addr; use kvm_ioctls::{VcpuFd, VmFd}; -use vm_memory::GuestAddress; +use vm_memory::{Address, GuestAddress, GuestAddressSpace}; use vmm_sys_util::eventfd::EventFd; use crate::address_space_manager::GuestAddressSpaceImpl; -use crate::vcpu::vcpu_impl::{Result, Vcpu, VcpuStateEvent}; +use crate::vcpu::vcpu_impl::{Result, Vcpu, VcpuStateEvent, VcpuError}; use crate::vcpu::VcpuConfig; #[allow(unused)] @@ -83,7 +86,34 @@ impl Vcpu { kernel_load_addr: Option, _pgtable_addr: Option, ) -> Result<()> { - // TODO: add arm vcpu configure() function. issue: #4445 + let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default(); + + // This reads back the kernel's preferred target type. + vm_fd + .get_preferred_target(&mut kvi) + .map_err(VcpuError::VcpuArmPreferredTarget)?; + // We already checked that the capability is supported. + kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_PSCI_0_2; + // Non-boot cpus are powered off initially. + if self.id > 0 { + kvi.features[0] |= 1 << kvm_bindings::KVM_ARM_VCPU_POWER_OFF; + } + + self.fd.vcpu_init(&kvi).map_err(VcpuError::VcpuArmInit)?; + + if let Some(address) = kernel_load_addr { + regs::setup_regs( + &self.fd, + self.id, + address.raw_value(), + get_fdt_addr(vm_as.memory().deref()), + ) + .map_err(VcpuError::REGSConfiguration)?; + } + + self.mpidr = + regs::read_mpidr(&self.fd).map_err(VcpuError::REGSConfiguration)?; + Ok(()) } diff --git a/src/dragonball/src/vcpu/vcpu_impl.rs b/src/dragonball/src/vcpu/vcpu_impl.rs index 7c39ca2805..d2711cace4 100644 --- a/src/dragonball/src/vcpu/vcpu_impl.rs +++ b/src/dragonball/src/vcpu/vcpu_impl.rs @@ -452,9 +452,6 @@ impl Vcpu { Ok(VcpuEmulation::Handled) } VcpuExit::MmioWrite(addr, data) => { - #[cfg(target_arch = "aarch64")] - self.check_boot_complete_signal(addr, data); - let _ = self.io_mgr.mmio_write(addr, data); METRICS.vcpu.exit_mmio_write.inc(); Ok(VcpuEmulation::Handled) @@ -851,20 +848,52 @@ pub mod tests { (vcpu, rx) } - #[cfg(target_arch = "x86_64")] + #[cfg(target_arch = "aarch64")] + fn create_vcpu() -> (Vcpu, Receiver) { + // Call for kvm too frequently would cause error in some host kernel. + std::thread::sleep(std::time::Duration::from_millis(5)); + + let kvm = Kvm::new().unwrap(); + let vm = Arc::new(kvm.create_vm().unwrap()); + let kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap(); + let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap()); + let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new())))); + let reset_event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap(); + let vcpu_state_event = EventFd::new(libc::EFD_NONBLOCK).unwrap(); + let (tx, rx) = channel(); + let time_stamp = TimestampUs::default(); + + let vcpu = Vcpu::new_aarch64( + 0, + vcpu_fd, + io_manager, + reset_event_fd, + vcpu_state_event, + tx, + time_stamp, + false, + ) + .unwrap(); + + (vcpu, rx) + } + #[test] fn test_vcpu_run_emulation() { let (mut vcpu, _) = create_vcpu(); - // Io in - *(EMULATE_RES.lock().unwrap()) = EmulationCase::IoIn; - let res = vcpu.run_emulation(); - assert!(matches!(res, Ok(VcpuEmulation::Handled))); + #[cfg(target_arch = "x86_64")] + { + // Io in + *(EMULATE_RES.lock().unwrap()) = EmulationCase::IoIn; + let res = vcpu.run_emulation(); + assert!(matches!(res, Ok(VcpuEmulation::Handled))); - // Io out - *(EMULATE_RES.lock().unwrap()) = EmulationCase::IoOut; - let res = vcpu.run_emulation(); - assert!(matches!(res, Ok(VcpuEmulation::Handled))); + // Io out + *(EMULATE_RES.lock().unwrap()) = EmulationCase::IoOut; + let res = vcpu.run_emulation(); + assert!(matches!(res, Ok(VcpuEmulation::Handled))); + } // Mmio read *(EMULATE_RES.lock().unwrap()) = EmulationCase::MmioRead;