kvm.rs0.00%
1
// Copyright 2024 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::fmt::{Debug, Formatter, Result};16
17
use bitfield::bitfield;18
19
use crate::sys::ioctl::{ioctl_ior, ioctl_iowr};20
use 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
25
pub const KVMIO: u8 = 0xAE;26
pub const KVM_API_VERSION: i32 = 12;27
28
#[cfg(target_arch = "x86_64")]29
consts! {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")]40
pub struct KvmVmType(#[allow(dead_code)] pub u64);41
42
pub const KVM_MAX_CPUID_ENTRIES: usize = 256;43
44
bitflags! {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)]53
pub 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)]66
pub struct KvmCpuid2<const N: usize> {67
pub nent: u32,68
pub padding: u32,69
pub entries: [KvmCpuidEntry2; N],70
}71
72
pub const KVM_CPUID_SIGNATURE: u32 = 0x4000_0000;73
pub const KVM_CPUID_FEATURES: u32 = 0x4000_0001;74
75
bitflags! {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)]99
pub struct KvmMsrEntry {100
pub index: u32,101
pub _reserved: u32,102
pub data: u64,103
}104
105
#[repr(C)]106
#[derive(Debug, Clone)]107
pub struct KvmMsrs<const N: usize> {108
pub nmsrs: u32,109
pub _pad: u32,110
pub entries: [KvmMsrEntry; N],111
}112
113
pub const MAX_IO_MSRS: usize = 256;114
115
bitflags! {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)]126
pub 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)]136
pub 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
148
bitflags! {149
#[derive(Default)]150
pub struct KvmMemoryAttribute(u64) {151
PRIVATE = 1 << 3;152
}153
}154
155
#[repr(C)]156
#[derive(Debug, Default, Copy, Clone)]157
pub 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)]166
pub 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)]174
pub 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)]197
pub 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)]215
pub 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)]223
pub 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)]246
pub 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
268
consts! {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
279
consts! {280
pub struct KvmSystemEvent(u32) {281
SHUTDOWN = 1;282
RESET = 2;283
}284
}285
286
#[repr(C)]287
#[derive(Debug, Clone, Copy)]288
pub struct KvmRunExitSystemEvent {289
pub type_: KvmSystemEvent,290
pub flags: u64,291
}292
293
bitflags! {294
pub struct KvmMemoryFaultFlag(u64) {295
PRIVATE = 1 << 3;296
}297
}298
299
#[repr(C)]300
#[derive(Debug, Clone, Copy)]301
pub struct KvmRunExitMemoryFault {302
pub flags: KvmMemoryFaultFlag,303
pub gpa: u64,304
pub size: u64,305
}306
307
#[repr(C)]308
#[derive(Copy, Clone)]309
pub 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)]327
pub 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)]338
pub struct KvmRunExitMmio {339
pub phys_addr: u64,340
pub data: [u8; 8],341
pub len: u32,342
pub is_write: u8,343
}344
345
consts! {346
pub struct KvmExitIo(u8) {347
IN = 0;348
OUT = 1;349
}350
}351
352
#[repr(C)]353
#[derive(Debug, Clone, Copy)]354
pub 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
362
consts! {363
pub struct KvmHypercall(u64) {364
MAP_GPA_RANGE = 12;365
}366
}367
368
#[repr(C)]369
#[derive(Debug, Copy, Clone)]370
pub 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)]379
pub union KvmSyncRegsBlock {380
pub padding: [u8; 2048],381
}382
383
bitflags! {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)]393
pub 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
401
pub const KVM_IRQ_ROUTING_IRQCHIP: u32 = 1;402
pub const KVM_IRQ_ROUTING_MSI: u32 = 2;403
404
pub const KVM_IRQCHIP_IOAPIC: u32 = 2;405
406
#[derive(Debug, Clone, Copy, Default)]407
#[repr(C)]408
pub struct KvmIrqRoutingIrqchip {409
pub irqchip: u32,410
pub pin: u32,411
}412
413
#[derive(Clone, Copy, Debug, Default)]414
#[repr(C)]415
pub 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)]424
pub union KvmIrqRoutingType {425
pub irqchip: KvmIrqRoutingIrqchip,426
pub msi: KvmIrqRoutingMsi,427
pub pad: [u32; 8],428
}429
430
impl Debug for KvmIrqRoutingType {431
fn fmt(&self, f: &mut Formatter<'_>) -> Result {432
f.debug_list().entries(unsafe { &self.pad }.iter()).finish()433
}434
}435
436
impl Default for KvmIrqRoutingType {437
fn default() -> Self {438
KvmIrqRoutingType { pad: [0; 8] }439
}440
}441
442
#[derive(Clone, Copy, Default)]443
#[repr(C)]444
pub struct KvmIrqRoutingEntry {445
pub gsi: u32,446
pub type_: u32,447
pub flags: KvmMsiFlag,448
pub pad: u32,449
pub routing: KvmIrqRoutingType,450
}451
452
impl 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)]470
pub struct KvmIrqRouting<const N: usize> {471
pub nr: u32,472
pub _flags: u32,473
pub entries: [KvmIrqRoutingEntry; N],474
}475
476
impl<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
484
bitflags! {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)]493
pub 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
502
consts! {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
517
bitflags! {518
pub struct KvmX2apicApiFlag(u64) {519
USE_32BIT_IDS = 1 << 0;520
DISABLE_BROADCAST_QUIRK = 1 << 1;521
}522
}523
524
bitflags! {525
pub struct KvmMapGpaRangeFlag(u64) {526
PAGE_2M = 1 << 0;527
PAGE_1G = 1 << 1;528
ENCRYPTED = 1 << 4;529
}530
}531
532
bitflags! {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)]543
pub 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)]554
pub struct KvmEncRegion {555
pub addr: u64,556
pub size: u64,557
}558
559
#[repr(C)]560
#[derive(Debug, Clone)]561
pub 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)]570
pub struct KvmOneReg {571
pub id: u64,572
pub addr: u64,573
}574
575
#[derive(Debug, Clone, Copy)]576
#[repr(C)]577
pub 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)]585
pub struct KvmDeviceAttr {586
pub _flags: u32,587
pub group: u32,588
pub attr: u64,589
pub addr: u64,590
}591
592
consts! {593
pub struct KvmDevType(u32) {594
ARM_VGIC_V2 = 5;595
ARM_VGIC_V3 = 7;596
ARM_ITS = 8;597
}598
}599
600
consts! {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
612
consts! {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
623
consts! {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
633
bitfield! {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)]645
pub struct KvmVcpuInit {646
pub target: u32,647
pub features: [u32; 7],648
}649
650
bitflags! {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
659
ioctl_none!(kvm_get_api_version, KVMIO, 0x00);660
ioctl_write_val!(kvm_create_vm, KVMIO, 0x01, KvmVmType);661
ioctl_write_val!(kvm_check_extension, KVMIO, 0x03, KvmCap);662
ioctl_none!(kvm_get_vcpu_mmap_size, KVMIO, 0x04);663
ioctl_writeread_buf!(kvm_get_supported_cpuid, KVMIO, 0x05, KvmCpuid2);664
665
ioctl_write_val!(kvm_create_vcpu, KVMIO, 0x41, u32);666
ioctl_write_ptr!(667
kvm_set_user_memory_region,668
KVMIO,669
0x46,670
KvmUserspaceMemoryRegion671
);672
ioctl_write_val!(kvm_set_tss_addr, KVMIO, 0x47, u64);673
ioctl_write_ptr!(kvm_set_identity_map_addr, KVMIO, 0x48, u64);674
ioctl_write_ptr!(675
kvm_set_user_memory_region2,676
KVMIO,677
0x49,678
KvmUserspaceMemoryRegion2679
);680
681
ioctl_none!(kvm_create_irqchip, KVMIO, 0x60);682
ioctl_write_buf!(kvm_set_gsi_routing, KVMIO, 0x6a, KvmIrqRouting);683
684
ioctl_write_ptr!(kvm_irqfd, KVMIO, 0x76, KvmIrqfd);685
ioctl_write_ptr!(kvm_ioeventfd, KVMIO, 0x79, KvmIoEventFd);686
687
ioctl_none!(kvm_run, KVMIO, 0x80);688
ioctl_read!(kvm_get_regs, KVMIO, 0x81, KvmRegs);689
ioctl_write_ptr!(kvm_set_regs, KVMIO, 0x82, KvmRegs);690
ioctl_read!(kvm_get_sregs, KVMIO, 0x83, KvmSregs);691
ioctl_write_ptr!(kvm_set_sregs, KVMIO, 0x84, KvmSregs);692
ioctl_write_buf!(kvm_set_msrs, KVMIO, 0x89, KvmMsrs);693
694
ioctl_write_buf!(kvm_set_cpuid2, KVMIO, 0x90, KvmCpuid2);695
696
ioctl_write_ptr!(kvm_enable_cap, KVMIO, 0xa3, KvmEnableCap);697
ioctl_write_ptr!(kvm_signal_msi, KVMIO, 0xa5, KvmMsi);698
699
ioctl_write_ptr!(kvm_get_one_reg, KVMIO, 0xab, KvmOneReg);700
ioctl_write_ptr!(kvm_set_one_reg, KVMIO, 0xac, KvmOneReg);701
702
ioctl_none!(kvm_kvmclock_ctrl, KVMIO, 0xad);703
704
ioctl_write_ptr!(kvm_arm_vcpu_init, KVMIO, 0xae, KvmVcpuInit);705
ioctl_read!(kvm_arm_preferred_target, KVMIO, 0xaf, KvmVcpuInit);706
707
ioctl_writeread!(kvm_memory_encrypt_op, ioctl_iowr::<u64>(KVMIO, 0xba));708
709
ioctl_write_ptr!(710
kvm_memory_encrypt_reg_region,711
ioctl_ior::<KvmEncRegion>(KVMIO, 0xbb),712
KvmEncRegion713
);714
715
ioctl_write_ptr!(716
kvm_memory_encrypt_unreg_region,717
ioctl_ior::<KvmEncRegion>(KVMIO, 0xbc),718
KvmEncRegion719
);720
721
ioctl_read!(kvm_get_sregs2, KVMIO, 0xcc, KvmSregs2);722
ioctl_write_ptr!(kvm_set_sregs2, KVMIO, 0xcd, KvmSregs2);723
724
ioctl_write_ptr!(kvm_set_memory_attributes, KVMIO, 0xd2, KvmMemoryAttributes);725
726
ioctl_writeread!(kvm_create_guest_memfd, KVMIO, 0xd4, KvmCreateGuestMemfd);727
728
ioctl_writeread!(kvm_create_device, KVMIO, 0xe0, KvmCreateDevice);729
ioctl_write_ptr!(kvm_set_device_attr, KVMIO, 0xe1, KvmDeviceAttr);730
ioctl_write_ptr!(kvm_get_device_attr, KVMIO, 0xe2, KvmDeviceAttr);731