Skip to content

Commit 2cc4234

Browse files
authored
Intercept qemu exit port to achieve grace VM shutdown (#16)
1 parent ab5d194 commit 2cc4234

File tree

1 file changed

+33
-29
lines changed

1 file changed

+33
-29
lines changed

src/vmx/vcpu.rs

+33-29
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ use crate::{ept::GuestPageWalkInfo, msr::Msr, regs::GeneralRegisters};
2525

2626
const VMX_PREEMPTION_TIMER_SET_VALUE: u32 = 1_000_000;
2727

28+
const QEMU_EXIT_PORT: u16 = 0x604;
29+
const QEMU_EXIT_MAGIC: u64 = 0x2000;
30+
2831
pub struct XState {
2932
host_xcr0: u64,
3033
guest_xcr0: u64,
@@ -431,40 +434,42 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
431434

432435
// Implementation of private methods
433436
impl<H: AxVCpuHal> VmxVcpu<H> {
434-
#[allow(dead_code)]
435437
fn setup_io_bitmap(&mut self) -> AxResult {
436438
// By default, I/O bitmap is set as `intercept_all`.
437439
// Todo: these should be combined with emulated pio device management,
438440
// in `modules/axvm/src/device/x86_64/mod.rs` somehow.
439441
let io_to_be_intercepted = [
440-
// UART
441-
// 0x3f8..0x3f8 + 8, // COM1
442-
// We need to intercepted the access to COM2 ports.
443-
// Because we want to reserve this port for host Linux.
444-
0x2f8..0x2f8 + 8, // COM2
445-
// 0x3e8..0x3e8 + 8, // COM3
446-
// 0x2e8..0x2e8 + 8, // COM4
447-
// Virual PIC
448-
0x20..0x20 + 2, // PIC1
449-
0xa0..0xa0 + 2, // PIC2
450-
// Debug Port
451-
// 0x80..0x80 + 1, // Debug Port
452-
//
453-
0x92..0x92 + 1, // system_control_a
454-
0x61..0x61 + 1, // system_control_b
455-
// RTC
456-
0x70..0x70 + 2, // CMOS
457-
0x40..0x40 + 4, // PIT
458-
// 0xf0..0xf0 + 2, // ports about fpu
459-
// 0x3d4..0x3d4 + 2, // ports about vga
460-
0x87..0x87 + 1, // port about dma
461-
0x60..0x60 + 1, // ports about ps/2 controller
462-
0x64..0x64 + 1, // ports about ps/2 controller
463-
0xcf8..0xcf8 + 8, // PCI
442+
// // UART
443+
// // 0x3f8..0x3f8 + 8, // COM1
444+
// // We need to intercepted the access to COM2 ports.
445+
// // Because we want to reserve this port for host Linux.
446+
// 0x2f8..0x2f8 + 8, // COM2
447+
// // 0x3e8..0x3e8 + 8, // COM3
448+
// // 0x2e8..0x2e8 + 8, // COM4
449+
// // Virual PIC
450+
// 0x20..0x20 + 2, // PIC1
451+
// 0xa0..0xa0 + 2, // PIC2
452+
// // Debug Port
453+
// // 0x80..0x80 + 1, // Debug Port
454+
// //
455+
// 0x92..0x92 + 1, // system_control_a
456+
// 0x61..0x61 + 1, // system_control_b
457+
// // RTC
458+
// 0x70..0x70 + 2, // CMOS
459+
// 0x40..0x40 + 4, // PIT
460+
// // 0xf0..0xf0 + 2, // ports about fpu
461+
// // 0x3d4..0x3d4 + 2, // ports about vga
462+
// 0x87..0x87 + 1, // port about dma
463+
// 0x60..0x60 + 1, // ports about ps/2 controller
464+
// 0x64..0x64 + 1, // ports about ps/2 controller
465+
// 0xcf8..0xcf8 + 8, // PCI
466+
467+
// QEMU exit port
468+
QEMU_EXIT_PORT..QEMU_EXIT_PORT + 1, // QEMU exit port
464469
];
465470
for port_range in io_to_be_intercepted {
466471
self.io_bitmap.set_intercept_of_range(
467-
port_range.start,
472+
port_range.start as _,
468473
port_range.count() as u32,
469474
true,
470475
);
@@ -704,6 +709,8 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
704709
// Pass-through exceptions (except #UD(6)), don't use I/O bitmap, set MSR bitmaps.
705710
let exception_bitmap: u32 = 1 << 6;
706711

712+
self.setup_io_bitmap()?;
713+
707714
VmcsControl32::EXCEPTION_BITMAP.write(exception_bitmap)?;
708715
VmcsControl64::IO_BITMAP_A_ADDR.write(self.io_bitmap.phys_addr().0.as_usize() as _)?;
709716
VmcsControl64::IO_BITMAP_B_ADDR.write(self.io_bitmap.phys_addr().1.as_usize() as _)?;
@@ -1194,9 +1201,6 @@ impl<H: AxVCpuHal> AxArchVCpu for VmxVcpu<H> {
11941201
warn!("VCpu {:#x?}", self);
11951202
AxVCpuExitReason::Halt
11961203
} else {
1197-
const QEMU_EXIT_PORT: u16 = 0x604;
1198-
const QEMU_EXIT_MAGIC: u64 = 0x2000;
1199-
12001204
let width = match AccessWidth::try_from(io_info.access_size as usize) {
12011205
Ok(width) => width,
12021206
Err(_) => {

0 commit comments

Comments
 (0)