Skip to content

Commit a1f6425

Browse files
Andrew Jonesandreeaflorescu
authored andcommitted
aarch64: add test_run_code
Signed-off-by: Andrew Jones <[email protected]> Signed-off-by: Diana Popa <[email protected]>
1 parent e904ef3 commit a1f6425

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

src/ioctls/vcpu.rs

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,6 @@ impl AsRawFd for VcpuFd {
11921192
mod tests {
11931193
extern crate byteorder;
11941194

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

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

@@ -1430,6 +1428,101 @@ mod tests {
14301428
}
14311429
}
14321430

1431+
#[cfg(target_arch = "aarch64")]
1432+
#[test]
1433+
fn test_run_code() {
1434+
use std::io::Write;
1435+
1436+
let kvm = Kvm::new().unwrap();
1437+
let vm = kvm.create_vm().unwrap();
1438+
#[rustfmt::skip]
1439+
let code = [
1440+
0x40, 0x20, 0x80, 0x52, /* mov w0, #0x102 */
1441+
0x00, 0x01, 0x00, 0xb9, /* str w0, [x8]; test physical memory write */
1442+
0x81, 0x60, 0x80, 0x52, /* mov w1, #0x304 */
1443+
0x02, 0x00, 0x80, 0x52, /* mov w2, #0x0 */
1444+
0x20, 0x01, 0x40, 0xb9, /* ldr w0, [x9]; test MMIO read */
1445+
0x1f, 0x18, 0x14, 0x71, /* cmp w0, #0x506 */
1446+
0x20, 0x00, 0x82, 0x1a, /* csel w0, w1, w2, eq */
1447+
0x20, 0x01, 0x00, 0xb9, /* str w0, [x9]; test MMIO write */
1448+
0x00, 0x00, 0x00, 0x14, /* b <this address>; shouldn't get here, but if so loop forever */
1449+
];
1450+
1451+
let mem_size = 0x20000;
1452+
let load_addr = mmap_anonymous(mem_size);
1453+
let guest_addr: u64 = 0x10000;
1454+
let slot: u32 = 0;
1455+
let mem_region = kvm_userspace_memory_region {
1456+
slot,
1457+
guest_phys_addr: guest_addr,
1458+
memory_size: mem_size as u64,
1459+
userspace_addr: load_addr as u64,
1460+
flags: KVM_MEM_LOG_DIRTY_PAGES,
1461+
};
1462+
unsafe {
1463+
vm.set_user_memory_region(mem_region).unwrap();
1464+
}
1465+
1466+
unsafe {
1467+
// Get a mutable slice of `mem_size` from `load_addr`.
1468+
// This is safe because we mapped it before.
1469+
let mut slice = std::slice::from_raw_parts_mut(load_addr, mem_size);
1470+
slice.write(&code).unwrap();
1471+
}
1472+
1473+
let vcpu_fd = vm.create_vcpu(0).unwrap();
1474+
let mut kvi = kvm_bindings::kvm_vcpu_init::default();
1475+
vm.get_preferred_target(&mut kvi).unwrap();
1476+
vcpu_fd.vcpu_init(&kvi).unwrap();
1477+
1478+
let core_reg_base: u64 = 0x6030_0000_0010_0000;
1479+
let mmio_addr: u64 = guest_addr + mem_size as u64;
1480+
1481+
// Set the PC to the guest address where we loaded the code.
1482+
vcpu_fd
1483+
.set_one_reg(core_reg_base + 2 * 32, guest_addr)
1484+
.unwrap();
1485+
1486+
// Set x8 and x9 to the addresses the guest test code needs
1487+
vcpu_fd
1488+
.set_one_reg(core_reg_base + 2 * 8, guest_addr + 0x10000)
1489+
.unwrap();
1490+
vcpu_fd
1491+
.set_one_reg(core_reg_base + 2 * 9, mmio_addr)
1492+
.unwrap();
1493+
1494+
loop {
1495+
match vcpu_fd.run().expect("run failed") {
1496+
VcpuExit::MmioRead(addr, data) => {
1497+
assert_eq!(addr, mmio_addr);
1498+
assert_eq!(data.len(), 4);
1499+
data[3] = 0x0;
1500+
data[2] = 0x0;
1501+
data[1] = 0x5;
1502+
data[0] = 0x6;
1503+
}
1504+
VcpuExit::MmioWrite(addr, data) => {
1505+
assert_eq!(addr, mmio_addr);
1506+
assert_eq!(data.len(), 4);
1507+
assert_eq!(data[3], 0x0);
1508+
assert_eq!(data[2], 0x0);
1509+
assert_eq!(data[1], 0x3);
1510+
assert_eq!(data[0], 0x4);
1511+
// The code snippet dirties one page at guest_addr + 0x10000.
1512+
// The code page should not be dirty, as it's not written by the guest.
1513+
let dirty_pages_bitmap = vm.get_dirty_log(slot, mem_size).unwrap();
1514+
let dirty_pages = dirty_pages_bitmap
1515+
.into_iter()
1516+
.map(|page| page.count_ones())
1517+
.fold(0, |dirty_page_count, i| dirty_page_count + i);
1518+
assert_eq!(dirty_pages, 1);
1519+
break;
1520+
}
1521+
r => panic!("unexpected exit reason: {:?}", r),
1522+
}
1523+
}
1524+
}
1525+
14331526
#[cfg(target_arch = "x86_64")]
14341527
#[test]
14351528
fn test_run_code() {

0 commit comments

Comments
 (0)