@@ -14,6 +14,9 @@ use std::io;
14
14
#[ cfg( feature = "tee" ) ]
15
15
use std:: os:: unix:: io:: RawFd ;
16
16
17
+ #[ cfg( feature = "tee" ) ]
18
+ use kvm_ioctls:: VcpuExit :: Unsupported ;
19
+
17
20
use std:: sync:: Arc ;
18
21
use std:: sync:: Mutex ;
19
22
@@ -51,7 +54,7 @@ use kvm_bindings::{
51
54
#[ cfg( feature = "tee" ) ]
52
55
use kvm_bindings:: {
53
56
kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, KVM_API_VERSION ,
54
- KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEM_GUEST_MEMFD ,
57
+ KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEMORY_EXIT_FLAG_PRIVATE , KVM_MEM_GUEST_MEMFD , KVM_EXIT_MEMORY_FAULT
55
58
} ;
56
59
#[ cfg( not( feature = "tee" ) ) ]
57
60
use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
@@ -835,6 +838,13 @@ pub struct VcpuConfig {
835
838
pub cpu_template : Option < CpuFeaturesTemplate > ,
836
839
}
837
840
841
+ #[ cfg( feature = "tee" ) ]
842
+ pub struct MemProperties {
843
+ pub addr : u64 ,
844
+ pub size : u64 ,
845
+ pub attributes : u32 ,
846
+ }
847
+
838
848
// Using this for easier explicit type-casting to help IDEs interpret the code.
839
849
type VcpuCell = Cell < Option < * mut Vcpu > > ;
840
850
@@ -857,6 +867,10 @@ pub struct Vcpu {
857
867
#[ cfg( target_arch = "aarch64" ) ]
858
868
mpidr : u64 ,
859
869
870
+ // The transmitting end of the events channel which will be given to the vcpu side
871
+ #[ cfg( feature = "tee" ) ]
872
+ sender_io : Sender < MemProperties > ,
873
+
860
874
// The receiving end of events channel owned by the vcpu side.
861
875
event_receiver : Receiver < VcpuEvent > ,
862
876
// The transmitting end of the events channel which will be given to the handler.
@@ -998,7 +1012,12 @@ impl Vcpu {
998
1012
/// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits.
999
1013
/// * `create_ts` - A timestamp used by the vcpu to calculate its lifetime.
1000
1014
#[ cfg( target_arch = "aarch64" ) ]
1001
- pub fn new_aarch64 ( id : u8 , vm_fd : & VmFd , exit_evt : EventFd ) -> Result < Self > {
1015
+ pub fn new_aarch64 (
1016
+ id : u8 ,
1017
+ vm_fd : & VmFd ,
1018
+ exit_evt : EventFd ,
1019
+ #[ cfg( feature = "tee" ) ] sender_io : Sender < MemProperties > ,
1020
+ ) -> Result < Self > {
1002
1021
let kvm_vcpu = vm_fd. create_vcpu ( id as u64 ) . map_err ( Error :: VcpuFd ) ?;
1003
1022
let ( event_sender, event_receiver) = unbounded ( ) ;
1004
1023
let ( response_sender, response_receiver) = unbounded ( ) ;
@@ -1013,6 +1032,8 @@ impl Vcpu {
1013
1032
event_sender : Some ( event_sender) ,
1014
1033
response_receiver : Some ( response_receiver) ,
1015
1034
response_sender,
1035
+ #[ cfg( feature = "tee" ) ]
1036
+ sender_io,
1016
1037
} )
1017
1038
}
1018
1039
@@ -1299,16 +1320,44 @@ impl Vcpu {
1299
1320
info ! ( "Received KVM_EXIT_SHUTDOWN signal" ) ;
1300
1321
Ok ( VcpuEmulation :: Stopped )
1301
1322
}
1323
+ #[ cfg( feature = "tee" ) ]
1324
+ VcpuExit :: MemoryFault { flags, gpa, size } => {
1325
+ if flags & !KVM_MEMORY_EXIT_FLAG_PRIVATE as u64 != 0 {
1326
+ error ! ( "KVM_EXIT_MEMORY_FAULT: Unknown flag {}" , flags) ;
1327
+ Err ( Error :: VcpuUnhandledKvmExit )
1328
+ } else {
1329
+ // from private to shared
1330
+ let mut attr = 0 ;
1331
+ // from shared to private
1332
+ if flags & KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1333
+ == KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1334
+ {
1335
+ attr = KVM_MEMORY_ATTRIBUTE_PRIVATE ;
1336
+ } ;
1337
+
1338
+ let _ = self . sender_io . try_send ( MemProperties {
1339
+ addr : gpa,
1340
+ size,
1341
+ attributes : attr,
1342
+ } ) ;
1343
+ Ok ( VcpuEmulation :: Handled )
1344
+ }
1345
+ }
1346
+ // Documentation specifices that when KVM exists with KVM_EXIT_MEMORY_FAULT,
1347
+ // userspace should assume kvm_run.exit_reason is stale/undefined for error numbers
1348
+ // different than EFAULT or EHWPOISON
1349
+ #[ cfg( feature = "tee" ) ]
1350
+ Unsupported ( KVM_EXIT_MEMORY_FAULT ) => Ok ( VcpuEmulation :: Handled ) ,
1351
+ VcpuExit :: InternalError => {
1352
+ error ! ( "Received KVM_EXIT_INTERNAL_ERROR signal" ) ;
1353
+ Err ( Error :: VcpuUnhandledKvmExit )
1354
+ }
1302
1355
// Documentation specifies that below kvm exits are considered
1303
1356
// errors.
1304
1357
VcpuExit :: FailEntry ( reason, vcpu) => {
1305
1358
error ! ( "Received KVM_EXIT_FAIL_ENTRY signal: reason={reason}, vcpu={vcpu}" ) ;
1306
1359
Err ( Error :: VcpuUnhandledKvmExit )
1307
1360
}
1308
- VcpuExit :: InternalError => {
1309
- error ! ( "Received KVM_EXIT_INTERNAL_ERROR signal" ) ;
1310
- Err ( Error :: VcpuUnhandledKvmExit )
1311
- }
1312
1361
r => {
1313
1362
// TODO: Are we sure we want to finish running a vcpu upon
1314
1363
// receiving a vm exit that is not necessarily an error?
0 commit comments