@@ -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
@@ -1471,12 +1484,25 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1471
1484
#[ cfg( target_os = "macos" ) ]
1472
1485
let ( sender, receiver) = unbounded ( ) ;
1473
1486
1487
+ #[ cfg( feature = "tee" ) ]
1488
+ let ( pm_sender, pm_receiver) = unbounded ( ) ;
1489
+ #[ cfg( feature = "tee" ) ]
1490
+ let pm_efd =
1491
+ EventFd :: new ( EFD_SEMAPHORE ) . expect ( "unable to create TEE memory properties eventfd" ) ;
1492
+
1474
1493
let _vmm = match vmm:: builder:: build_microvm (
1475
1494
& ctx_cfg. vmr ,
1476
1495
& mut event_manager,
1477
1496
ctx_cfg. shutdown_efd ,
1478
1497
#[ cfg( target_os = "macos" ) ]
1479
1498
sender,
1499
+ #[ cfg( feature = "tee" ) ]
1500
+ (
1501
+ pm_sender,
1502
+ pm_efd
1503
+ . try_clone ( )
1504
+ . expect ( "unable to clone TEE memory properties eventfd" ) ,
1505
+ ) ,
1480
1506
) {
1481
1507
Ok ( vmm) => vmm,
1482
1508
Err ( e) => {
@@ -1485,7 +1511,7 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1485
1511
}
1486
1512
} ;
1487
1513
1488
- #[ cfg( target_os = "macos" ) ]
1514
+ #[ cfg( any ( target_os = "macos" , feature = "tee" ) ) ]
1489
1515
let mapper_vmm = _vmm. clone ( ) ;
1490
1516
1491
1517
#[ cfg( target_os = "macos" ) ]
@@ -1508,6 +1534,93 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1508
1534
. unwrap ( ) ;
1509
1535
}
1510
1536
1537
+ #[ cfg( feature = "tee" ) ]
1538
+ let guest_mem = _vmm. lock ( ) . unwrap ( ) . guest_memory ( ) . clone ( ) ;
1539
+
1540
+ #[ cfg( feature = "tee" ) ]
1541
+ std:: thread:: Builder :: new ( )
1542
+ . name ( "TEE memory properties worker" . into ( ) )
1543
+ . spawn ( move || loop {
1544
+ match pm_receiver. recv ( ) {
1545
+ Err ( e) => error ! ( "Error in pm receiver: {:?}" , e) ,
1546
+ Ok ( m) => {
1547
+ let ( guest_memfd, region_start) = mapper_vmm
1548
+ . lock ( )
1549
+ . unwrap ( )
1550
+ . kvm_vm ( )
1551
+ . guest_memfd_get ( m. gpa )
1552
+ . unwrap_or_else ( || panic ! ( "unable to find KVM guest_memfd for memory region corresponding to GPA 0x{:x}" , m. gpa) ) ;
1553
+
1554
+ let attributes: u64 = if m. private {
1555
+ KVM_MEMORY_ATTRIBUTE_PRIVATE as u64
1556
+ } else {
1557
+ 0
1558
+ } ;
1559
+
1560
+ let attr = kvm_memory_attributes {
1561
+ address : m. gpa ,
1562
+ size : m. size ,
1563
+ attributes,
1564
+ flags : 0 ,
1565
+ } ;
1566
+
1567
+ mapper_vmm
1568
+ . lock ( )
1569
+ . unwrap ( )
1570
+ . kvm_vm ( )
1571
+ . fd ( )
1572
+ . set_memory_attributes ( attr)
1573
+ . unwrap_or_else ( |_| panic ! ( "unable to set memory attributes for memory region corresponding to guest address 0x{:x}" , m. gpa) ) ;
1574
+
1575
+ let region = guest_mem. find_region ( GuestAddress ( m. gpa ) ) ;
1576
+ if region. is_none ( ) {
1577
+ error ! ( "{}" , format!( "guest memory region corresponding to GPA 0x{:x} not found" , m. gpa) ) ;
1578
+ pm_efd. write ( 1 ) . unwrap ( ) ;
1579
+ continue ;
1580
+ }
1581
+
1582
+ let offset = m. gpa - region_start;
1583
+
1584
+ if m. private {
1585
+ let region_addr = MemoryRegionAddress ( offset) ;
1586
+
1587
+ let host_startaddr = region
1588
+ . unwrap ( )
1589
+ . get_host_address ( region_addr)
1590
+ . expect ( "host address corresponding to memory region address 0x{:x} not found" ) ;
1591
+
1592
+ let ret = unsafe {
1593
+ madvise (
1594
+ host_startaddr as * mut c_void ,
1595
+ m. size . try_into ( ) . unwrap ( ) ,
1596
+ MADV_DONTNEED ,
1597
+ )
1598
+ } ;
1599
+
1600
+ if ret < 0 {
1601
+ error ! ( "{}" , format!( "unable to advise kernel that memory region corresponding to GPA 0x{:x} will likely not be needed (madvise)" , m. gpa) ) ;
1602
+ }
1603
+ } else {
1604
+ let ret = unsafe {
1605
+ fallocate (
1606
+ guest_memfd,
1607
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE ,
1608
+ offset as i64 ,
1609
+ m. size as i64 ,
1610
+ )
1611
+ } ;
1612
+
1613
+ if ret < 0 {
1614
+ error ! ( "{}" , format!( "unable to allocate space in guest_memfd for shared memory (fallocate)" ) ) ;
1615
+ }
1616
+ }
1617
+
1618
+ pm_efd. write ( 1 ) . unwrap ( ) ;
1619
+ }
1620
+ }
1621
+ } )
1622
+ . unwrap ( ) ;
1623
+
1511
1624
loop {
1512
1625
match event_manager. run ( ) {
1513
1626
Ok ( _) => { }
0 commit comments