@@ -583,39 +583,6 @@ void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt)
583583 BUG_ON (ret && ret != - EAGAIN );
584584}
585585
586- struct pkvm_mem_transition {
587- u64 nr_pages ;
588-
589- struct {
590- enum pkvm_component_id id ;
591- /* Address in the initiator's address space */
592- u64 addr ;
593-
594- union {
595- struct {
596- /* Address in the completer's address space */
597- u64 completer_addr ;
598- } host ;
599- struct {
600- u64 completer_addr ;
601- } hyp ;
602- };
603- } initiator ;
604-
605- struct {
606- enum pkvm_component_id id ;
607- } completer ;
608- };
609-
610- struct pkvm_mem_share {
611- const struct pkvm_mem_transition tx ;
612- const enum kvm_pgtable_prot completer_prot ;
613- };
614-
615- struct pkvm_mem_donation {
616- const struct pkvm_mem_transition tx ;
617- };
618-
619586struct check_walk_data {
620587 enum pkvm_page_state desired ;
621588 enum pkvm_page_state (* get_page_state )(kvm_pte_t pte , u64 addr );
@@ -675,56 +642,6 @@ static int __host_set_page_state_range(u64 addr, u64 size,
675642 return 0 ;
676643}
677644
678- static int host_request_owned_transition (u64 * completer_addr ,
679- const struct pkvm_mem_transition * tx )
680- {
681- u64 size = tx -> nr_pages * PAGE_SIZE ;
682- u64 addr = tx -> initiator .addr ;
683-
684- * completer_addr = tx -> initiator .host .completer_addr ;
685- return __host_check_page_state_range (addr , size , PKVM_PAGE_OWNED );
686- }
687-
688- static int host_initiate_donation (u64 * completer_addr ,
689- const struct pkvm_mem_transition * tx )
690- {
691- u8 owner_id = tx -> completer .id ;
692- u64 size = tx -> nr_pages * PAGE_SIZE ;
693-
694- * completer_addr = tx -> initiator .host .completer_addr ;
695- return host_stage2_set_owner_locked (tx -> initiator .addr , size , owner_id );
696- }
697-
698- static bool __host_ack_skip_pgtable_check (const struct pkvm_mem_transition * tx )
699- {
700- return !(IS_ENABLED (CONFIG_NVHE_EL2_DEBUG ) ||
701- tx -> initiator .id != PKVM_ID_HYP );
702- }
703-
704- static int __host_ack_transition (u64 addr , const struct pkvm_mem_transition * tx ,
705- enum pkvm_page_state state )
706- {
707- u64 size = tx -> nr_pages * PAGE_SIZE ;
708-
709- if (__host_ack_skip_pgtable_check (tx ))
710- return 0 ;
711-
712- return __host_check_page_state_range (addr , size , state );
713- }
714-
715- static int host_ack_donation (u64 addr , const struct pkvm_mem_transition * tx )
716- {
717- return __host_ack_transition (addr , tx , PKVM_NOPAGE );
718- }
719-
720- static int host_complete_donation (u64 addr , const struct pkvm_mem_transition * tx )
721- {
722- u64 size = tx -> nr_pages * PAGE_SIZE ;
723- u8 host_id = tx -> completer .id ;
724-
725- return host_stage2_set_owner_locked (addr , size , host_id );
726- }
727-
728645static enum pkvm_page_state hyp_get_page_state (kvm_pte_t pte , u64 addr )
729646{
730647 if (!kvm_pte_valid (pte ))
@@ -745,52 +662,6 @@ static int __hyp_check_page_state_range(u64 addr, u64 size,
745662 return check_page_state_range (& pkvm_pgtable , addr , size , & d );
746663}
747664
748- static int hyp_request_donation (u64 * completer_addr ,
749- const struct pkvm_mem_transition * tx )
750- {
751- u64 size = tx -> nr_pages * PAGE_SIZE ;
752- u64 addr = tx -> initiator .addr ;
753-
754- * completer_addr = tx -> initiator .hyp .completer_addr ;
755- return __hyp_check_page_state_range (addr , size , PKVM_PAGE_OWNED );
756- }
757-
758- static int hyp_initiate_donation (u64 * completer_addr ,
759- const struct pkvm_mem_transition * tx )
760- {
761- u64 size = tx -> nr_pages * PAGE_SIZE ;
762- int ret ;
763-
764- * completer_addr = tx -> initiator .hyp .completer_addr ;
765- ret = kvm_pgtable_hyp_unmap (& pkvm_pgtable , tx -> initiator .addr , size );
766- return (ret != size ) ? - EFAULT : 0 ;
767- }
768-
769- static bool __hyp_ack_skip_pgtable_check (const struct pkvm_mem_transition * tx )
770- {
771- return !(IS_ENABLED (CONFIG_NVHE_EL2_DEBUG ) ||
772- tx -> initiator .id != PKVM_ID_HOST );
773- }
774-
775- static int hyp_ack_donation (u64 addr , const struct pkvm_mem_transition * tx )
776- {
777- u64 size = tx -> nr_pages * PAGE_SIZE ;
778-
779- if (__hyp_ack_skip_pgtable_check (tx ))
780- return 0 ;
781-
782- return __hyp_check_page_state_range (addr , size , PKVM_NOPAGE );
783- }
784-
785- static int hyp_complete_donation (u64 addr ,
786- const struct pkvm_mem_transition * tx )
787- {
788- void * start = (void * )addr , * end = start + (tx -> nr_pages * PAGE_SIZE );
789- enum kvm_pgtable_prot prot = pkvm_mkstate (PAGE_HYP , PKVM_PAGE_OWNED );
790-
791- return pkvm_create_mappings_locked (start , end , prot );
792- }
793-
794665static enum pkvm_page_state guest_get_page_state (kvm_pte_t pte , u64 addr )
795666{
796667 if (!kvm_pte_valid (pte ))
@@ -812,94 +683,6 @@ static int __guest_check_page_state_range(struct pkvm_hyp_vcpu *vcpu, u64 addr,
812683 return check_page_state_range (& vm -> pgt , addr , size , & d );
813684}
814685
815- static int check_donation (struct pkvm_mem_donation * donation )
816- {
817- const struct pkvm_mem_transition * tx = & donation -> tx ;
818- u64 completer_addr ;
819- int ret ;
820-
821- switch (tx -> initiator .id ) {
822- case PKVM_ID_HOST :
823- ret = host_request_owned_transition (& completer_addr , tx );
824- break ;
825- case PKVM_ID_HYP :
826- ret = hyp_request_donation (& completer_addr , tx );
827- break ;
828- default :
829- ret = - EINVAL ;
830- }
831-
832- if (ret )
833- return ret ;
834-
835- switch (tx -> completer .id ) {
836- case PKVM_ID_HOST :
837- ret = host_ack_donation (completer_addr , tx );
838- break ;
839- case PKVM_ID_HYP :
840- ret = hyp_ack_donation (completer_addr , tx );
841- break ;
842- default :
843- ret = - EINVAL ;
844- }
845-
846- return ret ;
847- }
848-
849- static int __do_donate (struct pkvm_mem_donation * donation )
850- {
851- const struct pkvm_mem_transition * tx = & donation -> tx ;
852- u64 completer_addr ;
853- int ret ;
854-
855- switch (tx -> initiator .id ) {
856- case PKVM_ID_HOST :
857- ret = host_initiate_donation (& completer_addr , tx );
858- break ;
859- case PKVM_ID_HYP :
860- ret = hyp_initiate_donation (& completer_addr , tx );
861- break ;
862- default :
863- ret = - EINVAL ;
864- }
865-
866- if (ret )
867- return ret ;
868-
869- switch (tx -> completer .id ) {
870- case PKVM_ID_HOST :
871- ret = host_complete_donation (completer_addr , tx );
872- break ;
873- case PKVM_ID_HYP :
874- ret = hyp_complete_donation (completer_addr , tx );
875- break ;
876- default :
877- ret = - EINVAL ;
878- }
879-
880- return ret ;
881- }
882-
883- /*
884- * do_donate():
885- *
886- * The page owner transfers ownership to another component, losing access
887- * as a consequence.
888- *
889- * Initiator: OWNED => NOPAGE
890- * Completer: NOPAGE => OWNED
891- */
892- static int do_donate (struct pkvm_mem_donation * donation )
893- {
894- int ret ;
895-
896- ret = check_donation (donation );
897- if (ret )
898- return ret ;
899-
900- return WARN_ON (__do_donate (donation ));
901- }
902-
903686int __pkvm_host_share_hyp (u64 pfn )
904687{
905688 u64 phys = hyp_pfn_to_phys (pfn );
@@ -964,30 +747,29 @@ int __pkvm_host_unshare_hyp(u64 pfn)
964747
965748int __pkvm_host_donate_hyp (u64 pfn , u64 nr_pages )
966749{
750+ u64 phys = hyp_pfn_to_phys (pfn );
751+ u64 size = PAGE_SIZE * nr_pages ;
752+ void * virt = __hyp_va (phys );
753+ enum kvm_pgtable_prot prot ;
967754 int ret ;
968- u64 host_addr = hyp_pfn_to_phys (pfn );
969- u64 hyp_addr = (u64 )__hyp_va (host_addr );
970- struct pkvm_mem_donation donation = {
971- .tx = {
972- .nr_pages = nr_pages ,
973- .initiator = {
974- .id = PKVM_ID_HOST ,
975- .addr = host_addr ,
976- .host = {
977- .completer_addr = hyp_addr ,
978- },
979- },
980- .completer = {
981- .id = PKVM_ID_HYP ,
982- },
983- },
984- };
985755
986756 host_lock_component ();
987757 hyp_lock_component ();
988758
989- ret = do_donate (& donation );
759+ ret = __host_check_page_state_range (phys , size , PKVM_PAGE_OWNED );
760+ if (ret )
761+ goto unlock ;
762+ if (IS_ENABLED (CONFIG_NVHE_EL2_DEBUG )) {
763+ ret = __hyp_check_page_state_range ((u64 )virt , size , PKVM_NOPAGE );
764+ if (ret )
765+ goto unlock ;
766+ }
990767
768+ prot = pkvm_mkstate (PAGE_HYP , PKVM_PAGE_OWNED );
769+ WARN_ON (pkvm_create_mappings_locked (virt , virt + size , prot ));
770+ WARN_ON (host_stage2_set_owner_locked (phys , size , PKVM_ID_HYP ));
771+
772+ unlock :
991773 hyp_unlock_component ();
992774 host_unlock_component ();
993775
@@ -996,30 +778,27 @@ int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages)
996778
997779int __pkvm_hyp_donate_host (u64 pfn , u64 nr_pages )
998780{
781+ u64 phys = hyp_pfn_to_phys (pfn );
782+ u64 size = PAGE_SIZE * nr_pages ;
783+ u64 virt = (u64 )__hyp_va (phys );
999784 int ret ;
1000- u64 host_addr = hyp_pfn_to_phys (pfn );
1001- u64 hyp_addr = (u64 )__hyp_va (host_addr );
1002- struct pkvm_mem_donation donation = {
1003- .tx = {
1004- .nr_pages = nr_pages ,
1005- .initiator = {
1006- .id = PKVM_ID_HYP ,
1007- .addr = hyp_addr ,
1008- .hyp = {
1009- .completer_addr = host_addr ,
1010- },
1011- },
1012- .completer = {
1013- .id = PKVM_ID_HOST ,
1014- },
1015- },
1016- };
1017785
1018786 host_lock_component ();
1019787 hyp_lock_component ();
1020788
1021- ret = do_donate (& donation );
789+ ret = __hyp_check_page_state_range (virt , size , PKVM_PAGE_OWNED );
790+ if (ret )
791+ goto unlock ;
792+ if (IS_ENABLED (CONFIG_NVHE_EL2_DEBUG )) {
793+ ret = __host_check_page_state_range (phys , size , PKVM_NOPAGE );
794+ if (ret )
795+ goto unlock ;
796+ }
1022797
798+ WARN_ON (kvm_pgtable_hyp_unmap (& pkvm_pgtable , virt , size ) != size );
799+ WARN_ON (host_stage2_set_owner_locked (phys , size , PKVM_ID_HOST ));
800+
801+ unlock :
1023802 hyp_unlock_component ();
1024803 host_unlock_component ();
1025804
0 commit comments