1 // Copyright 2017 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #![cfg(any(target_os = "android", target_os = "linux"))]
6 #![cfg(target_arch = "x86_64")]
7
8 use base::MemoryMappingBuilder;
9 use base::SharedMemory;
10 use kvm::*;
11 use kvm_sys::kvm_regs;
12 use vm_memory::GuestAddress;
13 use vm_memory::GuestMemory;
14
15 #[test]
test_run()16 fn test_run() {
17 /*
18 0000 881C mov [si],bl
19 0002 F4 hlt
20 */
21 let code = [0x88, 0x1c, 0xf4];
22 let mem_size = 0x10000;
23 let load_addr = GuestAddress(0x1000);
24 let guest_mem = GuestMemory::new(&[]).unwrap();
25 let mem = SharedMemory::new("test", mem_size).expect("failed to create shared memory");
26 let mmap = MemoryMappingBuilder::new(mem_size as usize)
27 .from_shared_memory(&mem)
28 .build()
29 .expect("failed to create memory mapping");
30
31 mmap.write_slice(&code[..], load_addr.offset() as usize)
32 .expect("Writing code to memory failed.");
33
34 let kvm = Kvm::new().expect("new kvm failed");
35 let mut vm = Vm::new(&kvm, guest_mem).expect("new vm failed");
36 let vcpu = Vcpu::new(0, &kvm, &vm).expect("new vcpu failed");
37 let mut vcpu_sregs = vcpu.get_sregs().expect("get sregs failed");
38 vcpu_sregs.cs.base = 0;
39 vcpu_sregs.cs.selector = 0;
40 vcpu.set_sregs(&vcpu_sregs).expect("set sregs failed");
41
42 // SAFETY: trivially safe
43 let mut vcpu_regs: kvm_regs = unsafe { std::mem::zeroed() };
44 vcpu_regs.rip = load_addr.offset();
45 vcpu_regs.rflags = 2;
46 // Write 0x12 to the beginning of the 9th page.
47 vcpu_regs.rsi = 0x8000;
48 vcpu_regs.rbx = 0x12;
49 vcpu.set_regs(&vcpu_regs).expect("set regs failed");
50 let slot = vm
51 .add_memory_region(
52 GuestAddress(0),
53 Box::new(
54 MemoryMappingBuilder::new(mem_size as usize)
55 .from_shared_memory(&mem)
56 .build()
57 .expect("failed to create memory mapping"),
58 ),
59 false,
60 true,
61 )
62 .expect("failed to register memory");
63
64 let runnable_vcpu = vcpu.to_runnable(None).unwrap();
65 let run_result = runnable_vcpu.run().expect("run failed");
66 if !matches!(run_result, VcpuExit::Hlt) {
67 panic!("unexpected exit reason: {:?}", run_result);
68 }
69
70 let mut dirty_log = [0x0, 0x0];
71 vm.get_dirty_log(slot, &mut dirty_log[..])
72 .expect("failed to get dirty log");
73 // Tests the 9th page was written to.
74 assert_eq!(dirty_log[1], 0x1);
75 assert_eq!(
76 mmap.read_obj::<u64>(vcpu_regs.rsi as usize).unwrap(),
77 vcpu_regs.rbx
78 );
79 }
80