@@ -370,94 +370,6 @@ static int host_stage2_idmap(u64 addr)
370
370
return ret ;
371
371
}
372
372
373
- static inline bool check_prot (enum kvm_pgtable_prot prot ,
374
- enum kvm_pgtable_prot required ,
375
- enum kvm_pgtable_prot denied )
376
- {
377
- return (prot & (required | denied )) == required ;
378
- }
379
-
380
- int __pkvm_host_share_hyp (u64 pfn )
381
- {
382
- phys_addr_t addr = hyp_pfn_to_phys (pfn );
383
- enum kvm_pgtable_prot prot , cur ;
384
- void * virt = __hyp_va (addr );
385
- enum pkvm_page_state state ;
386
- kvm_pte_t pte ;
387
- int ret ;
388
-
389
- if (!addr_is_memory (addr ))
390
- return - EINVAL ;
391
-
392
- host_lock_component ();
393
- hyp_lock_component ();
394
-
395
- ret = kvm_pgtable_get_leaf (& host_kvm .pgt , addr , & pte , NULL );
396
- if (ret )
397
- goto unlock ;
398
- if (!pte )
399
- goto map_shared ;
400
-
401
- /*
402
- * Check attributes in the host stage-2 PTE. We need the page to be:
403
- * - mapped RWX as we're sharing memory;
404
- * - not borrowed, as that implies absence of ownership.
405
- * Otherwise, we can't let it got through
406
- */
407
- cur = kvm_pgtable_stage2_pte_prot (pte );
408
- prot = pkvm_mkstate (0 , PKVM_PAGE_SHARED_BORROWED );
409
- if (!check_prot (cur , PKVM_HOST_MEM_PROT , prot )) {
410
- ret = - EPERM ;
411
- goto unlock ;
412
- }
413
-
414
- state = pkvm_getstate (cur );
415
- if (state == PKVM_PAGE_OWNED )
416
- goto map_shared ;
417
-
418
- /*
419
- * Tolerate double-sharing the same page, but this requires
420
- * cross-checking the hypervisor stage-1.
421
- */
422
- if (state != PKVM_PAGE_SHARED_OWNED ) {
423
- ret = - EPERM ;
424
- goto unlock ;
425
- }
426
-
427
- ret = kvm_pgtable_get_leaf (& pkvm_pgtable , (u64 )virt , & pte , NULL );
428
- if (ret )
429
- goto unlock ;
430
-
431
- /*
432
- * If the page has been shared with the hypervisor, it must be
433
- * already mapped as SHARED_BORROWED in its stage-1.
434
- */
435
- cur = kvm_pgtable_hyp_pte_prot (pte );
436
- prot = pkvm_mkstate (PAGE_HYP , PKVM_PAGE_SHARED_BORROWED );
437
- if (!check_prot (cur , prot , ~prot ))
438
- ret = - EPERM ;
439
- goto unlock ;
440
-
441
- map_shared :
442
- /*
443
- * If the page is not yet shared, adjust mappings in both page-tables
444
- * while both locks are held.
445
- */
446
- prot = pkvm_mkstate (PAGE_HYP , PKVM_PAGE_SHARED_BORROWED );
447
- ret = pkvm_create_mappings_locked (virt , virt + PAGE_SIZE , prot );
448
- BUG_ON (ret );
449
-
450
- prot = pkvm_mkstate (PKVM_HOST_MEM_PROT , PKVM_PAGE_SHARED_OWNED );
451
- ret = host_stage2_idmap_locked (addr , PAGE_SIZE , prot );
452
- BUG_ON (ret );
453
-
454
- unlock :
455
- hyp_unlock_component ();
456
- host_unlock_component ();
457
-
458
- return ret ;
459
- }
460
-
461
373
void handle_host_mem_abort (struct kvm_cpu_context * host_ctxt )
462
374
{
463
375
struct kvm_vcpu_fault_info fault ;
@@ -708,3 +620,36 @@ static int do_share(struct pkvm_mem_share *share)
708
620
709
621
return WARN_ON (__do_share (share ));
710
622
}
623
+
624
+ int __pkvm_host_share_hyp (u64 pfn )
625
+ {
626
+ int ret ;
627
+ u64 host_addr = hyp_pfn_to_phys (pfn );
628
+ u64 hyp_addr = (u64 )__hyp_va (host_addr );
629
+ struct pkvm_mem_share share = {
630
+ .tx = {
631
+ .nr_pages = 1 ,
632
+ .initiator = {
633
+ .id = PKVM_ID_HOST ,
634
+ .addr = host_addr ,
635
+ .host = {
636
+ .completer_addr = hyp_addr ,
637
+ },
638
+ },
639
+ .completer = {
640
+ .id = PKVM_ID_HYP ,
641
+ },
642
+ },
643
+ .completer_prot = PAGE_HYP ,
644
+ };
645
+
646
+ host_lock_component ();
647
+ hyp_lock_component ();
648
+
649
+ ret = do_share (& share );
650
+
651
+ hyp_unlock_component ();
652
+ host_unlock_component ();
653
+
654
+ return ret ;
655
+ }
0 commit comments