Skip to content

Commit

Permalink
aarch64: add test_run_code
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Diana Popa <dpopa@amazon.com>
  • Loading branch information
Andrew Jones authored and andreeaflorescu committed Jan 9, 2020
1 parent e904ef3 commit a1f6425
Showing 1 changed file with 95 additions and 2 deletions.
97 changes: 95 additions & 2 deletions src/ioctls/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,6 @@ impl AsRawFd for VcpuFd {
mod tests {
extern crate byteorder;

#[cfg(target_arch = "x86_64")]
use super::*;
use ioctls::system::Kvm;
#[cfg(any(
Expand All @@ -1205,7 +1204,6 @@ mod tests {

// Helper function for memory mapping `size` bytes of anonymous memory.
// Panics if the mmap fails.
#[cfg(target_arch = "x86_64")]
fn mmap_anonymous(size: usize) -> *mut u8 {
use std::ptr::null_mut;

Expand Down Expand Up @@ -1430,6 +1428,101 @@ mod tests {
}
}

#[cfg(target_arch = "aarch64")]
#[test]
fn test_run_code() {
use std::io::Write;

let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
#[rustfmt::skip]
let code = [
0x40, 0x20, 0x80, 0x52, /* mov w0, #0x102 */
0x00, 0x01, 0x00, 0xb9, /* str w0, [x8]; test physical memory write */
0x81, 0x60, 0x80, 0x52, /* mov w1, #0x304 */
0x02, 0x00, 0x80, 0x52, /* mov w2, #0x0 */
0x20, 0x01, 0x40, 0xb9, /* ldr w0, [x9]; test MMIO read */
0x1f, 0x18, 0x14, 0x71, /* cmp w0, #0x506 */
0x20, 0x00, 0x82, 0x1a, /* csel w0, w1, w2, eq */
0x20, 0x01, 0x00, 0xb9, /* str w0, [x9]; test MMIO write */
0x00, 0x00, 0x00, 0x14, /* b <this address>; shouldn't get here, but if so loop forever */
];

let mem_size = 0x20000;
let load_addr = mmap_anonymous(mem_size);
let guest_addr: u64 = 0x10000;
let slot: u32 = 0;
let mem_region = kvm_userspace_memory_region {
slot,
guest_phys_addr: guest_addr,
memory_size: mem_size as u64,
userspace_addr: load_addr as u64,
flags: KVM_MEM_LOG_DIRTY_PAGES,
};
unsafe {
vm.set_user_memory_region(mem_region).unwrap();
}

unsafe {
// Get a mutable slice of `mem_size` from `load_addr`.
// This is safe because we mapped it before.
let mut slice = std::slice::from_raw_parts_mut(load_addr, mem_size);
slice.write(&code).unwrap();
}

let vcpu_fd = vm.create_vcpu(0).unwrap();
let mut kvi = kvm_bindings::kvm_vcpu_init::default();
vm.get_preferred_target(&mut kvi).unwrap();
vcpu_fd.vcpu_init(&kvi).unwrap();

let core_reg_base: u64 = 0x6030_0000_0010_0000;
let mmio_addr: u64 = guest_addr + mem_size as u64;

// Set the PC to the guest address where we loaded the code.
vcpu_fd
.set_one_reg(core_reg_base + 2 * 32, guest_addr)
.unwrap();

// Set x8 and x9 to the addresses the guest test code needs
vcpu_fd
.set_one_reg(core_reg_base + 2 * 8, guest_addr + 0x10000)
.unwrap();
vcpu_fd
.set_one_reg(core_reg_base + 2 * 9, mmio_addr)
.unwrap();

loop {
match vcpu_fd.run().expect("run failed") {
VcpuExit::MmioRead(addr, data) => {
assert_eq!(addr, mmio_addr);
assert_eq!(data.len(), 4);
data[3] = 0x0;
data[2] = 0x0;
data[1] = 0x5;
data[0] = 0x6;
}
VcpuExit::MmioWrite(addr, data) => {
assert_eq!(addr, mmio_addr);
assert_eq!(data.len(), 4);
assert_eq!(data[3], 0x0);
assert_eq!(data[2], 0x0);
assert_eq!(data[1], 0x3);
assert_eq!(data[0], 0x4);
// The code snippet dirties one page at guest_addr + 0x10000.
// The code page should not be dirty, as it's not written by the guest.
let dirty_pages_bitmap = vm.get_dirty_log(slot, mem_size).unwrap();
let dirty_pages = dirty_pages_bitmap
.into_iter()
.map(|page| page.count_ones())
.fold(0, |dirty_page_count, i| dirty_page_count + i);
assert_eq!(dirty_pages, 1);
break;
}
r => panic!("unexpected exit reason: {:?}", r),
}
}
}

#[cfg(target_arch = "x86_64")]
#[test]
fn test_run_code() {
Expand Down

0 comments on commit a1f6425

Please sign in to comment.