Skip to content

Commit

Permalink
aarch64: update main doc
Browse files Browse the repository at this point in the history
The main doc example for running some
machine code in a microVM is adapted to
also support aarch64 architecture.

Signed-off-by: Diana Popa <dpopa@amazon.com>
  • Loading branch information
dianpopa authored and andreeaflorescu committed Jan 9, 2020
1 parent a1f6425 commit 18bc6b9
Showing 1 changed file with 67 additions and 36 deletions.
103 changes: 67 additions & 36 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
//! # Example - Running a VM on x86_64
//!
//! In this example we are creating a Virtual Machine (VM) with one vCPU.
//! On the vCPU we are running x86_64 specific code. This example is based on
//! On the vCPU we are running machine specific code. This example is based on
//! the [LWN article](https://lwn.net/Articles/658511/) on using the KVM API.
//! The aarch64 example was modfied accordingly.
//!
//! To get code running on the vCPU we are going through the following steps:
//!
Expand All @@ -37,7 +38,7 @@
//! are adding only one memory region and write the code in one memory page.
//! 4. Create a vCPU using the VM object. The vCPU is used for running
//! [vCPU specific ioctls](struct.VcpuFd.html).
//! 5. Setup x86 specific general purpose registers and special registers. For
//! 5. Setup architectural specific general purpose registers and special registers. For
//! details about how and why these registers are set, please check the
//! [LWN article](https://lwn.net/Articles/658511/) on which this example is
//! built.
Expand All @@ -52,7 +53,6 @@
//! use kvm_ioctls::{Kvm, VmFd, VcpuFd};
//! use kvm_ioctls::VcpuExit;
//!
//! #[cfg(target_arch = "x86_64")]
//! fn main(){
//! use std::io::Write;
//! use std::slice;
Expand All @@ -61,15 +61,41 @@
//! use kvm_bindings::KVM_MEM_LOG_DIRTY_PAGES;
//! use kvm_bindings::kvm_userspace_memory_region;
//!
//! let mem_size = 0x4000;
//! let guest_addr = 0x1000;
//! let asm_code: &[u8];
//!
//! // Setting up architectural dependent values.
//! #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
//! {
//! asm_code = &[
//! 0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */
//! 0x00, 0xd8, /* add %bl, %al */
//! 0x04, b'0', /* add $'0', %al */
//! 0xee, /* out %al, %dx */
//! 0xec, /* in %dx, %al */
//! 0xc6, 0x06, 0x00, 0x80, 0x00, /* movl $0, (0x8000); This generates a MMIO Write.*/
//! 0x8a, 0x16, 0x00, 0x80, /* movl (0x8000), %dl; This generates a MMIO Read.*/
//! 0xf4, /* hlt */
//! ];
//! }
//! #[cfg(target_arch = "aarch64")]
//! {
//! asm_code = &[
//! 0x01, 0x00, 0x00, 0x10, /* adr x1, <this address> */
//! 0x22, 0x10, 0x00, 0xb9, /* str w2, [x1, #16]; write to this page */
//! 0x02, 0x00, 0x00, 0xb9, /* str w2, [x0]; This generates a MMIO Write.*/
//! 0x00, 0x00, 0x00, 0x14, /* b <this address>; shouldn't get here, but if so loop forever */
//! ];
//! }
//!
//! // 1. Instantiate KVM.
//! let kvm = Kvm::new().unwrap();
//!
//! // 2. Create a VM.
//! let vm = kvm.create_vm().unwrap();
//!
//! // 3. Initialize Guest Memory.
//! let mem_size = 0x4000;
//! let guest_addr: u64 = 0x1000;
//! let load_addr: *mut u8 = unsafe {
//! libc::mmap(
//! null_mut(),
Expand All @@ -93,39 +119,44 @@
//! };
//! unsafe { vm.set_user_memory_region(mem_region).unwrap() };
//!
//!
//! let x86_code = [
//! 0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */
//! 0x00, 0xd8, /* add %bl, %al */
//! 0x04, b'0', /* add $'0', %al */
//! 0xee, /* out %al, %dx */
//! 0xec, /* in %dx, %al */
//! 0xc6, 0x06, 0x00, 0x80, 0x00, /* movl $0, (0x8000); This generates a MMIO Write.*/
//! 0x8a, 0x16, 0x00, 0x80, /* movl (0x8000), %dl; This generates a MMIO Read.*/
//! 0xf4, /* hlt */
//! ];
//!
//! // Write the code in the guest memory. This will generate a dirty page.
//! unsafe {
//! let mut slice = slice::from_raw_parts_mut(load_addr, mem_size);
//! slice.write(&x86_code).unwrap();
//! slice.write(&asm_code).unwrap();
//! }
//!
//! // 4. Create one vCPU.
//! let vcpu_fd = vm.create_vcpu(0).unwrap();
//!
//! // 5. Initialize general purpose and special registers.
//! let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
//! vcpu_sregs.cs.base = 0;
//! vcpu_sregs.cs.selector = 0;
//! vcpu_fd.set_sregs(&vcpu_sregs).unwrap();
//!
//! let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
//! vcpu_regs.rip = guest_addr;
//! vcpu_regs.rax = 2;
//! vcpu_regs.rbx = 3;
//! vcpu_regs.rflags = 2;
//! vcpu_fd.set_regs(&vcpu_regs).unwrap();
//! #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
//! {
//! // x86_64 specific registry setup.
//! let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
//! vcpu_sregs.cs.base = 0;
//! vcpu_sregs.cs.selector = 0;
//! vcpu_fd.set_sregs(&vcpu_sregs).unwrap();
//!
//! let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
//! vcpu_regs.rip = guest_addr;
//! vcpu_regs.rax = 2;
//! vcpu_regs.rbx = 3;
//! vcpu_regs.rflags = 2;
//! vcpu_fd.set_regs(&vcpu_regs).unwrap();
//! }
//!
//! #[cfg(target_arch = "aarch64")]
//! {
//! // aarch64 specific registry setup.
//! 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;
//! vcpu_fd.set_one_reg(core_reg_base + 2 * 32, guest_addr); // set PC
//! vcpu_fd.set_one_reg(core_reg_base + 2 * 0, mmio_addr); // set X0
//! }
//!
//! // 6. Run code on the vCPU.
//! loop {
Expand Down Expand Up @@ -155,26 +186,26 @@
//! "Received an MMIO Write Request to the address {:#x}.",
//! addr,
//! );
//! }
//! VcpuExit::Hlt => {
//! // The code snippet dirties 1 page when it is loaded in memory
//! 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);
//! // Since on aarch64 there is not halt instruction,
//! // we break immediately after the last known instruction
//! // of the asm code example so that we avoid an infinite loop.
//! #[cfg(target_arch = "aarch64")]
//! break;
//! }
//! VcpuExit::Hlt => {
//! break;
//! }
//! r => panic!("Unexpected exit reason: {:?}", r),
//! }
//! }
//! }
//!
//! #[cfg(not(target_arch = "x86_64"))]
//! fn main() {
//! println!("This code example only works on x86_64.");
//! }
//! ```
extern crate kvm_bindings;
Expand Down

0 comments on commit 18bc6b9

Please sign in to comment.