@@ -5,6 +5,8 @@ use std::collections::hash_map::Entry;
5
5
use std:: collections:: HashMap ;
6
6
use std:: convert:: TryInto ;
7
7
use std:: env;
8
+ #[ cfg( feature = "tee" ) ]
9
+ use std:: ffi:: c_void;
8
10
use std:: ffi:: CStr ;
9
11
#[ cfg( target_os = "linux" ) ]
10
12
use std:: ffi:: CString ;
@@ -20,7 +22,7 @@ use std::sync::atomic::{AtomicI32, Ordering};
20
22
use std:: sync:: LazyLock ;
21
23
use std:: sync:: Mutex ;
22
24
23
- #[ cfg( target_os = "macos" ) ]
25
+ #[ cfg( any ( target_os = "macos" , feature = "tee" ) ) ]
24
26
use crossbeam_channel:: unbounded;
25
27
#[ cfg( feature = "blk" ) ]
26
28
use devices:: virtio:: block:: ImageType ;
@@ -54,6 +56,17 @@ use vmm::vmm_config::machine_config::VmConfig;
54
56
use vmm:: vmm_config:: net:: NetworkInterfaceConfig ;
55
57
use vmm:: vmm_config:: vsock:: VsockDeviceConfig ;
56
58
59
+ #[ cfg( feature = "tee" ) ]
60
+ use kvm_bindings:: { kvm_memory_attributes, KVM_MEMORY_ATTRIBUTE_PRIVATE } ;
61
+
62
+ #[ cfg( feature = "tee" ) ]
63
+ use vm_memory:: { guest_memory:: GuestMemory , GuestAddress , GuestMemoryRegion , MemoryRegionAddress } ;
64
+
65
+ #[ cfg( feature = "tee" ) ]
66
+ use libc:: {
67
+ fallocate, madvise, EFD_SEMAPHORE , FALLOC_FL_KEEP_SIZE , FALLOC_FL_PUNCH_HOLE , MADV_DONTNEED ,
68
+ } ;
69
+
57
70
// Value returned on success. We use libc's errors otherwise.
58
71
const KRUN_SUCCESS : i32 = 0 ;
59
72
// Maximum number of arguments/environment variables we allow
@@ -1468,12 +1481,25 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1468
1481
#[ cfg( target_os = "macos" ) ]
1469
1482
let ( sender, receiver) = unbounded ( ) ;
1470
1483
1484
+ #[ cfg( feature = "tee" ) ]
1485
+ let ( pm_sender, pm_receiver) = unbounded ( ) ;
1486
+ #[ cfg( feature = "tee" ) ]
1487
+ let pm_efd =
1488
+ EventFd :: new ( EFD_SEMAPHORE ) . expect ( "unable to create TEE memory properties eventfd" ) ;
1489
+
1471
1490
let _vmm = match vmm:: builder:: build_microvm (
1472
1491
& ctx_cfg. vmr ,
1473
1492
& mut event_manager,
1474
1493
ctx_cfg. shutdown_efd ,
1475
1494
#[ cfg( target_os = "macos" ) ]
1476
1495
sender,
1496
+ #[ cfg( feature = "tee" ) ]
1497
+ (
1498
+ pm_sender,
1499
+ pm_efd
1500
+ . try_clone ( )
1501
+ . expect ( "unable to clone TEE memory properties eventfd" ) ,
1502
+ ) ,
1477
1503
) {
1478
1504
Ok ( vmm) => vmm,
1479
1505
Err ( e) => {
@@ -1482,7 +1508,7 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1482
1508
}
1483
1509
} ;
1484
1510
1485
- #[ cfg( target_os = "macos" ) ]
1511
+ #[ cfg( any ( target_os = "macos" , feature = "tee" ) ) ]
1486
1512
let mapper_vmm = _vmm. clone ( ) ;
1487
1513
1488
1514
#[ cfg( target_os = "macos" ) ]
@@ -1505,6 +1531,93 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1505
1531
. unwrap ( ) ;
1506
1532
}
1507
1533
1534
+ #[ cfg( feature = "tee" ) ]
1535
+ let guest_mem = _vmm. lock ( ) . unwrap ( ) . guest_memory ( ) . clone ( ) ;
1536
+
1537
+ #[ cfg( feature = "tee" ) ]
1538
+ std:: thread:: Builder :: new ( )
1539
+ . name ( "TEE memory properties worker" . into ( ) )
1540
+ . spawn ( move || loop {
1541
+ match pm_receiver. recv ( ) {
1542
+ Err ( e) => error ! ( "Error in pm receiver: {:?}" , e) ,
1543
+ Ok ( m) => {
1544
+ let ( guest_memfd, region_start) = mapper_vmm
1545
+ . lock ( )
1546
+ . unwrap ( )
1547
+ . kvm_vm ( )
1548
+ . guest_memfd_get ( m. gpa )
1549
+ . unwrap_or_else ( || panic ! ( "unable to find KVM guest_memfd for memory region corresponding to GPA 0x{:x}" , m. gpa) ) ;
1550
+
1551
+ let attributes: u64 = if m. private {
1552
+ KVM_MEMORY_ATTRIBUTE_PRIVATE as u64
1553
+ } else {
1554
+ 0
1555
+ } ;
1556
+
1557
+ let attr = kvm_memory_attributes {
1558
+ address : m. gpa ,
1559
+ size : m. size ,
1560
+ attributes,
1561
+ flags : 0 ,
1562
+ } ;
1563
+
1564
+ mapper_vmm
1565
+ . lock ( )
1566
+ . unwrap ( )
1567
+ . kvm_vm ( )
1568
+ . fd ( )
1569
+ . set_memory_attributes ( attr)
1570
+ . unwrap_or_else ( |_| panic ! ( "unable to set memory attributes for memory region corresponding to guest address 0x{:x}" , m. gpa) ) ;
1571
+
1572
+ let region = guest_mem. find_region ( GuestAddress ( m. gpa ) ) ;
1573
+ if region. is_none ( ) {
1574
+ error ! ( "{}" , format!( "guest memory region corresponding to GPA 0x{:x} not found" , m. gpa) ) ;
1575
+ pm_efd. write ( 1 ) . unwrap ( ) ;
1576
+ continue ;
1577
+ }
1578
+
1579
+ let offset = m. gpa - region_start;
1580
+
1581
+ if m. private {
1582
+ let region_addr = MemoryRegionAddress ( offset) ;
1583
+
1584
+ let host_startaddr = region
1585
+ . unwrap ( )
1586
+ . get_host_address ( region_addr)
1587
+ . expect ( "host address corresponding to memory region address 0x{:x} not found" ) ;
1588
+
1589
+ let ret = unsafe {
1590
+ madvise (
1591
+ host_startaddr as * mut c_void ,
1592
+ m. size . try_into ( ) . unwrap ( ) ,
1593
+ MADV_DONTNEED ,
1594
+ )
1595
+ } ;
1596
+
1597
+ if ret < 0 {
1598
+ error ! ( "{}" , format!( "unable to advise kernel that memory region corresponding to GPA 0x{:x} will likely not be needed (madvise)" , m. gpa) ) ;
1599
+ }
1600
+ } else {
1601
+ let ret = unsafe {
1602
+ fallocate (
1603
+ guest_memfd,
1604
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE ,
1605
+ offset as i64 ,
1606
+ m. size as i64 ,
1607
+ )
1608
+ } ;
1609
+
1610
+ if ret < 0 {
1611
+ error ! ( "{}" , format!( "unable to allocate space in guest_memfd for shared memory (fallocate)" ) ) ;
1612
+ }
1613
+ }
1614
+
1615
+ pm_efd. write ( 1 ) . unwrap ( ) ;
1616
+ }
1617
+ }
1618
+ } )
1619
+ . unwrap ( ) ;
1620
+
1508
1621
loop {
1509
1622
match event_manager. run ( ) {
1510
1623
Ok ( _) => { }
0 commit comments