linux_kvm/
raw.rs

1//! Raw data types for use with various KVM `ioctl` requests.
2
3use linux_unsafe::ulong;
4
5/// The layout of the shared memory region used to communicate with the
6/// `KVM_RUN` ioctl request, which is `mmap`ed from the VCPU's file descriptor.
7#[allow(non_camel_case_types)]
8#[derive(Clone, Copy)]
9#[repr(C)]
10pub struct kvm_run {
11    pub request_interrupt_window: u8,
12    pub immediate_exit: u8,
13    pub padding1: [u8; 6],
14    pub exit_reason: u32,
15    pub ready_for_interrupt_injection: u8,
16    pub if_flag: u8,
17    pub flags: u16,
18    pub cr8: u64,
19    pub apic_base: u64,
20
21    #[cfg(target_arch = "s390x")]
22    pub psw_mask: u64,
23    #[cfg(target_arch = "s390x")]
24    pub psw_addr: u64,
25
26    pub exit_details: ExitDetails,
27}
28
29impl core::fmt::Debug for kvm_run {
30    #[inline(never)]
31    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32        let mut ds = f.debug_struct("kvm_run");
33        ds.field("request_interrupt_window", &self.request_interrupt_window)
34            .field("immediate_exit", &self.immediate_exit)
35            .field("padding1", &self.padding1)
36            .field("exit_reason", &self.exit_reason)
37            .field(
38                "ready_for_interrupt_injection",
39                &self.ready_for_interrupt_injection,
40            )
41            .field("if_flag", &self.if_flag)
42            .field("flags", &self.flags)
43            .field("cr8", &self.cr8)
44            .field("apic_base", &self.apic_base);
45
46        #[cfg(target_arch = "s390x")]
47        {
48            ds.field("psw_mask", &self.psw_mask)
49                .field("psw_addr", &self.psw_addr);
50        }
51
52        #[cfg(not(feature = "nightly"))]
53        ds.field("exit_details", &self.exit_details);
54        // more useful debug info when DebugStruct.field_with is available
55        #[cfg(feature = "nightly")]
56        ds.field_with(
57            "exit_details",
58            #[inline(never)]
59            |f| {
60                let mut ds = f.debug_struct("ExitDetails");
61                // The following is technically unsound because all of the fields
62                // are pub and so it's possible to construct a value where
63                // exit_reason disagrees with exit_details, but all of the variants
64                // are just plain data without any implicit padding and with
65                // field types where all bit patterns are valid, so this should
66                // be okay in practice and makes this debug output far more useful.
67                match self.exit_reason {
68                    0 => ds.field("hw", unsafe { &self.exit_details.hw }).finish(),
69                    1 => ds
70                        .field("exception", unsafe { &self.exit_details.ex })
71                        .finish(),
72                    2 => ds.field("io", unsafe { &self.exit_details.io }).finish(),
73                    4 => ds
74                        .field("debug", unsafe { &self.exit_details.debug })
75                        .finish(),
76                    6 => ds
77                        .field("mmio", unsafe { &self.exit_details.mmio })
78                        .finish(),
79                    9 => ds
80                        .field("fail_entry", unsafe { &self.exit_details.fail_entry })
81                        .finish(),
82                    24 => ds
83                        .field("system_event", unsafe { &self.exit_details.system_event })
84                        .finish(),
85                    35 => ds
86                        .field("riscv_sbi", unsafe { &self.exit_details.riscv_sbi })
87                        .finish(),
88                    36 => ds
89                        .field("riscv_csr", unsafe { &self.exit_details.riscv_csr })
90                        .finish(),
91                    37 => ds
92                        .field("notify", unsafe { &self.exit_details.notify })
93                        .finish(),
94                    39 => ds
95                        .field("memory_fault", unsafe { &self.exit_details.memory_fault })
96                        .finish(),
97                    _ => ds.finish_non_exhaustive(),
98                }
99            },
100        );
101        ds.finish()
102    }
103}
104
105#[allow(non_camel_case_types)]
106#[derive(Clone, Copy, Debug)]
107#[repr(C)]
108pub struct kvm_userspace_memory_region {
109    pub slot: u32,
110    pub flags: u32,
111    pub guest_phys_addr: u64,
112    pub memory_size: u64,    // in bytes
113    pub userspace_addr: u64, // start of the userspace allocated memory
114}
115
116#[cfg(target_arch = "x86_64")]
117#[allow(non_camel_case_types)]
118#[derive(Clone, Copy, Debug)]
119#[repr(C)]
120pub struct kvm_regs {
121    pub rax: u64,
122    pub rbx: u64,
123    pub rcx: u64,
124    pub rdx: u64,
125    pub rsi: u64,
126    pub rdi: u64,
127    pub rsp: u64,
128    pub rbp: u64,
129    pub r8: u64,
130    pub r9: u64,
131    pub r10: u64,
132    pub r11: u64,
133    pub r12: u64,
134    pub r13: u64,
135    pub r14: u64,
136    pub r15: u64,
137    pub rip: u64,
138    pub rflags: u64,
139}
140
141#[cfg(target_arch = "aarch64")]
142#[allow(non_camel_case_types)]
143#[derive(Clone, Copy, Debug)]
144#[repr(C)]
145pub struct kvm_regs {
146    pub regs: aarch64_user_pt_regs,
147    pub sp_el1: u64,
148    pub elr_el1: u64,
149    pub spsr: [u64; 5],
150    pub fp_regs: aarch64_user_fpsimd_state,
151}
152
153#[cfg(target_arch = "aarch64")]
154#[allow(non_camel_case_types)]
155#[derive(Clone, Copy, Debug)]
156#[repr(C)]
157pub struct aarch64_user_pt_regs {
158    pub regs: [u64; 31],
159    pub sp: u64,
160    pub pc: u64,
161    pub pstate: u64,
162}
163
164#[cfg(target_arch = "aarch64")]
165#[allow(non_camel_case_types)]
166#[derive(Clone, Copy, Debug)]
167#[repr(C)]
168pub struct aarch64_user_fpsimd_state {
169    pub vregs: [u128; 32],
170    pub fpsr: u32,
171    pub fpcr: u32,
172    pub __reserved: [u32; 2],
173}
174
175#[cfg(target_arch = "riscv64")]
176#[allow(non_camel_case_types)]
177#[derive(Clone, Copy, Debug)]
178#[repr(C)]
179pub struct kvm_regs {
180    // The RISC-V port does not support getting/setting
181    // all registers together. It only supports individual
182    // register accesses using the GET_ONE_REG/SET_ONE_REG operations.
183}
184
185#[allow(non_camel_case_types)]
186#[derive(Clone, Copy, Debug)]
187#[repr(C)]
188pub struct kvm_one_reg {
189    pub id: u64,
190    pub addr: u64,
191}
192
193#[allow(non_camel_case_types)]
194#[derive(Clone, Copy, Debug)]
195#[repr(C)]
196pub struct kvm_debug_exit_arch {
197    // TODO: Use conditional compilation to vary this by target architecture,
198    // for those that actually use this.
199}
200
201/// Used for the `exit_details` field of [`kvm_run`].
202#[derive(Clone, Copy)]
203#[repr(C)]
204pub union ExitDetails {
205    pub hw: ExitUnknown,
206    pub fail_entry: ExitFailEntry,
207    pub ex: ExitException,
208    pub io: ExitIo,
209    pub debug: ExitDebug,
210    pub mmio: ExitMmio,
211    pub system_event: ExitSystemEvent,
212    pub riscv_sbi: ExitRiscvSbi,
213    pub riscv_csr: ExitRiscvCsr,
214    pub notify: ExitNotify,
215    pub memory_fault: ExitMemoryFault,
216    // TODO: The rest of these
217    pub padding: [linux_unsafe::char; 256],
218}
219
220impl core::fmt::Debug for ExitDetails {
221    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
222        f.debug_struct("ExitDetails").finish_non_exhaustive()
223    }
224}
225
226#[derive(Clone, Copy, Debug)]
227#[repr(C)]
228pub struct ExitUnknown {
229    pub hardware_exit_reason: u64,
230}
231
232#[derive(Clone, Copy, Debug)]
233#[repr(C)]
234pub struct ExitFailEntry {
235    pub hardware_entry_failure_reason: u64,
236    pub cpu: u32,
237}
238
239#[derive(Clone, Copy, Debug)]
240#[repr(C)]
241pub struct ExitException {
242    pub exception: u32,
243    pub error_code: u32,
244}
245
246#[derive(Clone, Copy, Debug)]
247#[repr(C)]
248pub struct ExitIo {
249    pub direction: u8,
250    pub size: u8,
251    pub port: u16,
252    pub count: u32,
253    pub data_offset: u64,
254}
255
256#[derive(Clone, Copy, Debug)]
257#[repr(C)]
258pub struct ExitDebug {
259    pub arch: kvm_debug_exit_arch,
260}
261
262#[derive(Clone, Copy, Debug)]
263#[repr(C)]
264pub struct ExitMmio {
265    pub phys_addr: u64,
266    pub data: [u8; 8],
267    pub len: u32,
268    pub is_write: u8,
269}
270
271#[derive(Clone, Copy, Debug)]
272#[repr(C)]
273pub struct ExitSystemEvent {
274    pub type_: u32,
275    pub ndata: u32,
276    pub data: [u64; 16],
277}
278
279#[derive(Clone, Copy, Debug)]
280#[repr(C)]
281pub struct ExitRiscvSbi {
282    pub extension_id: ulong,
283    pub function_id: ulong,
284    pub args: [ulong; 6],
285    pub ret: [ulong; 2],
286}
287
288#[derive(Clone, Copy, Debug)]
289#[repr(C)]
290pub struct ExitRiscvCsr {
291    pub csr_num: ulong,
292    pub new_value: ulong,
293    pub write_mask: ulong,
294    pub ret_value: ulong,
295}
296
297#[derive(Clone, Copy, Debug)]
298#[repr(C)]
299pub struct ExitNotify {
300    pub flags: u32,
301}
302
303#[derive(Clone, Copy, Debug)]
304#[repr(C)]
305pub struct ExitMemoryFault {
306    pub flags: u32,
307    pub gpa: u32,
308    pub size: u32,
309}