@@ -13,7 +13,10 @@ use std::os::unix::io::{AsRawFd, RawFd};
13
13
use crate :: ioctls:: { KvmRunWrapper , Result } ;
14
14
use crate :: kvm_ioctls:: * ;
15
15
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
16
- use kvm_bindings:: { CpuId , Msrs , KVM_MAX_CPUID_ENTRIES } ;
16
+ use kvm_bindings:: {
17
+ CpuId , Msrs , KVM_MAX_CPUID_ENTRIES , KVM_MSR_EXIT_REASON_FILTER , KVM_MSR_EXIT_REASON_INVAL ,
18
+ KVM_MSR_EXIT_REASON_UNKNOWN ,
19
+ } ;
17
20
use vmm_sys_util:: errno;
18
21
use vmm_sys_util:: ioctl:: { ioctl, ioctl_with_mut_ref, ioctl_with_ref} ;
19
22
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
@@ -25,6 +28,55 @@ pub fn reg_size(reg_id: u64) -> usize {
25
28
2_usize . pow ( ( ( reg_id & KVM_REG_SIZE_MASK ) >> KVM_REG_SIZE_SHIFT ) as u32 )
26
29
}
27
30
31
+ /// Information about a [`VcpuExit`] triggered by an MSR read (`KVM_EXIT_X86_RDMSR`).
32
+ #[ derive( Debug ) ]
33
+ pub struct ReadMsrExit < ' a > {
34
+ /// Must be set to 1 by the the user if the read access should fail. This
35
+ /// will inject a #GP fault into the guest when the VCPU is executed
36
+ /// again.
37
+ pub error : & ' a mut u8 ,
38
+ /// The reason for this exit.
39
+ pub reason : MsrExitReason ,
40
+ /// The MSR the guest wants to read.
41
+ pub index : u32 ,
42
+ /// The data to be supplied by the user as the MSR Contents to the guest.
43
+ pub data : & ' a mut u64 ,
44
+ }
45
+
46
+ /// Information about a [`VcpuExit`] triggered by an MSR write (`KVM_EXIT_X86_WRMSR`).
47
+ #[ derive( Debug ) ]
48
+ pub struct WriteMsrExit < ' a > {
49
+ /// Must be set to 1 by the the user if the write access should fail. This
50
+ /// will inject a #GP fault into the guest when the VCPU is executed
51
+ /// again.
52
+ pub error : & ' a mut u8 ,
53
+ /// The reason for this exit.
54
+ pub reason : MsrExitReason ,
55
+ /// The MSR the guest wants to write.
56
+ pub index : u32 ,
57
+ /// The data the guest wants to write into the MSR.
58
+ pub data : u64 ,
59
+ }
60
+
61
+ bitflags:: bitflags! {
62
+ /// The reason for a [`VcpuExit::X86Rdmsr`] or[`VcpuExit::X86Wrmsr`]. This
63
+ /// is also used when enabling
64
+ /// [`Cap::X86UserSpaceMsr`](crate::Cap::X86UserSpaceMsr) to specify which
65
+ /// reasons should be forwarded to the user via those exits.
66
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
67
+ pub struct MsrExitReason : u32 {
68
+ /// Corresponds to [`KVM_MSR_EXIT_REASON_UNKNOWN`]. The exit was
69
+ /// triggered by an access to an MSR that is unknown to KVM.
70
+ const Unknown = KVM_MSR_EXIT_REASON_UNKNOWN ;
71
+ /// Corresponds to [`KVM_MSR_EXIT_REASON_INVAL`]. The exit was
72
+ /// triggered by an access to an invalid MSR or to reserved bits.
73
+ const Inval = KVM_MSR_EXIT_REASON_INVAL ;
74
+ /// Corresponds to [`KVM_MSR_EXIT_REASON_FILTER`]. The exit was
75
+ /// triggered by an access to a filtered MSR.
76
+ const Filter = KVM_MSR_EXIT_REASON_FILTER ;
77
+ }
78
+ }
79
+
28
80
/// Reasons for vCPU exits.
29
81
///
30
82
/// The exit reasons are mapped to the `KVM_EXIT_*` defines in the
@@ -102,6 +154,10 @@ pub enum VcpuExit<'a> {
102
154
IoapicEoi ( u8 /* vector */ ) ,
103
155
/// Corresponds to KVM_EXIT_HYPERV.
104
156
Hyperv ,
157
+ /// Corresponds to KVM_EXIT_X86_RDMSR.
158
+ X86Rdmsr ( ReadMsrExit < ' a > ) ,
159
+ /// Corresponds to KVM_EXIT_X86_WRMSR.
160
+ X86Wrmsr ( WriteMsrExit < ' a > ) ,
105
161
/// Corresponds to an exit reason that is unknown from the current version
106
162
/// of the kvm-ioctls crate. Let the consumer decide about what to do with
107
163
/// it.
@@ -1422,6 +1478,30 @@ impl VcpuFd {
1422
1478
Ok ( VcpuExit :: MmioRead ( addr, data_slice) )
1423
1479
}
1424
1480
}
1481
+ KVM_EXIT_X86_RDMSR => {
1482
+ // SAFETY: Safe because the exit_reason (which comes from the kernel) told us
1483
+ // which union field to use.
1484
+ let msr = unsafe { & mut run. __bindgen_anon_1 . msr } ;
1485
+ let exit = ReadMsrExit {
1486
+ error : & mut msr. error ,
1487
+ reason : MsrExitReason :: from_bits_truncate ( msr. reason ) ,
1488
+ index : msr. index ,
1489
+ data : & mut msr. data ,
1490
+ } ;
1491
+ Ok ( VcpuExit :: X86Rdmsr ( exit) )
1492
+ }
1493
+ KVM_EXIT_X86_WRMSR => {
1494
+ // SAFETY: Safe because the exit_reason (which comes from the kernel) told us
1495
+ // which union field to use.
1496
+ let msr = unsafe { & mut run. __bindgen_anon_1 . msr } ;
1497
+ let exit = WriteMsrExit {
1498
+ error : & mut msr. error ,
1499
+ reason : MsrExitReason :: from_bits_truncate ( msr. reason ) ,
1500
+ index : msr. index ,
1501
+ data : msr. data ,
1502
+ } ;
1503
+ Ok ( VcpuExit :: X86Wrmsr ( exit) )
1504
+ }
1425
1505
KVM_EXIT_IRQ_WINDOW_OPEN => Ok ( VcpuExit :: IrqWindowOpen ) ,
1426
1506
KVM_EXIT_SHUTDOWN => Ok ( VcpuExit :: Shutdown ) ,
1427
1507
KVM_EXIT_FAIL_ENTRY => {
0 commit comments