Skip to content

Commit e904ef3

Browse files
Andrew Jonesandreeaflorescu
authored andcommitted
aarch64: support for getting dirty logs
Signed-off-by: Andrew Jones <[email protected]> Signed-off-by: Diana Popa <[email protected]>
1 parent f2c4d49 commit e904ef3

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

src/ioctls/vm.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
use kvm_bindings::*;
99
use std::fs::File;
10-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1110
use std::os::raw::c_void;
1211
use std::os::raw::{c_int, c_ulong};
1312
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
@@ -697,7 +696,7 @@ impl VmFd {
697696
/// # use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES};
698697
/// # let kvm = Kvm::new().unwrap();
699698
/// # let vm = kvm.create_vm().unwrap();
700-
/// // This examples is based on https://lwn.net/Articles/658511/.
699+
/// // This example is based on https://lwn.net/Articles/658511/.
701700
/// let mem_size = 0x4000;
702701
/// let guest_addr: u64 = 0x1000;
703702
/// let load_addr: *mut u8 = unsafe {
@@ -721,36 +720,62 @@ impl VmFd {
721720
/// };
722721
/// unsafe { vm.set_user_memory_region(mem_region).unwrap() };
723722
///
724-
/// // Dummy x86 code that just calls halt.
725-
/// let x86_code = [
726-
/// 0xf4, /* hlt */
723+
/// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
724+
/// // ASM code that just forces a MMIO Write.
725+
/// let asm_code = [
726+
/// 0xc6, 0x06, 0x00, 0x80, 0x00,
727+
/// ];
728+
/// #[cfg(target_arch = "aarch64")]
729+
/// let asm_code = [
730+
/// 0x01, 0x00, 0x00, 0x10, /* adr x1, <this address> */
731+
/// 0x22, 0x10, 0x00, 0xb9, /* str w2, [x1, #16]; write to this page */
732+
/// 0x02, 0x00, 0x00, 0xb9, /* str w2, [x0]; force MMIO exit */
733+
/// 0x00, 0x00, 0x00, 0x14, /* b <this address>; shouldn't get here, but if so loop forever */
727734
/// ];
728735
///
729736
/// // Write the code in the guest memory. This will generate a dirty page.
730737
/// unsafe {
731738
/// let mut slice = slice::from_raw_parts_mut(load_addr, mem_size);
732-
/// slice.write(&x86_code).unwrap();
739+
/// slice.write(&asm_code).unwrap();
733740
/// }
734741
///
735742
/// let vcpu_fd = vm.create_vcpu(0).unwrap();
736743
///
737-
/// let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
738-
/// vcpu_sregs.cs.base = 0;
739-
/// vcpu_sregs.cs.selector = 0;
740-
/// vcpu_fd.set_sregs(&vcpu_sregs).unwrap();
744+
/// #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
745+
/// {
746+
/// // x86_64 specific registry setup.
747+
/// let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
748+
/// vcpu_sregs.cs.base = 0;
749+
/// vcpu_sregs.cs.selector = 0;
750+
/// vcpu_fd.set_sregs(&vcpu_sregs).unwrap();
751+
///
752+
/// let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
753+
/// // Set the Instruction Pointer to the guest address where we loaded the code.
754+
/// vcpu_regs.rip = guest_addr;
755+
/// vcpu_regs.rax = 2;
756+
/// vcpu_regs.rbx = 3;
757+
/// vcpu_regs.rflags = 2;
758+
/// vcpu_fd.set_regs(&vcpu_regs).unwrap();
759+
/// }
741760
///
742-
/// let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
743-
/// // Set the Instruction Pointer to the guest address where we loaded the code.
744-
/// vcpu_regs.rip = guest_addr;
745-
/// vcpu_regs.rax = 2;
746-
/// vcpu_regs.rbx = 3;
747-
/// vcpu_regs.rflags = 2;
748-
/// vcpu_fd.set_regs(&vcpu_regs).unwrap();
761+
/// #[cfg(target_arch = "aarch64")]
762+
/// {
763+
/// // aarch64 specific registry setup.
764+
/// let mut kvi = kvm_bindings::kvm_vcpu_init::default();
765+
/// vm.get_preferred_target(&mut kvi).unwrap();
766+
/// vcpu_fd.vcpu_init(&kvi).unwrap();
767+
///
768+
/// let core_reg_base: u64 = 0x6030_0000_0010_0000;
769+
/// let mmio_addr: u64 = guest_addr + mem_size as u64;
770+
/// vcpu_fd.set_one_reg(core_reg_base + 2 * 32, guest_addr); // set PC
771+
/// vcpu_fd.set_one_reg(core_reg_base + 2 * 0, mmio_addr); // set X0
772+
/// }
749773
///
750774
/// loop {
751775
/// match vcpu_fd.run().expect("run failed") {
752-
/// VcpuExit::Hlt => {
753-
/// // The code snippet dirties 1 page when loading the code in memory.
776+
/// VcpuExit::MmioWrite(addr, data) => {
777+
/// // On x86_64, the code snippet dirties 1 page when loading the code in memory
778+
/// // while on aarch64 the dirty bit comes from writing to guest_addr (current PC).
754779
/// let dirty_pages_bitmap = vm.get_dirty_log(0, mem_size).unwrap();
755780
/// let dirty_pages = dirty_pages_bitmap
756781
/// .into_iter()
@@ -764,7 +789,6 @@ impl VmFd {
764789
/// }
765790
/// ```
766791
///
767-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
768792
pub fn get_dirty_log(&self, slot: u32, memory_size: usize) -> Result<Vec<u64>> {
769793
// Compute the length of the bitmap needed for all dirty pages in one memory slot.
770794
// One memory page is 4KiB (4096 bits) and `KVM_GET_DIRTY_LOG` returns one dirty bit for

src/kvm_ioctls.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ ioctl_iowr_nr!(KVM_GET_EMULATED_CPUID, KVMIO, 0x09, kvm_cpuid2);
2525
// Ioctls for VM fds.
2626

2727
ioctl_io_nr!(KVM_CREATE_VCPU, KVMIO, 0x41);
28-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
2928
ioctl_iow_nr!(KVM_GET_DIRTY_LOG, KVMIO, 0x42, kvm_dirty_log);
3029
/* Available with KVM_CAP_USER_MEMORY */
3130
ioctl_iow_nr!(

0 commit comments

Comments
 (0)