Struct linux_kvm::MemoryRegion

source ·
pub struct MemoryRegion { /* private fields */ }
Expand description

A page-aligned host memory region that can be mapped into the guest memory space of a VirtualMachine.

Implementations§

source§

impl MemoryRegion

source

pub fn new(length: size_t) -> Result<Self>

Attempts to allocate a new memory region of a given size.

Examples found in repository?
examples/kvm-vm-setup.rs (line 18)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn run() -> linux_io::result::Result<()> {
    let kvm = Kvm::open()?;
    println!("opened KVM subsystem: {:?}", &kvm);
    let version = kvm.get_api_version()?;
    if version != 12 {
        eprintln!("unsupported KVM API version {}", version);
        return Err(linux_io::result::Error::new(25));
    }
    let mut vm = kvm.create_vm()?;
    println!("created a VM: {:?}", &vm);

    let mut mem = MemoryRegion::new(0x1000)?;
    println!("created a memory region: {:?}", &mem);

    {
        let mem_data = mem.as_mut_slice();

        #[cfg(target_arch = "x86_64")]
        {
            // "UD2" explicitly-undefined instruction
            mem_data[0] = 0x0f;
            mem_data[1] = 0x0b;
        }

        #[cfg(target_arch = "aarch64")]
        {
            // "udf" explicitly-undefined instruction
            mem_data[0] = 0x01;
            mem_data[1] = 0x00;
            mem_data[2] = 0x00;
            mem_data[3] = 0x00;
        }
    }

    vm.set_guest_memory_region(0, KVM_MEM_READONLY, 0x1000, &mut mem)?;
    println!("registered the memory region with the VM");

    let cpu = vm.create_vcpu(0)?;
    println!("created a VCPU: {:?}", &cpu);
    let mut runner = cpu.to_runner()?;
    println!("created a VCPU runner: {:?}", &runner);
    runner.with_raw_run_state(|state| println!("run state: {:?}", &state));

    runner.modify_regs(|regs| {
        #[cfg(target_arch = "x86_64")]
        {
            regs.rip = 0x1000;
        }
        #[cfg(target_arch = "aarch64")]
        {
            regs.regs.pc = 0x1000;
        }
    })?;
    println!("set initial register values");

    #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
    {
        runner.run_raw()?;
        runner.with_raw_run_state(|state| println!("run state after running: {:?}", &state));
        let regs = runner.get_regs()?;
        println!("registers after running: {:?}", &regs)
    }

    Ok(())
}
source

pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [u8]

Returns a view of the memory region as a mutable slice, which the caller can then modify to populate the memory area.

Examples found in repository?
examples/kvm-vm-setup.rs (line 22)
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn run() -> linux_io::result::Result<()> {
    let kvm = Kvm::open()?;
    println!("opened KVM subsystem: {:?}", &kvm);
    let version = kvm.get_api_version()?;
    if version != 12 {
        eprintln!("unsupported KVM API version {}", version);
        return Err(linux_io::result::Error::new(25));
    }
    let mut vm = kvm.create_vm()?;
    println!("created a VM: {:?}", &vm);

    let mut mem = MemoryRegion::new(0x1000)?;
    println!("created a memory region: {:?}", &mem);

    {
        let mem_data = mem.as_mut_slice();

        #[cfg(target_arch = "x86_64")]
        {
            // "UD2" explicitly-undefined instruction
            mem_data[0] = 0x0f;
            mem_data[1] = 0x0b;
        }

        #[cfg(target_arch = "aarch64")]
        {
            // "udf" explicitly-undefined instruction
            mem_data[0] = 0x01;
            mem_data[1] = 0x00;
            mem_data[2] = 0x00;
            mem_data[3] = 0x00;
        }
    }

    vm.set_guest_memory_region(0, KVM_MEM_READONLY, 0x1000, &mut mem)?;
    println!("registered the memory region with the VM");

    let cpu = vm.create_vcpu(0)?;
    println!("created a VCPU: {:?}", &cpu);
    let mut runner = cpu.to_runner()?;
    println!("created a VCPU runner: {:?}", &runner);
    runner.with_raw_run_state(|state| println!("run state: {:?}", &state));

    runner.modify_regs(|regs| {
        #[cfg(target_arch = "x86_64")]
        {
            regs.rip = 0x1000;
        }
        #[cfg(target_arch = "aarch64")]
        {
            regs.regs.pc = 0x1000;
        }
    })?;
    println!("set initial register values");

    #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
    {
        runner.run_raw()?;
        runner.with_raw_run_state(|state| println!("run state after running: {:?}", &state));
        let regs = runner.get_regs()?;
        println!("registers after running: {:?}", &regs)
    }

    Ok(())
}

Trait Implementations§

source§

impl Debug for MemoryRegion

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'a> Drop for MemoryRegion

source§

fn drop(&mut self)

MemoryRegion automatically releases its memory mapping when dropped, and will panic if that fails.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.