@@ -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,14 +45,14 @@ 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
} ;
48
+ #[ cfg( feature = "tee" ) ]
42
49
use kvm_bindings:: {
43
- kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region,
44
- kvm_userspace_memory_region2, KVM_API_VERSION , KVM_MEMORY_ATTRIBUTE_PRIVATE ,
45
- KVM_MEM_GUEST_MEMFD ,
50
+ kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2, KVM_API_VERSION ,
51
+ KVM_MEMORY_ATTRIBUTE_PRIVATE , KVM_MEMORY_EXIT_FLAG_PRIVATE , KVM_MEM_GUEST_MEMFD , KVM_EXIT_MEMORY_FAULT
46
52
} ;
47
- #[ cfg( feature = "tee" ) ]
48
- use kvm_bindings:: { kvm_enable_cap , KVM_CAP_EXIT_HYPERCALL } ;
49
- use kvm_ioctls:: { Cap :: * , * } ;
53
+ #[ cfg( not ( feature = "tee" ) ) ]
54
+ use kvm_bindings:: { kvm_userspace_memory_region , KVM_API_VERSION } ;
55
+ use kvm_ioctls:: * ;
50
56
use utils:: eventfd:: EventFd ;
51
57
use utils:: signal:: { register_signal_handler, sigrtmin, Killable } ;
52
58
use utils:: sm:: StateMachine ;
@@ -771,6 +777,13 @@ pub struct VcpuConfig {
771
777
pub cpu_template : Option < CpuFeaturesTemplate > ,
772
778
}
773
779
780
+ #[ cfg( feature = "tee" ) ]
781
+ pub struct MemProperties {
782
+ pub addr : u64 ,
783
+ pub size : u64 ,
784
+ pub attributes : u32 ,
785
+ }
786
+
774
787
// Using this for easier explicit type-casting to help IDEs interpret the code.
775
788
type VcpuCell = Cell < Option < * mut Vcpu > > ;
776
789
@@ -793,6 +806,10 @@ pub struct Vcpu {
793
806
#[ cfg( target_arch = "aarch64" ) ]
794
807
mpidr : u64 ,
795
808
809
+ // The transmitting end of the events channel which will be given to the vcpu side
810
+ #[ cfg( feature = "tee" ) ]
811
+ sender_io : Sender < MemProperties > ,
812
+
796
813
// The receiving end of events channel owned by the vcpu side.
797
814
event_receiver : Receiver < VcpuEvent > ,
798
815
// The transmitting end of the events channel which will be given to the handler.
@@ -940,7 +957,12 @@ impl Vcpu {
940
957
/// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits.
941
958
/// * `create_ts` - A timestamp used by the vcpu to calculate its lifetime.
942
959
#[ cfg( target_arch = "aarch64" ) ]
943
- pub fn new_aarch64 ( id : u8 , vm_fd : & VmFd , exit_evt : EventFd ) -> Result < Self > {
960
+ pub fn new_aarch64 (
961
+ id : u8 ,
962
+ vm_fd : & VmFd ,
963
+ exit_evt : EventFd ,
964
+ #[ cfg( feature = "tee" ) ] sender_io : Sender < MemProperties > ,
965
+ ) -> Result < Self > {
944
966
let kvm_vcpu = vm_fd. create_vcpu ( id as u64 ) . map_err ( Error :: VcpuFd ) ?;
945
967
let ( event_sender, event_receiver) = unbounded ( ) ;
946
968
let ( response_sender, response_receiver) = unbounded ( ) ;
@@ -955,6 +977,8 @@ impl Vcpu {
955
977
event_sender : Some ( event_sender) ,
956
978
response_receiver : Some ( response_receiver) ,
957
979
response_sender,
980
+ #[ cfg( feature = "tee" ) ]
981
+ sender_io,
958
982
} )
959
983
}
960
984
@@ -1266,16 +1290,44 @@ impl Vcpu {
1266
1290
info ! ( "Received KVM_EXIT_SHUTDOWN signal" ) ;
1267
1291
Ok ( VcpuEmulation :: Stopped )
1268
1292
}
1293
+ #[ cfg( feature = "tee" ) ]
1294
+ VcpuExit :: MemoryFault { flags, gpa, size } => {
1295
+ if flags & !KVM_MEMORY_EXIT_FLAG_PRIVATE as u64 != 0 {
1296
+ error ! ( "KVM_EXIT_MEMORY_FAULT: Unknown flag {}" , flags) ;
1297
+ Err ( Error :: VcpuUnhandledKvmExit )
1298
+ } else {
1299
+ // from private to shared
1300
+ let mut attr = 0 ;
1301
+ // from shared to private
1302
+ if flags & KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1303
+ == KVM_MEMORY_EXIT_FLAG_PRIVATE as u64
1304
+ {
1305
+ attr = KVM_MEMORY_ATTRIBUTE_PRIVATE ;
1306
+ } ;
1307
+
1308
+ let _ = self . sender_io . try_send ( MemProperties {
1309
+ addr : gpa,
1310
+ size,
1311
+ attributes : attr,
1312
+ } ) ;
1313
+ Ok ( VcpuEmulation :: Handled )
1314
+ }
1315
+ }
1316
+ // Documentation specifices that when KVM exists with KVM_EXIT_MEMORY_FAULT,
1317
+ // userspace should assume kvm_run.exit_reason is stale/undefined for error numbers
1318
+ // different than EFAULT or EHWPOISON
1319
+ #[ cfg( feature = "tee" ) ]
1320
+ Unsupported ( KVM_EXIT_MEMORY_FAULT ) => Ok ( VcpuEmulation :: Handled ) ,
1321
+ VcpuExit :: InternalError => {
1322
+ error ! ( "Received KVM_EXIT_INTERNAL_ERROR signal" ) ;
1323
+ Err ( Error :: VcpuUnhandledKvmExit )
1324
+ }
1269
1325
// Documentation specifies that below kvm exits are considered
1270
1326
// errors.
1271
1327
VcpuExit :: FailEntry ( reason, vcpu) => {
1272
1328
error ! ( "Received KVM_EXIT_FAIL_ENTRY signal: reason={reason}, vcpu={vcpu}" ) ;
1273
1329
Err ( Error :: VcpuUnhandledKvmExit )
1274
1330
}
1275
- VcpuExit :: InternalError => {
1276
- error ! ( "Received KVM_EXIT_INTERNAL_ERROR signal" ) ;
1277
- Err ( Error :: VcpuUnhandledKvmExit )
1278
- }
1279
1331
r => {
1280
1332
// TODO: Are we sure we want to finish running a vcpu upon
1281
1333
// receiving a vm exit that is not necessarily an error?
0 commit comments