@@ -1192,7 +1192,6 @@ impl AsRawFd for VcpuFd {
1192
1192
mod tests {
1193
1193
extern crate byteorder;
1194
1194
1195
- #[ cfg( target_arch = "x86_64" ) ]
1196
1195
use super :: * ;
1197
1196
use ioctls:: system:: Kvm ;
1198
1197
#[ cfg( any(
@@ -1205,7 +1204,6 @@ mod tests {
1205
1204
1206
1205
// Helper function for memory mapping `size` bytes of anonymous memory.
1207
1206
// Panics if the mmap fails.
1208
- #[ cfg( target_arch = "x86_64" ) ]
1209
1207
fn mmap_anonymous ( size : usize ) -> * mut u8 {
1210
1208
use std:: ptr:: null_mut;
1211
1209
@@ -1430,6 +1428,101 @@ mod tests {
1430
1428
}
1431
1429
}
1432
1430
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
+
1433
1526
#[ cfg( target_arch = "x86_64" ) ]
1434
1527
#[ test]
1435
1528
fn test_run_code ( ) {
0 commit comments