Alioth Code Coverage

kvm.rs0.00%

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::{Debug, Formatter, Result};
16
17use bitfield::bitfield;
18
19use crate::sys::ioctl::{ioctl_ior, ioctl_iowr};
20use crate::{
21 bitflags, consts, ioctl_none, ioctl_read, ioctl_write_buf, ioctl_write_ptr, ioctl_write_val,
22 ioctl_writeread, ioctl_writeread_buf,
23};
24
25pub const KVMIO: u8 = 0xAE;
26pub const KVM_API_VERSION: i32 = 12;
27
28#[cfg(target_arch = "x86_64")]
29consts! {
30 pub struct KvmVmType(u64) {
31 DEFAULT = 0;
32 SW_PROTECTED = 1;
33 SEV = 2;
34 SEV_ES = 3;
35 SNP = 4;
36 TDX = 5;
37 }
38}
39#[cfg(target_arch = "aarch64")]
40pub struct KvmVmType(#[allow(dead_code)] pub u64);
41
42pub const KVM_MAX_CPUID_ENTRIES: usize = 256;
43
44bitflags! {
45 #[derive(Default)]
46 pub struct KvmCpuid2Flag(u32) {
47 SIGNIFCANT_INDEX = 1 << 0;
48 }
49}
50
51#[repr(C)]
52#[derive(Debug, Copy, Clone, Default)]
53pub struct KvmCpuidEntry2 {
54 pub function: u32,
55 pub index: u32,
56 pub flags: KvmCpuid2Flag,
57 pub eax: u32,
58 pub ebx: u32,
59 pub ecx: u32,
60 pub edx: u32,
61 pub padding: [u32; 3],
62}
63
64#[repr(C)]
65#[derive(Debug, Clone)]
66pub struct KvmCpuid2<const N: usize> {
67 pub nent: u32,
68 pub padding: u32,
69 pub entries: [KvmCpuidEntry2; N],
70}
71
72pub const KVM_CPUID_SIGNATURE: u32 = 0x4000_0000;
73pub const KVM_CPUID_FEATURES: u32 = 0x4000_0001;
74
75bitflags! {
76 pub struct KvmCpuidFeature(u32) {
77 CLOCKSOURCE = 1 << 0;
78 NOP_IO_DELAY = 1 << 1;
79 MMU_OP = 1 << 2;
80 CLOCKSOURCE2 = 1 << 3;
81 ASYNC_PF = 1 << 4;
82 STEAL_TIME = 1 << 5;
83 PV_EOI = 1 << 6;
84 PV_UNHALT = 1 << 7;
85 PV_TLB_FLUSH = 1 << 9;
86 ASYNC_PF_VMEXIT = 1 << 10;
87 PV_SEND_IPI = 1 << 11;
88 POLL_CONTROL = 1 << 12;
89 PV_SCHED_YIELD = 1 << 13;
90 ASYNC_PF_INT = 1 << 14;
91 MSI_EXT_DEST_ID = 1 << 15;
92 HC_MAP_GPA_RANGE = 1 << 16;
93 MIGRATION_CONTROL = 1 << 17;
94 }
95}
96
97#[repr(C)]
98#[derive(Debug, Copy, Clone, Default)]
99pub struct KvmMsrEntry {
100 pub index: u32,
101 pub _reserved: u32,
102 pub data: u64,
103}
104
105#[repr(C)]
106#[derive(Debug, Clone)]
107pub struct KvmMsrs<const N: usize> {
108 pub nmsrs: u32,
109 pub _pad: u32,
110 pub entries: [KvmMsrEntry; N],
111}
112
113pub const MAX_IO_MSRS: usize = 256;
114
115bitflags! {
116 #[derive(Default)]
117 pub struct KvmMemFlag(u32) {
118 LOG_DIRTY_PAGES = 1 << 0;
119 READONLY = 1 << 1;
120 GUEST_MEMFD = 1 << 2;
121 }
122}
123
124#[repr(C)]
125#[derive(Debug, Copy, Clone)]
126pub struct KvmUserspaceMemoryRegion {
127 pub slot: u32,
128 pub flags: KvmMemFlag,
129 pub guest_phys_addr: u64,
130 pub memory_size: u64,
131 pub userspace_addr: u64,
132}
133
134#[repr(C)]
135#[derive(Debug, Default, Copy, Clone)]
136pub struct KvmUserspaceMemoryRegion2 {
137 pub slot: u32,
138 pub flags: KvmMemFlag,
139 pub guest_phys_addr: u64,
140 pub memory_size: u64,
141 pub userspace_addr: u64,
142 pub guest_memfd_offset: u64,
143 pub guest_memfd: u32,
144 pub _pad1: u32,
145 pub _pad2: [u64; 14],
146}
147
148bitflags! {
149 #[derive(Default)]
150 pub struct KvmMemoryAttribute(u64) {
151 PRIVATE = 1 << 3;
152 }
153}
154
155#[repr(C)]
156#[derive(Debug, Default, Copy, Clone)]
157pub struct KvmMemoryAttributes {
158 pub address: u64,
159 pub size: u64,
160 pub attributes: KvmMemoryAttribute,
161 pub flags: u64,
162}
163
164#[repr(C)]
165#[derive(Debug, Copy, Clone, Default)]
166pub struct KvmCreateGuestMemfd {
167 pub size: u64,
168 pub flags: u64,
169 pub reserved: [u64; 6],
170}
171
172#[repr(C)]
173#[derive(Debug, Default, Copy, Clone)]
174pub struct KvmRegs {
175 pub rax: u64,
176 pub rbx: u64,
177 pub rcx: u64,
178 pub rdx: u64,
179 pub rsi: u64,
180 pub rdi: u64,
181 pub rsp: u64,
182 pub rbp: u64,
183 pub r8: u64,
184 pub r9: u64,
185 pub r10: u64,
186 pub r11: u64,
187 pub r12: u64,
188 pub r13: u64,
189 pub r14: u64,
190 pub r15: u64,
191 pub rip: u64,
192 pub rflags: u64,
193}
194
195#[repr(C)]
196#[derive(Debug, Default, Copy, Clone)]
197pub struct KvmSegment {
198 pub base: u64,
199 pub limit: u32,
200 pub selector: u16,
201 pub type_: u8,
202 pub present: u8,
203 pub dpl: u8,
204 pub db: u8,
205 pub s: u8,
206 pub l: u8,
207 pub g: u8,
208 pub avl: u8,
209 pub unusable: u8,
210 pub padding: u8,
211}
212
213#[repr(C)]
214#[derive(Debug, Default, Copy, Clone)]
215pub struct KvmDtable {
216 pub base: u64,
217 pub limit: u16,
218 pub padding: [u16; 3],
219}
220
221#[repr(C)]
222#[derive(Debug, Default, Copy, Clone)]
223pub struct KvmSregs {
224 pub cs: KvmSegment,
225 pub ds: KvmSegment,
226 pub es: KvmSegment,
227 pub fs: KvmSegment,
228 pub gs: KvmSegment,
229 pub ss: KvmSegment,
230 pub tr: KvmSegment,
231 pub ldt: KvmSegment,
232 pub gdt: KvmDtable,
233 pub idt: KvmDtable,
234 pub cr0: u64,
235 pub cr2: u64,
236 pub cr3: u64,
237 pub cr4: u64,
238 pub cr8: u64,
239 pub efer: u64,
240 pub apic_base: u64,
241 pub interrupt_bitmap: [u64; 4],
242}
243
244#[repr(C)]
245#[derive(Debug, Default, Copy, Clone)]
246pub struct KvmSregs2 {
247 pub cs: KvmSegment,
248 pub ds: KvmSegment,
249 pub es: KvmSegment,
250 pub fs: KvmSegment,
251 pub gs: KvmSegment,
252 pub ss: KvmSegment,
253 pub tr: KvmSegment,
254 pub ldt: KvmSegment,
255 pub gdt: KvmDtable,
256 pub idt: KvmDtable,
257 pub cr0: u64,
258 pub cr2: u64,
259 pub cr3: u64,
260 pub cr4: u64,
261 pub cr8: u64,
262 pub efer: u64,
263 pub apic_base: u64,
264 pub flags: u64,
265 pub pdptrs: [u64; 4],
266}
267
268consts! {
269 pub struct KvmExit(u32) {
270 IO = 2;
271 HYPERCALL = 3;
272 MMIO = 6;
273 SHUTDOWN = 8;
274 SYSTEM_EVENT = 24;
275 MEMORY_FAULT = 39;
276 }
277}
278
279consts! {
280 pub struct KvmSystemEvent(u32) {
281 SHUTDOWN = 1;
282 RESET = 2;
283 }
284}
285
286#[repr(C)]
287#[derive(Debug, Clone, Copy)]
288pub struct KvmRunExitSystemEvent {
289 pub type_: KvmSystemEvent,
290 pub flags: u64,
291}
292
293bitflags! {
294 pub struct KvmMemoryFaultFlag(u64) {
295 PRIVATE = 1 << 3;
296 }
297}
298
299#[repr(C)]
300#[derive(Debug, Clone, Copy)]
301pub struct KvmRunExitMemoryFault {
302 pub flags: KvmMemoryFaultFlag,
303 pub gpa: u64,
304 pub size: u64,
305}
306
307#[repr(C)]
308#[derive(Copy, Clone)]
309pub struct KvmRun {
310 pub request_interrupt_window: u8,
311 pub immediate_exit: u8,
312 pub padding1: [u8; 6],
313 pub exit_reason: KvmExit,
314 pub ready_for_interrupt_injection: u8,
315 pub if_flag: u8,
316 pub flags: u16,
317 pub cr8: u64,
318 pub apic_base: u64,
319 pub exit: KvmRunExit,
320 pub kvm_valid_regs: u64,
321 pub kvm_dirty_regs: u64,
322 pub s: KvmSyncRegsBlock,
323}
324
325#[repr(C)]
326#[derive(Copy, Clone)]
327pub union KvmRunExit {
328 pub mmio: KvmRunExitMmio,
329 pub io: KvmRunExitIo,
330 pub hypercall: KvmRunExitHypercall,
331 pub system_event: KvmRunExitSystemEvent,
332 pub memory_fault: KvmRunExitMemoryFault,
333 pub padding: [u8; 256],
334}
335
336#[repr(C)]
337#[derive(Debug, Clone, Copy)]
338pub struct KvmRunExitMmio {
339 pub phys_addr: u64,
340 pub data: [u8; 8],
341 pub len: u32,
342 pub is_write: u8,
343}
344
345consts! {
346 pub struct KvmExitIo(u8) {
347 IN = 0;
348 OUT = 1;
349 }
350}
351
352#[repr(C)]
353#[derive(Debug, Clone, Copy)]
354pub struct KvmRunExitIo {
355 pub direction: KvmExitIo,
356 pub size: u8,
357 pub port: u16,
358 pub count: u32,
359 pub data_offset: u64,
360}
361
362consts! {
363 pub struct KvmHypercall(u64) {
364 MAP_GPA_RANGE = 12;
365 }
366}
367
368#[repr(C)]
369#[derive(Debug, Copy, Clone)]
370pub struct KvmRunExitHypercall {
371 pub nr: KvmHypercall,
372 pub args: [u64; 6],
373 pub ret: u64,
374 pub flags: u64,
375}
376
377#[repr(C)]
378#[derive(Copy, Clone)]
379pub union KvmSyncRegsBlock {
380 pub padding: [u8; 2048],
381}
382
383bitflags! {
384 #[derive(Default)]
385 pub struct KvmIrqfdFlag(u32) {
386 DEASSIGN = 1 << 0;
387 RESAMPLE = 1 << 1;
388 }
389}
390
391#[repr(C)]
392#[derive(Debug, Default, Copy, Clone)]
393pub struct KvmIrqfd {
394 pub fd: u32,
395 pub gsi: u32,
396 pub flags: KvmIrqfdFlag,
397 pub resamplefd: u32,
398 pub pad: [u8; 16usize],
399}
400
401pub const KVM_IRQ_ROUTING_IRQCHIP: u32 = 1;
402pub const KVM_IRQ_ROUTING_MSI: u32 = 2;
403
404pub const KVM_IRQCHIP_IOAPIC: u32 = 2;
405
406#[derive(Debug, Clone, Copy, Default)]
407#[repr(C)]
408pub struct KvmIrqRoutingIrqchip {
409 pub irqchip: u32,
410 pub pin: u32,
411}
412
413#[derive(Clone, Copy, Debug, Default)]
414#[repr(C)]
415pub struct KvmIrqRoutingMsi {
416 pub address_lo: u32,
417 pub address_hi: u32,
418 pub data: u32,
419 pub devid: u32,
420}
421
422#[derive(Clone, Copy)]
423#[repr(C)]
424pub union KvmIrqRoutingType {
425 pub irqchip: KvmIrqRoutingIrqchip,
426 pub msi: KvmIrqRoutingMsi,
427 pub pad: [u32; 8],
428}
429
430impl Debug for KvmIrqRoutingType {
431 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
432 f.debug_list().entries(unsafe { &self.pad }.iter()).finish()
433 }
434}
435
436impl Default for KvmIrqRoutingType {
437 fn default() -> Self {
438 KvmIrqRoutingType { pad: [0; 8] }
439 }
440}
441
442#[derive(Clone, Copy, Default)]
443#[repr(C)]
444pub struct KvmIrqRoutingEntry {
445 pub gsi: u32,
446 pub type_: u32,
447 pub flags: KvmMsiFlag,
448 pub pad: u32,
449 pub routing: KvmIrqRoutingType,
450}
451
452impl Debug for KvmIrqRoutingEntry {
453 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
454 let mut debug_struct = f.debug_struct("KvmIrqRoutingEntry");
455 debug_struct.field("gsi", &self.gsi);
456 debug_struct.field("flags", &self.flags);
457 match self.type_ {
458 KVM_IRQ_ROUTING_IRQCHIP => {
459 debug_struct.field("irqchip", unsafe { &self.routing.irqchip })
460 }
461 KVM_IRQ_ROUTING_MSI => debug_struct.field("msi", unsafe { &self.routing.msi }),
462 _ => debug_struct.field("unknown", unsafe { &self.routing.pad }),
463 };
464 debug_struct.finish()
465 }
466}
467
468#[repr(C)]
469#[derive(Clone, Copy)]
470pub struct KvmIrqRouting<const N: usize> {
471 pub nr: u32,
472 pub _flags: u32,
473 pub entries: [KvmIrqRoutingEntry; N],
474}
475
476impl<const N: usize> Debug for KvmIrqRouting<N> {
477 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
478 f.debug_list()
479 .entries(self.entries.iter().take(self.nr as usize))
480 .finish()
481 }
482}
483
484bitflags! {
485 #[derive(Default)]
486 pub struct KvmMsiFlag(u32) {
487 VALID_DEVID = 1 << 0;
488 }
489}
490
491#[repr(C)]
492#[derive(Debug, Copy, Clone, Default)]
493pub struct KvmMsi {
494 pub address_lo: u32,
495 pub address_hi: u32,
496 pub data: u32,
497 pub flags: KvmMsiFlag,
498 pub devid: u32,
499 pub pad: [u8; 12usize],
500}
501
502consts! {
503 pub struct KvmCap(u32) {
504 IRQFD = 32;
505 KVMCLOCK_CTRL = 76;
506 SIGNAL_MSI = 77;
507 ARM_PSCI_0_2 = 102;
508 SPLIT_IRQCHIP = 121;
509 X2APIC_API = 129;
510 EXIT_HYPERCALL = 201;
511 // GUEST_MEMFD = 234;
512 // VM_TYPES = 235;
513 X86_APIC_BUS_CYCLES_NS = 237;
514 }
515}
516
517bitflags! {
518 pub struct KvmX2apicApiFlag(u64) {
519 USE_32BIT_IDS = 1 << 0;
520 DISABLE_BROADCAST_QUIRK = 1 << 1;
521 }
522}
523
524bitflags! {
525 pub struct KvmMapGpaRangeFlag(u64) {
526 PAGE_2M = 1 << 0;
527 PAGE_1G = 1 << 1;
528 ENCRYPTED = 1 << 4;
529 }
530}
531
532bitflags! {
533 #[derive(Default)]
534 pub struct KvmIoEventFdFlag(u32) {
535 DATA_MATCH = 1 << 0;
536 PIO = 1 << 1;
537 DEASSIGN = 1 << 2;
538 }
539}
540
541#[repr(C)]
542#[derive(Debug, Copy, Clone, Default)]
543pub struct KvmIoEventFd {
544 pub datamatch: u64,
545 pub addr: u64,
546 pub len: u32,
547 pub fd: i32,
548 pub flags: KvmIoEventFdFlag,
549 pub pad: [u32; 9],
550}
551
552#[repr(C)]
553#[derive(Debug, Copy, Clone)]
554pub struct KvmEncRegion {
555 pub addr: u64,
556 pub size: u64,
557}
558
559#[repr(C)]
560#[derive(Debug, Clone)]
561pub struct KvmEnableCap {
562 pub cap: KvmCap,
563 pub flags: u32,
564 pub args: [u64; 4],
565 pub pad: [u8; 64],
566}
567
568#[repr(C)]
569#[derive(Debug, Copy, Clone, Default)]
570pub struct KvmOneReg {
571 pub id: u64,
572 pub addr: u64,
573}
574
575#[derive(Debug, Clone, Copy)]
576#[repr(C)]
577pub struct KvmCreateDevice {
578 pub type_: KvmDevType,
579 pub fd: i32,
580 pub flags: u32,
581}
582
583#[derive(Debug, Clone, Copy, Default)]
584#[repr(C)]
585pub struct KvmDeviceAttr {
586 pub _flags: u32,
587 pub group: u32,
588 pub attr: u64,
589 pub addr: u64,
590}
591
592consts! {
593 pub struct KvmDevType(u32) {
594 ARM_VGIC_V2 = 5;
595 ARM_VGIC_V3 = 7;
596 ARM_ITS = 8;
597 }
598}
599
600consts! {
601 pub struct KvmDevArmVgicGrp(u32) {
602 ADDR = 0;
603 DIST_REGS = 1;
604 CPU_REGS = 2;
605 NR_IRQS = 3;
606 CTL = 4;
607 REDIS_REG = 5;
608 CPU_SYSREGS = 6;
609 }
610}
611
612consts! {
613 pub struct KvmVgicAddrType(u64) {
614 DIST_V2 = 0;
615 CPU_V2 = 1;
616 DIST_V3 = 2;
617 REDIST_V3 = 3;
618 ITS = 4;
619 REDIST_REGION_V3 = 5;
620 }
621}
622
623consts! {
624 pub struct KvmDevArmVgicCtrl(u64) {
625 INIT = 0;
626 ITS_SAVE_TABLES = 1;
627 ITS_RESTORE_TABLES = 2;
628 VGIC_SAVE_PENDING_TABLES = 3;
629 ITS_RESET = 4;
630 }
631}
632
633bitfield! {
634 #[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
635 #[repr(transparent)]
636 pub struct KvmVgicV3RedistRegion(u64);
637 impl Debug;
638 pub count, set_count: 63, 52;
639 pub base, set_base: 51, 16;
640 pub index, set_index: 11, 0;
641}
642
643#[repr(C)]
644#[derive(Debug, Copy, Clone, Default)]
645pub struct KvmVcpuInit {
646 pub target: u32,
647 pub features: [u32; 7],
648}
649
650bitflags! {
651 pub struct KvmArmVcpuFeature(u32) {
652 POWER_OFF = 1 << 0;
653 EL1_32BIT = 1 << 1;
654 PSCI_0_2 = 1 << 2;
655 PMU_V3 = 1 << 3;
656 }
657}
658
659ioctl_none!(kvm_get_api_version, KVMIO, 0x00);
660ioctl_write_val!(kvm_create_vm, KVMIO, 0x01, KvmVmType);
661ioctl_write_val!(kvm_check_extension, KVMIO, 0x03, KvmCap);
662ioctl_none!(kvm_get_vcpu_mmap_size, KVMIO, 0x04);
663ioctl_writeread_buf!(kvm_get_supported_cpuid, KVMIO, 0x05, KvmCpuid2);
664
665ioctl_write_val!(kvm_create_vcpu, KVMIO, 0x41, u32);
666ioctl_write_ptr!(
667 kvm_set_user_memory_region,
668 KVMIO,
669 0x46,
670 KvmUserspaceMemoryRegion
671);
672ioctl_write_val!(kvm_set_tss_addr, KVMIO, 0x47, u64);
673ioctl_write_ptr!(kvm_set_identity_map_addr, KVMIO, 0x48, u64);
674ioctl_write_ptr!(
675 kvm_set_user_memory_region2,
676 KVMIO,
677 0x49,
678 KvmUserspaceMemoryRegion2
679);
680
681ioctl_none!(kvm_create_irqchip, KVMIO, 0x60);
682ioctl_write_buf!(kvm_set_gsi_routing, KVMIO, 0x6a, KvmIrqRouting);
683
684ioctl_write_ptr!(kvm_irqfd, KVMIO, 0x76, KvmIrqfd);
685ioctl_write_ptr!(kvm_ioeventfd, KVMIO, 0x79, KvmIoEventFd);
686
687ioctl_none!(kvm_run, KVMIO, 0x80);
688ioctl_read!(kvm_get_regs, KVMIO, 0x81, KvmRegs);
689ioctl_write_ptr!(kvm_set_regs, KVMIO, 0x82, KvmRegs);
690ioctl_read!(kvm_get_sregs, KVMIO, 0x83, KvmSregs);
691ioctl_write_ptr!(kvm_set_sregs, KVMIO, 0x84, KvmSregs);
692ioctl_write_buf!(kvm_set_msrs, KVMIO, 0x89, KvmMsrs);
693
694ioctl_write_buf!(kvm_set_cpuid2, KVMIO, 0x90, KvmCpuid2);
695
696ioctl_write_ptr!(kvm_enable_cap, KVMIO, 0xa3, KvmEnableCap);
697ioctl_write_ptr!(kvm_signal_msi, KVMIO, 0xa5, KvmMsi);
698
699ioctl_write_ptr!(kvm_get_one_reg, KVMIO, 0xab, KvmOneReg);
700ioctl_write_ptr!(kvm_set_one_reg, KVMIO, 0xac, KvmOneReg);
701
702ioctl_none!(kvm_kvmclock_ctrl, KVMIO, 0xad);
703
704ioctl_write_ptr!(kvm_arm_vcpu_init, KVMIO, 0xae, KvmVcpuInit);
705ioctl_read!(kvm_arm_preferred_target, KVMIO, 0xaf, KvmVcpuInit);
706
707ioctl_writeread!(kvm_memory_encrypt_op, ioctl_iowr::<u64>(KVMIO, 0xba));
708
709ioctl_write_ptr!(
710 kvm_memory_encrypt_reg_region,
711 ioctl_ior::<KvmEncRegion>(KVMIO, 0xbb),
712 KvmEncRegion
713);
714
715ioctl_write_ptr!(
716 kvm_memory_encrypt_unreg_region,
717 ioctl_ior::<KvmEncRegion>(KVMIO, 0xbc),
718 KvmEncRegion
719);
720
721ioctl_read!(kvm_get_sregs2, KVMIO, 0xcc, KvmSregs2);
722ioctl_write_ptr!(kvm_set_sregs2, KVMIO, 0xcd, KvmSregs2);
723
724ioctl_write_ptr!(kvm_set_memory_attributes, KVMIO, 0xd2, KvmMemoryAttributes);
725
726ioctl_writeread!(kvm_create_guest_memfd, KVMIO, 0xd4, KvmCreateGuestMemfd);
727
728ioctl_writeread!(kvm_create_device, KVMIO, 0xe0, KvmCreateDevice);
729ioctl_write_ptr!(kvm_set_device_attr, KVMIO, 0xe1, KvmDeviceAttr);
730ioctl_write_ptr!(kvm_get_device_attr, KVMIO, 0xe2, KvmDeviceAttr);
731