zx/
guest.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::{AsHandleRef, Handle, HandleBased, HandleRef, Port, Resource, Status, Vmar, ok, sys};
6
7/// Wrapper type for guest physical addresses.
8#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
9#[repr(transparent)]
10pub struct GPAddr(pub usize);
11
12/// An object representing a Zircon guest
13///
14/// As essentially a subtype of `Handle`, it can be freely interconverted.
15#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
16#[repr(transparent)]
17pub struct Guest(Handle);
18impl_handle_based!(Guest);
19
20impl Guest {
21    pub fn create(hypervisor: &Resource) -> Result<(Guest, Vmar), Status> {
22        unsafe {
23            let mut guest_handle = 0;
24            let mut vmar_handle = 0;
25            ok(sys::zx_guest_create(
26                hypervisor.raw_handle(),
27                0,
28                &mut guest_handle,
29                &mut vmar_handle,
30            ))?;
31            Ok((
32                Self::from(Handle::from_raw(guest_handle)),
33                Vmar::from(Handle::from_raw(vmar_handle)),
34            ))
35        }
36    }
37
38    /// Set a bell trap for the given guest physical address range that will be delivered on the specified `Port`.
39    pub fn set_trap_bell(
40        &self,
41        addr: GPAddr,
42        size: usize,
43        port: &Port,
44        key: u64,
45    ) -> Result<(), Status> {
46        ok(unsafe {
47            sys::zx_guest_set_trap(
48                self.raw_handle(),
49                sys::ZX_GUEST_TRAP_BELL,
50                addr.0,
51                size,
52                port.raw_handle(),
53                key,
54            )
55        })
56    }
57
58    /// Set a memory trap for the given guest physical address range.
59    ///
60    /// The trap will be delivered through calls to `Resume` on the guests `Vcpu`.
61    pub fn set_mem_trap(&self, addr: GPAddr, size: usize, key: u64) -> Result<(), Status> {
62        ok(unsafe {
63            sys::zx_guest_set_trap(
64                self.raw_handle(),
65                sys::ZX_GUEST_TRAP_MEM,
66                addr.0,
67                size,
68                sys::ZX_HANDLE_INVALID,
69                key,
70            )
71        })
72    }
73
74    /// Set an IO trap for the given port range in the guest.
75    ///
76    /// The trap will be delivered through calls to `Resume` on the guests `Vcpu`.
77    pub fn set_io_trap(&self, addr: u16, size: u16, key: u64) -> Result<(), Status> {
78        ok(unsafe {
79            sys::zx_guest_set_trap(
80                self.raw_handle(),
81                sys::ZX_GUEST_TRAP_IO,
82                addr.into(),
83                size.into(),
84                sys::ZX_HANDLE_INVALID,
85                key,
86            )
87        })
88    }
89}
90
91// Below are types and implementations for parts of guest trap packets that allow the type safe
92// wrappers to provide constrained values.
93
94/// Represents the default operand size as specified by the CS descriptor.
95#[derive(Debug, Clone, Copy)]
96pub enum CSDefaultOperandSize {
97    Bits16 = 2,
98    Bits32 = 4,
99}
100
101#[derive(Debug, Clone, Copy)]
102pub enum MemAccessSize {
103    Bits8 = 1,
104    Bits16 = 2,
105    Bits32 = 4,
106    Bits64 = 8,
107}
108
109#[derive(Debug, Clone, Copy)]
110pub enum MemData {
111    Data8(u8),
112    Data16(u16),
113    Data32(u32),
114    Data64(u64),
115}
116
117#[derive(Debug, Clone, Copy)]
118pub enum PortAccessSize {
119    Bits8 = 1,
120    Bits16 = 2,
121    Bits32 = 4,
122}
123
124#[derive(Debug, Clone, Copy)]
125pub enum AccessType {
126    Read,
127    Write,
128}
129
130#[derive(Debug, Clone, Copy)]
131pub enum PortData {
132    Data8(u8),
133    Data16(u16),
134    Data32(u32),
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140    use fidl_fuchsia_kernel as fkernel;
141    use fuchsia_component::client::connect_to_protocol;
142    use zx::HandleBased;
143
144    async fn get_hypervisor() -> Resource {
145        let resource = connect_to_protocol::<fkernel::HypervisorResourceMarker>()
146            .unwrap()
147            .get()
148            .await
149            .unwrap();
150        unsafe { Resource::from(Handle::from_raw(resource.into_raw())) }
151    }
152
153    #[fuchsia::test]
154    async fn guest_create() {
155        let hypervisor = get_hypervisor().await;
156        match Guest::create(&hypervisor) {
157            Err(Status::NOT_SUPPORTED) => {
158                println!("Hypervisor not supported");
159                return;
160            }
161            result => result.unwrap(),
162        };
163    }
164}