@@ -485,6 +485,16 @@ static int host_request_owned_transition(u64 *completer_addr,
485
485
return __host_check_page_state_range (addr , size , PKVM_PAGE_OWNED );
486
486
}
487
487
488
+ static int host_request_unshare (u64 * completer_addr ,
489
+ const struct pkvm_mem_transition * tx )
490
+ {
491
+ u64 size = tx -> nr_pages * PAGE_SIZE ;
492
+ u64 addr = tx -> initiator .addr ;
493
+
494
+ * completer_addr = tx -> initiator .host .completer_addr ;
495
+ return __host_check_page_state_range (addr , size , PKVM_PAGE_SHARED_OWNED );
496
+ }
497
+
488
498
static int host_initiate_share (u64 * completer_addr ,
489
499
const struct pkvm_mem_transition * tx )
490
500
{
@@ -495,6 +505,16 @@ static int host_initiate_share(u64 *completer_addr,
495
505
return __host_set_page_state_range (addr , size , PKVM_PAGE_SHARED_OWNED );
496
506
}
497
507
508
+ static int host_initiate_unshare (u64 * completer_addr ,
509
+ const struct pkvm_mem_transition * tx )
510
+ {
511
+ u64 size = tx -> nr_pages * PAGE_SIZE ;
512
+ u64 addr = tx -> initiator .addr ;
513
+
514
+ * completer_addr = tx -> initiator .host .completer_addr ;
515
+ return __host_set_page_state_range (addr , size , PKVM_PAGE_OWNED );
516
+ }
517
+
498
518
static enum pkvm_page_state hyp_get_page_state (kvm_pte_t pte )
499
519
{
500
520
if (!kvm_pte_valid (pte ))
@@ -535,6 +555,17 @@ static int hyp_ack_share(u64 addr, const struct pkvm_mem_transition *tx,
535
555
return __hyp_check_page_state_range (addr , size , PKVM_NOPAGE );
536
556
}
537
557
558
+ static int hyp_ack_unshare (u64 addr , const struct pkvm_mem_transition * tx )
559
+ {
560
+ u64 size = tx -> nr_pages * PAGE_SIZE ;
561
+
562
+ if (__hyp_ack_skip_pgtable_check (tx ))
563
+ return 0 ;
564
+
565
+ return __hyp_check_page_state_range (addr , size ,
566
+ PKVM_PAGE_SHARED_BORROWED );
567
+ }
568
+
538
569
static int hyp_complete_share (u64 addr , const struct pkvm_mem_transition * tx ,
539
570
enum kvm_pgtable_prot perms )
540
571
{
@@ -545,6 +576,14 @@ static int hyp_complete_share(u64 addr, const struct pkvm_mem_transition *tx,
545
576
return pkvm_create_mappings_locked (start , end , prot );
546
577
}
547
578
579
+ static int hyp_complete_unshare (u64 addr , const struct pkvm_mem_transition * tx )
580
+ {
581
+ u64 size = tx -> nr_pages * PAGE_SIZE ;
582
+ int ret = kvm_pgtable_hyp_unmap (& pkvm_pgtable , addr , size );
583
+
584
+ return (ret != size ) ? - EFAULT : 0 ;
585
+ }
586
+
548
587
static int check_share (struct pkvm_mem_share * share )
549
588
{
550
589
const struct pkvm_mem_transition * tx = & share -> tx ;
@@ -621,6 +660,82 @@ static int do_share(struct pkvm_mem_share *share)
621
660
return WARN_ON (__do_share (share ));
622
661
}
623
662
663
+ static int check_unshare (struct pkvm_mem_share * share )
664
+ {
665
+ const struct pkvm_mem_transition * tx = & share -> tx ;
666
+ u64 completer_addr ;
667
+ int ret ;
668
+
669
+ switch (tx -> initiator .id ) {
670
+ case PKVM_ID_HOST :
671
+ ret = host_request_unshare (& completer_addr , tx );
672
+ break ;
673
+ default :
674
+ ret = - EINVAL ;
675
+ }
676
+
677
+ if (ret )
678
+ return ret ;
679
+
680
+ switch (tx -> completer .id ) {
681
+ case PKVM_ID_HYP :
682
+ ret = hyp_ack_unshare (completer_addr , tx );
683
+ break ;
684
+ default :
685
+ ret = - EINVAL ;
686
+ }
687
+
688
+ return ret ;
689
+ }
690
+
691
+ static int __do_unshare (struct pkvm_mem_share * share )
692
+ {
693
+ const struct pkvm_mem_transition * tx = & share -> tx ;
694
+ u64 completer_addr ;
695
+ int ret ;
696
+
697
+ switch (tx -> initiator .id ) {
698
+ case PKVM_ID_HOST :
699
+ ret = host_initiate_unshare (& completer_addr , tx );
700
+ break ;
701
+ default :
702
+ ret = - EINVAL ;
703
+ }
704
+
705
+ if (ret )
706
+ return ret ;
707
+
708
+ switch (tx -> completer .id ) {
709
+ case PKVM_ID_HYP :
710
+ ret = hyp_complete_unshare (completer_addr , tx );
711
+ break ;
712
+ default :
713
+ ret = - EINVAL ;
714
+ }
715
+
716
+ return ret ;
717
+ }
718
+
719
+ /*
720
+ * do_unshare():
721
+ *
722
+ * The page owner revokes access from another component for a range of
723
+ * pages which were previously shared using do_share().
724
+ *
725
+ * Initiator: SHARED_OWNED => OWNED
726
+ * Completer: SHARED_BORROWED => NOPAGE
727
+ */
728
+ static int do_unshare (struct pkvm_mem_share * share )
729
+ {
730
+ int ret ;
731
+
732
+ ret = check_unshare (share );
733
+ if (ret )
734
+ return ret ;
735
+
736
+ return WARN_ON (__do_unshare (share ));
737
+ }
738
+
624
739
int __pkvm_host_share_hyp (u64 pfn )
625
740
{
626
741
int ret ;
0 commit comments