@@ -1193,7 +1193,10 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1193
1193
match receiver. recv ( ) {
1194
1194
Err ( e) => error ! ( "Error in receiver: {:?}" , e) ,
1195
1195
Ok ( ( gpa, size, private) ) => {
1196
- let _ = convert_memory ( & mapper_vmm, gpa, size, private) ;
1196
+ let ret = convert_memory ( & mapper_vmm, gpa, size, private) ;
1197
+ if ret < 0 {
1198
+ panic ! ( "{}" , format!( "ERROR CONVERTING MEMORY: {:x} {:x} {}" , gpa, size, private) ) ;
1199
+ }
1197
1200
} ,
1198
1201
}
1199
1202
} ) . unwrap ( ) ;
@@ -1227,74 +1230,139 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1227
1230
}
1228
1231
}
1229
1232
1233
+ use vm_memory:: Address ;
1234
+ fn has_guest_memory ( gpa : u64 , size : u64 , memfd_regions : & Vec < ( vm_memory:: GuestAddress , u64 , u64 ) > ) -> ( bool , i64 ) {
1235
+ for ( a, s, i) in memfd_regions. iter ( ) {
1236
+ if gpa >= a. 0 && gpa + size <= a. 0 + * s {
1237
+ return ( true , * i as i64 ) ;
1238
+ }
1239
+ }
1240
+ ( false , -1 )
1241
+ }
1242
+
1230
1243
use std:: sync:: Arc ;
1231
1244
use vm_memory:: GuestAddress ;
1245
+ use vm_memory:: GuestMemory ;
1246
+ use libc:: fallocate;
1247
+ use libc:: madvise;
1248
+ use libc:: FALLOC_FL_KEEP_SIZE ;
1249
+ use libc:: FALLOC_FL_PUNCH_HOLE ;
1250
+ use libc:: MADV_DONTNEED ;
1251
+ use libc:: MADV_REMOVE ;
1232
1252
fn convert_memory ( vmm : & Arc < Mutex < vmm:: Vmm > > , gpa : u64 , size : u64 , to_private : bool ) -> i32 {
1253
+
1254
+ // check to make sure the starting address is aligned with the page size
1255
+ // check to make sure the size of the memory block is also aligned with the page size
1256
+ // if size is non-positive then return -1
1257
+ // retrive the memory region associated with the starting address and the size
1258
+ // set the memory attributes to the desired value
1259
+ // if converting memory from shared to private, then discard the ram range
1260
+ // if converting from private to shared, then discard the guest memfd range
1261
+
1233
1262
let mut ret = -1 ;
1234
- let is_aligned = |n : u64 , m : u64 | -> bool {
1235
- ( ( n) % ( m) ) == 0
1236
- } ;
1237
-
1238
- if !is_aligned ( gpa, 4096 ) || !is_aligned ( size, 4096 ) {
1263
+ let vmm = vmm. as_ref ( ) . lock ( ) . unwrap ( ) ;
1264
+ let guest_memfd_regions = vmm. guest_memfd_regions ( ) ;
1265
+
1266
+ let page_size = 4096 ;
1267
+
1268
+ // check to make sure the starting address is aligned with the page size
1269
+ // check to make sure the size of the memory block is also aligned with the page size
1270
+ if ( gpa % page_size) != 0 || ( size % page_size) != 0 {
1271
+ println ! ( "ALIGNMENT ERROR" ) ;
1239
1272
return -1 ;
1240
1273
}
1241
1274
1275
+ // if size is non-positive then return -1
1242
1276
if size < 1 {
1277
+ println ! ( "BAD SIZE" ) ;
1243
1278
return -1 ;
1244
1279
}
1245
1280
1246
- use vm_memory:: guest_memory:: GuestMemory ;
1247
- let binding = vmm. as_ref ( ) . lock ( ) . unwrap ( ) ;
1248
- let region = binding. guest_memory ( ) . find_region ( GuestAddress ( gpa) ) ;
1249
-
1281
+ let region = vmm. guest_memory ( ) . find_region ( GuestAddress ( gpa) ) ;
1250
1282
if let None = region {
1251
- // Ignore converting non-assigned region to shared
1283
+ // ignore converting non-assigned region to shared
1252
1284
//
1253
1285
// TDX requires vMMIO region to be shared to inject #VE to guest. OVMF issues
1254
- // conservatively MapGPA(shared) on 32bit PCI MMIO region, and V vIO-APIC 0xFEC00000 4K
1255
- // page. OVMF assigns 32bit PCI MMIO region to [top of low memory: typically 2GB=0xC000000 ,
1256
- // 0xFC00000 )
1286
+ // conservatively MapGPA(shared) on 32bit PCI MMIO region, and vIO-APIC 0xFEC 4k page. OVMF
1287
+ // assignes 32bit PCI MMIO region to [top of low memory: typically 2GB=0xC0000000 ,
1288
+ // 0xFC000000 )
1257
1289
if !to_private {
1290
+ println ! ( "IGNORE NON-ASSIGNED" ) ;
1258
1291
return 0 ;
1259
1292
}
1293
+
1294
+ println ! ( "ERROR FINDING REGION" ) ;
1260
1295
return -1 ;
1261
1296
}
1262
-
1263
1297
let region = region. unwrap ( ) ;
1264
1298
1265
- use vm_memory:: Address ;
1266
- let mut region_has_guest_memfd = false ;
1267
- for region in binding. guest_memfd_regions ( ) . iter ( ) {
1268
- if gpa >= region. 0 . raw_value ( ) && gpa + size <= region. 0 . raw_value ( ) + region. 1 {
1269
- region_has_guest_memfd = true ;
1270
- }
1271
- }
1299
+ // retrive the memory region associated with the starting address and the size
1300
+ let ( region_has_guest_memfd, memfd_id) = has_guest_memory ( gpa, size, guest_memfd_regions) ;
1272
1301
1302
+ // check to make sure there is a guest memfd backing
1273
1303
if !region_has_guest_memfd {
1274
- println ! ( "DOESNT HAVE MEMFD" ) ;
1275
-
1276
- // Because vMMIO region must be shared, guest TD may convert vMMIO region to shared
1277
- // explicitly. Don't complain such case. See memory_region_type() for checking if the
1278
- // region is MMIO region.
1279
- // if !to_private && !is_ram && !is_ram_device && !is_rom && !is_romd {
1280
- // ret = 0;
1281
- // } else {
1282
- // println!("Convert non guest_memfd backed memory region (0x{:x}, 0x{:x}, {}", gpa, size, if to_private { "private" } else { "shared" });
1283
- // }
1284
-
1285
- return ret;
1304
+ panic ! ( "cannot convert non guest_memfd backed memory region" ) ;
1305
+ return -1 ;
1286
1306
}
1287
-
1307
+
1308
+ // set the memory attributes to the desired value
1288
1309
let attr = kvm_bindings:: kvm_memory_attributes {
1289
- address : gpa,
1290
- size,
1291
- attributes : if to_private {
1292
- // KVM_MEMORY_ATTRIBUTE_PRIVATE,
1293
- 1 << 3 } else { 0 } ,
1294
- flags : 0 ,
1310
+ address : gpa,
1311
+ size,
1312
+ attributes : if to_private {
1313
+ // KVM_MEMORY_ATTRIBUTE_PRIVATE,
1314
+ 1 << 3 } else { 0 } ,
1315
+ flags : 0 ,
1295
1316
} ;
1296
1317
1297
- binding. vm_fd ( ) . set_memory_attributes ( attr) . unwrap ( ) ;
1318
+ vmm. vm_fd ( ) . set_memory_attributes ( attr) . unwrap ( ) ;
1319
+
1320
+ use vm_memory:: GuestMemoryRegion ;
1321
+
1322
+ let offset = gpa - region. start_addr ( ) . raw_value ( ) ;
1323
+ if to_private {
1324
+ // ram_block_discard_range
1325
+ println ! ( "DISCARDING MEMORY RANGE WHEN CONVERTING SHARED TO PRIVATE" ) ;
1326
+
1327
+ let host_addr = region. get_host_address ( vm_memory:: MemoryRegionAddress ( gpa) ) . unwrap ( ) ;
1328
+
1329
+ // let host_addr = gpa + offset;
1330
+ unsafe {
1331
+ let _ret = madvise (
1332
+ host_addr as * mut libc:: c_void ,
1333
+ size. try_into ( ) . unwrap ( ) ,
1334
+ // madv_remove,
1335
+ MADV_DONTNEED ,
1336
+ ) ;
1337
+ println ! ( "gpa: {:x} size: {:x}" , gpa, size) ;
1338
+
1339
+ if _ret < 0 {
1340
+ println ! ( "error discarding memory range: gpa: 0x{:x} size: 0x{:x} res: {}" , gpa, size, std:: io:: Error :: last_os_error( ) ) ;
1341
+ return _ret;
1342
+ }
1343
+ }
1344
+ } else {
1345
+ // ram_block_discard_guest_memfd_range
1346
+ println ! ( "DISCARDING GUEST MEMFD MEMORY REGION WHEN CONVERTING PRIVATE TO SHARED" ) ;
1347
+ unsafe {
1348
+ let _ret = fallocate (
1349
+ memfd_id as i32 ,
1350
+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE ,
1351
+ offset as i64 ,
1352
+ size as i64 ,
1353
+ ) ;
1354
+
1355
+ if _ret < 0 {
1356
+ println ! ( "error discarding guest memfd memory range: {}" , std:: io:: Error :: last_os_error( ) ) ;
1357
+ return _ret;
1358
+ }
1359
+ }
1360
+ }
1298
1361
1362
+ 0
1363
+ }
1364
+
1365
+ fn ram_block_discard_range < T > ( rb : & vm_memory:: GuestRegionMmap < T > , start : u64 , length : u64 ) -> i64 {
1366
+ let mut ret = -1 ;
1299
1367
ret
1300
1368
}
0 commit comments