mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-28 07:33:09 +00:00
06dc708515
The reset system is asynchronous with an I/O event (PIO or MMIO) for ACPI/i8042/CMOS triggering a write to the reset_evt event handler. The VMM thread will pick up this event on the VMM main loop and then trigger a shutdown in the CpuManager. However since there is some delay between the CPU threads being marked to be killed (through the CpuManager::cpus_kill_signalled bool) it is possible for the guest vCPU that triggered the exit to be re-entered when the vCPU KVM_RUN is called after the I/O exit is completed. This is undesirable and in particular the Linux kernel will attempt to jump to real mode after a CMOS based exit - this is unsupported in nested KVM on AMD on Azure and will trigger an error in KVM_RUN. Solve this problem by spinning in the device that has triggered the reset until the vcpus_kill_signalled boolean has been updated indicating that the VMM thread has received the event and called CpuManager::shutdown(). In particular if this bool is set then the vCPU threads will not re-enter the guest. Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
52 lines
1.3 KiB
Rust
52 lines
1.3 KiB
Rust
// Copyright © 2022 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#![no_main]
|
|
use devices::legacy::Cmos;
|
|
use libc::EFD_NONBLOCK;
|
|
use libfuzzer_sys::fuzz_target;
|
|
use std::sync::atomic::AtomicBool;
|
|
use std::sync::Arc;
|
|
use vm_device::BusDevice;
|
|
use vmm_sys_util::eventfd::EventFd;
|
|
|
|
fuzz_target!(|bytes| {
|
|
// Need at least 16 bytes for the test
|
|
if bytes.len() < 16 {
|
|
return;
|
|
}
|
|
|
|
let mut below_4g = [0u8; 8];
|
|
let mut above_4g = [0u8; 8];
|
|
|
|
below_4g.copy_from_slice(&bytes[0..8]);
|
|
above_4g.copy_from_slice(&bytes[8..16]);
|
|
|
|
let mut cmos = Cmos::new(
|
|
u64::from_le_bytes(below_4g),
|
|
u64::from_le_bytes(above_4g),
|
|
EventFd::new(EFD_NONBLOCK).unwrap(),
|
|
Arc::new(AtomicBool::default()),
|
|
);
|
|
|
|
let mut i = 16;
|
|
while i < bytes.len() {
|
|
let read = bytes.get(i).unwrap_or(&0) % 2 == 0;
|
|
i += 1;
|
|
|
|
if read {
|
|
let offset = (bytes.get(i).unwrap_or(&0) % 2) as u64;
|
|
i += 1;
|
|
let mut out_bytes = vec![0];
|
|
cmos.read(0, offset, &mut out_bytes);
|
|
} else {
|
|
let offset = (bytes.get(i).unwrap_or(&0) % 2) as u64;
|
|
i += 1;
|
|
let data = vec![*bytes.get(i).unwrap_or(&0)];
|
|
i += 1;
|
|
cmos.write(0, offset, &data);
|
|
}
|
|
}
|
|
});
|