Skip to content

Commit

Permalink
feat: add --no-console option
Browse files Browse the repository at this point in the history
It is now possible to run a VM without a console with --no-console option

Co-authored-by: Esteban Baron <[email protected]>
Signed-off-by: Alexis Langlet <[email protected]>
  • Loading branch information
EstebanBAR0N authored and alexis-langlet committed Apr 11, 2023
1 parent 01273fb commit 9990b84
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ fn main() -> Result<(), Error> {
opts.cpus,
opts.memory,
&opts.kernel,
opts.console,
opts.console.clone(),
opts.initramfs,
opts.net,
)
.map_err(Error::VmmConfigure)?;

// Run the VMM
vmm.run().map_err(Error::VmmRun)?;
vmm.run(opts.console.is_none()).map_err(Error::VmmRun)?;

Ok(())
}
15 changes: 10 additions & 5 deletions src/vmm/src/cpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl Vcpu {
}

/// vCPU emulation loop.
pub fn run(&mut self) {
pub fn run(&mut self, no_console: bool, should_stop: Arc<Mutex<bool>>) {
// Call into KVM to launch (VMLAUNCH) or resume (VMRESUME) the virtual CPU.
// This is a blocking function, it only returns for either an error or a
// VM-Exit. In the latter case, we can inspect the exit reason.
Expand All @@ -232,11 +232,16 @@ impl Vcpu {
// The VM stopped (Shutdown ot HLT).
VcpuExit::Shutdown | VcpuExit::Hlt => {
println!("Guest shutdown: {:?}. Bye!", exit_reason);
let stdin = io::stdin();
let stdin_lock = stdin.lock();
stdin_lock.set_canon_mode().unwrap();

unsafe { libc::exit(0) };
if no_console {
*should_stop.lock().unwrap() = true;
} else {
let stdin = io::stdin();
let stdin_lock = stdin.lock();
stdin_lock.set_canon_mode().unwrap();

unsafe { libc::exit(0) };
}
}

// This is a PIO write, i.e. the guest is trying to write
Expand Down
2 changes: 1 addition & 1 deletion src/vmm/src/kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const HIMEM_START: u64 = 0x0010_0000; // 1 MB
/// Address where the kernel command line is written.
const CMDLINE_START: u64 = 0x0002_0000;
// Default command line
pub const DEFAULT_CMDLINE: &str = "console=ttyS0 i8042.nokbd reboot=k panic=1 pci=off";
pub const DEFAULT_CMDLINE: &str = "i8042.nokbd reboot=k panic=1 pci=off";

fn add_e820_entry(
params: &mut boot_params,
Expand Down
46 changes: 43 additions & 3 deletions src/vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ extern crate linux_loader;
extern crate vm_memory;
extern crate vm_superio;

use std::any::Any;
use std::fs::File;
use std::io::stdout;
use std::os::unix::io::AsRawFd;
Expand Down Expand Up @@ -83,6 +84,10 @@ pub enum Error {
VirtioNet(devices::net::VirtioNetError),
/// Error related to IOManager.
IoManager(vm_device::device_manager::Error),
/// Access thread handler error
AccessThreadHandlerError,
/// Join thread error
JoinThreadError(Box<dyn Any + Send>),
}

/// Dedicated [`Result`](https://doc.rust-lang.org/std/result/) type.
Expand Down Expand Up @@ -249,6 +254,14 @@ impl VMM {
}

pub fn configure_console(&mut self, console_path: Option<String>) -> Result<()> {
if console_path.is_none() {
return Ok(());
}

self.cmdline
.insert_str("console=ttyS0")
.map_err(Error::Cmdline)?;

if let Some(console_path) = console_path {
// We create the file if it does not exist, else we open
let file = File::create(&console_path).map_err(Error::ConsoleError)?;
Expand Down Expand Up @@ -312,12 +325,39 @@ impl VMM {
}

// Run all virtual CPUs.
pub fn run(&mut self) -> Result<()> {
pub fn run(&mut self, no_console: bool) -> Result<()> {
let mut handlers: Vec<thread::JoinHandle<_>> = Vec::new();
let should_stop = Arc::new(Mutex::new(false));

for mut vcpu in self.vcpus.drain(..) {
println!("Starting vCPU {:?}", vcpu.index);
let _ = thread::Builder::new().spawn(move || loop {
vcpu.run();

let should_stop_cloned = Arc::clone(&should_stop);

let handler = thread::Builder::new().spawn(move || loop {
if *should_stop_cloned.lock().unwrap() {
println!("Stopping vCPU {:?}", vcpu.index);
break;
}

vcpu.run(no_console, Arc::clone(&should_stop_cloned));
});

match handler {
Ok(handler) => handlers.push(handler),
Err(_) => {
println!("Failed to start vCPU");
return Err(Error::AccessThreadHandlerError);
}
}
}

if no_console {
for handler in handlers {
handler.join().map_err(Error::JoinThreadError)?
}

return Ok(()); // We don't want to start the console if we are in no_console mode.
}

let stdin = io::stdin();
Expand Down

0 comments on commit 9990b84

Please sign in to comment.