@@ -867,6 +867,27 @@ static int hyp_complete_donation(u64 addr,
867867 return pkvm_create_mappings_locked (start , end , prot );
868868}
869869
870+ static enum pkvm_page_state guest_get_page_state (kvm_pte_t pte , u64 addr )
871+ {
872+ if (!kvm_pte_valid (pte ))
873+ return PKVM_NOPAGE ;
874+
875+ return pkvm_getstate (kvm_pgtable_stage2_pte_prot (pte ));
876+ }
877+
878+ static int __guest_check_page_state_range (struct pkvm_hyp_vcpu * vcpu , u64 addr ,
879+ u64 size , enum pkvm_page_state state )
880+ {
881+ struct pkvm_hyp_vm * vm = pkvm_hyp_vcpu_to_hyp_vm (vcpu );
882+ struct check_walk_data d = {
883+ .desired = state ,
884+ .get_page_state = guest_get_page_state ,
885+ };
886+
887+ hyp_assert_lock_held (& vm -> lock );
888+ return check_page_state_range (& vm -> pgt , addr , size , & d );
889+ }
890+
870891static int check_share (struct pkvm_mem_share * share )
871892{
872893 const struct pkvm_mem_transition * tx = & share -> tx ;
@@ -1349,3 +1370,54 @@ int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages)
13491370
13501371 return ret ;
13511372}
1373+
1374+ int __pkvm_host_share_guest (u64 pfn , u64 gfn , struct pkvm_hyp_vcpu * vcpu ,
1375+ enum kvm_pgtable_prot prot )
1376+ {
1377+ struct pkvm_hyp_vm * vm = pkvm_hyp_vcpu_to_hyp_vm (vcpu );
1378+ u64 phys = hyp_pfn_to_phys (pfn );
1379+ u64 ipa = hyp_pfn_to_phys (gfn );
1380+ struct hyp_page * page ;
1381+ int ret ;
1382+
1383+ if (prot & ~KVM_PGTABLE_PROT_RWX )
1384+ return - EINVAL ;
1385+
1386+ ret = check_range_allowed_memory (phys , phys + PAGE_SIZE );
1387+ if (ret )
1388+ return ret ;
1389+
1390+ host_lock_component ();
1391+ guest_lock_component (vm );
1392+
1393+ ret = __guest_check_page_state_range (vcpu , ipa , PAGE_SIZE , PKVM_NOPAGE );
1394+ if (ret )
1395+ goto unlock ;
1396+
1397+ page = hyp_phys_to_page (phys );
1398+ switch (page -> host_state ) {
1399+ case PKVM_PAGE_OWNED :
1400+ WARN_ON (__host_set_page_state_range (phys , PAGE_SIZE , PKVM_PAGE_SHARED_OWNED ));
1401+ break ;
1402+ case PKVM_PAGE_SHARED_OWNED :
1403+ if (page -> host_share_guest_count )
1404+ break ;
1405+ /* Only host to np-guest multi-sharing is tolerated */
1406+ WARN_ON (1 );
1407+ fallthrough ;
1408+ default :
1409+ ret = - EPERM ;
1410+ goto unlock ;
1411+ }
1412+
1413+ WARN_ON (kvm_pgtable_stage2_map (& vm -> pgt , ipa , PAGE_SIZE , phys ,
1414+ pkvm_mkstate (prot , PKVM_PAGE_SHARED_BORROWED ),
1415+ & vcpu -> vcpu .arch .pkvm_memcache , 0 ));
1416+ page -> host_share_guest_count ++ ;
1417+
1418+ unlock :
1419+ guest_unlock_component (vm );
1420+ host_unlock_component ();
1421+
1422+ return ret ;
1423+ }
0 commit comments