@@ -13,6 +13,12 @@ use std::io;
13
13
14
14
use std:: os:: unix:: io:: RawFd ;
15
15
16
+ #[ cfg( feature = "tee" ) ]
17
+ use kvm_ioctls:: VcpuExit :: Unsupported ;
18
+
19
+ use std:: sync:: Arc ;
20
+ use std:: sync:: Mutex ;
21
+
16
22
use std:: result;
17
23
use std:: sync:: atomic:: { fence, Ordering } ;
18
24
#[ cfg( not( test) ) ]
@@ -39,18 +45,18 @@ use kvm_bindings::{
39
45
KVM_CLOCK_TSC_STABLE , KVM_IRQCHIP_IOAPIC , KVM_IRQCHIP_PIC_MASTER , KVM_IRQCHIP_PIC_SLAVE ,
40
46
KVM_MAX_CPUID_ENTRIES ,
41
47
} ;
42
- use kvm_bindings:: {
43
- kvm_userspace_memory_region, KVM_API_VERSION , KVM_SYSTEM_EVENT_RESET , KVM_SYSTEM_EVENT_SHUTDOWN ,
44
- } ;
45
48
#[ cfg( feature = "tee" ) ]
46
49
use kvm_bindings:: {
47
- kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region ,
48
- kvm_userspace_memory_region2 , KVM_API_VERSION , KVM_MEMORY_ATTRIBUTE_PRIVATE ,
50
+ kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2 , KVM_API_VERSION ,
51
+ KVM_EXIT_MEMORY_FAULT , KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEMORY_EXIT_FLAG_PRIVATE ,
49
52
KVM_MEM_GUEST_MEMFD ,
50
53
} ;
51
- #[ cfg( feature = "tee" ) ]
52
- use kvm_bindings:: { kvm_enable_cap, KVM_CAP_EXIT_HYPERCALL } ;
53
- use kvm_ioctls:: { Cap :: * , * } ;
54
+ #[ cfg( not( feature = "tee" ) ) ]
55
+ use kvm_bindings:: { kvm_userspace_memory_region, KVM_API_VERSION } ;
56
+ use kvm_bindings:: {
57
+ kvm_userspace_memory_region, KVM_API_VERSION , KVM_SYSTEM_EVENT_RESET , KVM_SYSTEM_EVENT_SHUTDOWN ,
58
+ } ;
59
+ use kvm_ioctls:: * ;
54
60
use utils:: eventfd:: EventFd ;
55
61
use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
56
62
use utils:: sm:: StateMachine ;
@@ -768,6 +774,13 @@ pub struct VcpuConfig {
768
774
pub cpu_template : Option < CpuFeaturesTemplate > ,
769
775
}
770
776
777
+ #[ cfg( feature = "tee" ) ]
778
+ pub struct MemProperties {
779
+ pub addr : u64 ,
780
+ pub size : u64 ,
781
+ pub attributes : u32 ,
782
+ }
783
+
771
784
// Using this for easier explicit type-casting to help IDEs interpret the code.
772
785
type VcpuCell = Cell < Option < * mut Vcpu > > ;
773
786
@@ -790,6 +803,10 @@ pub struct Vcpu {
790
803
#[ cfg( target_arch = "aarch64" ) ]
791
804
mpidr : u64 ,
792
805
806
+ // The transmitting end of the events channel which will be given to the vcpu side
807
+ #[ cfg( feature = "tee" ) ]
808
+ sender_io : Sender < MemProperties > ,
809
+
793
810
// The receiving end of events channel owned by the vcpu side.
794
811
event_receiver : Receiver < VcpuEvent > ,
795
812
// The transmitting end of the events channel which will be given to the handler.
@@ -937,7 +954,12 @@ impl Vcpu {
937
954
/// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits.
938
955
/// * `create_ts` - A timestamp used by the vcpu to calculate its lifetime.
939
956
#[ cfg( target_arch = "aarch64" ) ]
940
- pub fn new_aarch64 ( id : u8 , vm_fd : & VmFd , exit_evt : EventFd ) -> Result < Self > {
957
+ pub fn new_aarch64 (
958
+ id : u8 ,
959
+ vm_fd : & VmFd ,
960
+ exit_evt : EventFd ,
961
+ #[ cfg( feature = "tee" ) ] sender_io : Sender < MemProperties > ,
962
+ ) -> Result < Self > {
941
963
let kvm_vcpu = vm_fd. create_vcpu ( id as u64 ) . map_err ( Error :: VcpuFd ) ?;
942
964
let ( event_sender, event_receiver) = unbounded ( ) ;
943
965
let ( response_sender, response_receiver) = unbounded ( ) ;
@@ -952,6 +974,8 @@ impl Vcpu {
952
974
event_sender : Some ( event_sender) ,
953
975
response_receiver : Some ( response_receiver) ,
954
976
response_sender,
977
+ #[ cfg( feature = "tee" ) ]
978
+ sender_io,
955
979
} )
956
980
}
957
981
@@ -1260,6 +1284,38 @@ impl Vcpu {
1260
1284
info ! ( "Received KVM_EXIT_SHUTDOWN signal" ) ;
1261
1285
Ok ( VcpuEmulation :: Stopped )
1262
1286
}
1287
+ #[ cfg( feature = "tee" ) ]
1288
+ VcpuExit :: MemoryFault { flags, gpa, size } => {
1289
+ if flags & !KVM_MEMORY_EXIT_FLAG_PRIVATE as u64 != 0 {
1290
+ error ! ( "KVM_EXIT_MEMORY_FAULT: Unknown flag {}" , flags) ;
1291
+ Err ( Error :: VcpuUnhandledKvmExit )
1292
+ } else {
1293
+ // from private to shared
1294
+ let mut attr = 0 ;
1295
+ // from shared to private
1296
+ if flags & KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1297
+ == KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1298
+ {
1299
+ attr = KVM_MEMORY_ATTRIBUTE_PRIVATE ;
1300
+ } ;
1301
+
1302
+ let _ = self . sender_io . try_send ( MemProperties {
1303
+ addr : gpa,
1304
+ size,
1305
+ attributes : attr,
1306
+ } ) ;
1307
+ Ok ( VcpuEmulation :: Handled )
1308
+ }
1309
+ }
1310
+ // Documentation specifices that when KVM exists with KVM_EXIT_MEMORY_FAULT,
1311
+ // userspace should assume kvm_run.exit_reason is stale/undefined for error numbers
1312
+ // different than EFAULT or EHWPOISON
1313
+ #[ cfg( feature = "tee" ) ]
1314
+ Unsupported ( KVM_EXIT_MEMORY_FAULT ) => Ok ( VcpuEmulation :: Handled ) ,
1315
+ VcpuExit :: InternalError => {
1316
+ error ! ( "Received KVM_EXIT_INTERNAL_ERROR signal" ) ;
1317
+ Err ( Error :: VcpuUnhandledKvmExit )
1318
+ }
1263
1319
// Documentation specifies that below kvm exits are considered
1264
1320
// errors.
1265
1321
VcpuExit :: FailEntry ( reason, vcpu) => {
0 commit comments