forked from gz/rust-x86
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port kvm io example to use assembled function
- Loading branch information
1 parent
b18825b
commit 0a52a0d
Showing
5 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
|
||
rm target/debug/kvm-1204d1237e8c62b6 | ||
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="$(dirname $0)/tests/kvm/linker.sh" | ||
cargo test --test kvm -- "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#![feature(linkage, naked_functions, asm)] | ||
// In this example we will construct a single CPU x86 VM which will execute | ||
// "inb 0x01" at ring 0 with paging disabled | ||
|
||
extern crate kvm; | ||
extern crate memmap; | ||
|
||
use kvm::{Capability, Exit, IoDirection, System, Vcpu, VirtualMachine}; | ||
use memmap::{Mmap, Protection}; | ||
|
||
//#[allow(improper_ctypes)] | ||
extern { | ||
static kvmtest_begin_loc: u8; | ||
static kvmtest_end_loc: u8; | ||
} | ||
|
||
#[naked] | ||
//#[allow(dead_code)] | ||
#[link_section = ".kvmtest"] | ||
#[linkage = "external" ] | ||
unsafe extern "C" fn use_the_port() { | ||
asm!("inb $0, %al" :: "i"(0x01) :: "volatile"); | ||
} | ||
|
||
#[test] | ||
fn io_example() { | ||
// Allocate 2MB for the guest memory | ||
let mut anon_mmap = Mmap::anonymous(2 * (1 << 20), Protection::ReadWrite) | ||
.unwrap(); | ||
let slice = unsafe { anon_mmap.as_mut_slice() }; | ||
|
||
let slice2: &mut [u8] = { | ||
let kvmtest_begin: *mut u8 = &kvmtest_begin_loc as *const _ as _; | ||
let kvmtest_end: *mut u8 = &kvmtest_end_loc as *const _ as _; | ||
unsafe { | ||
::std::slice::from_raw_parts_mut( | ||
kvmtest_begin, | ||
(kvmtest_end as usize) - (kvmtest_begin as usize)) | ||
} | ||
}; | ||
|
||
slice[0x100000..][..slice2.len()].copy_from_slice(slice2); | ||
|
||
println!("fn: {:x}", use_the_port as usize); // make sure is used | ||
|
||
println!("slice: {:?}", slice2.as_ptr()); | ||
println!("len: {:x}", slice2.len()); | ||
println!("{:x}", slice[0]); | ||
println!("{:x}", slice[1]); | ||
println!("{:?}", &slice[..10]); | ||
|
||
// Initialize the KVM system | ||
let sys = System::initialize().unwrap(); | ||
|
||
// Create a Virtual Machine | ||
let mut vm = VirtualMachine::create(&sys).unwrap(); | ||
|
||
// Ensure that the VM supports memory backing with user memory | ||
assert!(vm.check_capability(Capability::UserMemory) > 0); | ||
// Set the 2 MB range to start at physical address 0 | ||
vm.set_user_memory_region(0, slice, 0).unwrap(); | ||
|
||
// Create a new VCPU | ||
let mut vcpu = Vcpu::create(&mut vm).unwrap(); | ||
|
||
// Set supported CPUID (KVM fails without doing this) | ||
let mut cpuid = sys.get_supported_cpuid().unwrap(); | ||
vcpu.set_cpuid2(&mut cpuid).unwrap(); | ||
|
||
// Setup the special registers | ||
let mut sregs = vcpu.get_sregs().unwrap(); | ||
|
||
// Set the code segment to have base 0, limit 4GB (flat segmentation) | ||
sregs.cs.base = 0x0; | ||
sregs.cs.limit = 0xffffffff; | ||
sregs.cs.selector = 0x8; | ||
sregs.cs._type = 0xb; | ||
sregs.cs.present = 1; | ||
sregs.cs.dpl = 0; | ||
sregs.cs.db = 0; | ||
sregs.cs.s = 1; | ||
sregs.cs.l = 0; | ||
sregs.cs.g = 1; | ||
sregs.cs.avl = 0; | ||
|
||
// We don't need to populate the GDT if we have our segments setup | ||
// cr0 - protected mode on, paging disabled | ||
sregs.cr0 = 0x50033; | ||
|
||
// Set the special registers | ||
vcpu.set_sregs(&sregs).unwrap(); | ||
|
||
let mut regs = vcpu.get_regs().unwrap(); | ||
// set the instruction pointer to 1 MB | ||
regs.rip = 0x100000; | ||
regs.rflags = 0x2; | ||
vcpu.set_regs(®s).unwrap(); | ||
|
||
// Actually run the VCPU | ||
let run = unsafe { vcpu.run() }.unwrap(); | ||
|
||
// Ensure that the exit reason we get back indicates that the I/O | ||
// instruction was executed | ||
assert!(run.exit_reason == Exit::Io); | ||
let io = unsafe { *run.io() }; | ||
assert!(io.direction == IoDirection::In); | ||
assert!(io.size == 1); | ||
assert!(io.port == 0x1); | ||
unsafe { | ||
println!("{:#?}", *run.io()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/*PHDRS | ||
{ | ||
test PT_LOAD FLAGS(0x7); /* rwx 0b111 *//* | ||
}*/ | ||
|
||
SECTIONS | ||
{ | ||
.kvmtest : | ||
{ | ||
kvmtest_begin_loc = .; | ||
*(.kvmtest*) | ||
kvmtest_end_loc = .; | ||
} /* :test */ | ||
} | ||
|
||
INSERT AFTER .rodata; /* do not override default script */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/sh | ||
set -x | ||
|
||
${CC:=cc} | ||
$CC -T $(dirname $0)/link.ld "$@" |