@@ -1095,16 +1095,60 @@ int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu)
10951095struct pkvm_expected_state {
10961096 enum pkvm_page_state host ;
10971097 enum pkvm_page_state hyp ;
1098+ enum pkvm_page_state guest [2 ]; /* [ gfn, gfn + 1 ] */
10981099};
10991100
11001101static struct pkvm_expected_state selftest_state ;
11011102static struct hyp_page * selftest_page ;
11021103
1104+ static struct pkvm_hyp_vm selftest_vm = {
1105+ .kvm = {
1106+ .arch = {
1107+ .mmu = {
1108+ .arch = & selftest_vm .kvm .arch ,
1109+ .pgt = & selftest_vm .pgt ,
1110+ },
1111+ },
1112+ },
1113+ };
1114+
1115+ static struct pkvm_hyp_vcpu selftest_vcpu = {
1116+ .vcpu = {
1117+ .arch = {
1118+ .hw_mmu = & selftest_vm .kvm .arch .mmu ,
1119+ },
1120+ .kvm = & selftest_vm .kvm ,
1121+ },
1122+ };
1123+
1124+ static void init_selftest_vm (void * virt )
1125+ {
1126+ struct hyp_page * p = hyp_virt_to_page (virt );
1127+ int i ;
1128+
1129+ selftest_vm .kvm .arch .mmu .vtcr = host_mmu .arch .mmu .vtcr ;
1130+ WARN_ON (kvm_guest_prepare_stage2 (& selftest_vm , virt ));
1131+
1132+ for (i = 0 ; i < pkvm_selftest_pages (); i ++ ) {
1133+ if (p [i ].refcount )
1134+ continue ;
1135+ p [i ].refcount = 1 ;
1136+ hyp_put_page (& selftest_vm .pool , hyp_page_to_virt (& p [i ]));
1137+ }
1138+ }
1139+
1140+ static u64 selftest_ipa (void )
1141+ {
1142+ return BIT (selftest_vm .pgt .ia_bits - 1 );
1143+ }
1144+
11031145static void assert_page_state (void )
11041146{
11051147 void * virt = hyp_page_to_virt (selftest_page );
11061148 u64 size = PAGE_SIZE << selftest_page -> order ;
1149+ struct pkvm_hyp_vcpu * vcpu = & selftest_vcpu ;
11071150 u64 phys = hyp_virt_to_phys (virt );
1151+ u64 ipa [2 ] = { selftest_ipa (), selftest_ipa () + PAGE_SIZE };
11081152
11091153 host_lock_component ();
11101154 WARN_ON (__host_check_page_state_range (phys , size , selftest_state .host ));
@@ -1113,6 +1157,11 @@ static void assert_page_state(void)
11131157 hyp_lock_component ();
11141158 WARN_ON (__hyp_check_page_state_range (phys , size , selftest_state .hyp ));
11151159 hyp_unlock_component ();
1160+
1161+ guest_lock_component (& selftest_vm );
1162+ WARN_ON (__guest_check_page_state_range (vcpu , ipa [0 ], size , selftest_state .guest [0 ]));
1163+ WARN_ON (__guest_check_page_state_range (vcpu , ipa [1 ], size , selftest_state .guest [1 ]));
1164+ guest_unlock_component (& selftest_vm );
11161165}
11171166
11181167#define assert_transition_res (res , fn , ...) \
@@ -1121,35 +1170,44 @@ static void assert_page_state(void)
11211170 assert_page_state(); \
11221171 } while (0)
11231172
1124- void pkvm_ownership_selftest (void )
1173+ void pkvm_ownership_selftest (void * base )
11251174{
1175+ enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_RWX ;
11261176 void * virt = hyp_alloc_pages (& host_s2_pool , 0 );
1127- u64 phys , size , pfn ;
1177+ struct pkvm_hyp_vcpu * vcpu = & selftest_vcpu ;
1178+ struct pkvm_hyp_vm * vm = & selftest_vm ;
1179+ u64 phys , size , pfn , gfn ;
11281180
11291181 WARN_ON (!virt );
11301182 selftest_page = hyp_virt_to_page (virt );
11311183 selftest_page -> refcount = 0 ;
1184+ init_selftest_vm (base );
11321185
11331186 size = PAGE_SIZE << selftest_page -> order ;
11341187 phys = hyp_virt_to_phys (virt );
11351188 pfn = hyp_phys_to_pfn (phys );
1189+ gfn = hyp_phys_to_pfn (selftest_ipa ());
11361190
11371191 selftest_state .host = PKVM_NOPAGE ;
11381192 selftest_state .hyp = PKVM_PAGE_OWNED ;
1193+ selftest_state .guest [0 ] = selftest_state .guest [1 ] = PKVM_NOPAGE ;
11391194 assert_page_state ();
11401195 assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
11411196 assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
11421197 assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
11431198 assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
11441199 assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
11451200 assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1201+ assert_transition_res (- EPERM , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1202+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
11461203
11471204 selftest_state .host = PKVM_PAGE_OWNED ;
11481205 selftest_state .hyp = PKVM_NOPAGE ;
11491206 assert_transition_res (0 , __pkvm_hyp_donate_host , pfn , 1 );
11501207 assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
11511208 assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
11521209 assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1210+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
11531211 assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
11541212
11551213 selftest_state .host = PKVM_PAGE_SHARED_OWNED ;
@@ -1159,6 +1217,8 @@ void pkvm_ownership_selftest(void)
11591217 assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
11601218 assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
11611219 assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1220+ assert_transition_res (- EPERM , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1221+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
11621222
11631223 assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
11641224 assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
@@ -1169,6 +1229,8 @@ void pkvm_ownership_selftest(void)
11691229 assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
11701230 assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
11711231 assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1232+ assert_transition_res (- EPERM , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1233+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
11721234
11731235 hyp_unpin_shared_mem (virt , virt + size );
11741236 assert_page_state ();
@@ -1186,13 +1248,37 @@ void pkvm_ownership_selftest(void)
11861248 assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
11871249 assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
11881250 assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1251+ assert_transition_res (- EPERM , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1252+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
11891253 assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
11901254
11911255 selftest_state .host = PKVM_PAGE_OWNED ;
11921256 selftest_state .hyp = PKVM_NOPAGE ;
11931257 assert_transition_res (0 , __pkvm_host_unshare_ffa , pfn , 1 );
11941258 assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
11951259
1260+ selftest_state .host = PKVM_PAGE_SHARED_OWNED ;
1261+ selftest_state .guest [0 ] = PKVM_PAGE_SHARED_BORROWED ;
1262+ assert_transition_res (0 , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1263+ assert_transition_res (- EPERM , __pkvm_host_share_guest , pfn , gfn , vcpu , prot );
1264+ assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1265+ assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1266+ assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1267+ assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1268+ assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1269+ assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1270+
1271+ selftest_state .guest [1 ] = PKVM_PAGE_SHARED_BORROWED ;
1272+ assert_transition_res (0 , __pkvm_host_share_guest , pfn , gfn + 1 , vcpu , prot );
1273+ WARN_ON (hyp_virt_to_page (virt )-> host_share_guest_count != 2 );
1274+
1275+ selftest_state .guest [0 ] = PKVM_NOPAGE ;
1276+ assert_transition_res (0 , __pkvm_host_unshare_guest , gfn , vm );
1277+
1278+ selftest_state .guest [1 ] = PKVM_NOPAGE ;
1279+ selftest_state .host = PKVM_PAGE_OWNED ;
1280+ assert_transition_res (0 , __pkvm_host_unshare_guest , gfn + 1 , vm );
1281+
11961282 selftest_state .host = PKVM_NOPAGE ;
11971283 selftest_state .hyp = PKVM_PAGE_OWNED ;
11981284 assert_transition_res (0 , __pkvm_host_donate_hyp , pfn , 1 );
0 commit comments