@@ -1095,16 +1095,60 @@ int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu)
1095
1095
struct pkvm_expected_state {
1096
1096
enum pkvm_page_state host ;
1097
1097
enum pkvm_page_state hyp ;
1098
+ enum pkvm_page_state guest [2 ]; /* [ gfn, gfn + 1 ] */
1098
1099
};
1099
1100
1100
1101
static struct pkvm_expected_state selftest_state ;
1101
1102
static struct hyp_page * selftest_page ;
1102
1103
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
+
1103
1145
static void assert_page_state (void )
1104
1146
{
1105
1147
void * virt = hyp_page_to_virt (selftest_page );
1106
1148
u64 size = PAGE_SIZE << selftest_page -> order ;
1149
+ struct pkvm_hyp_vcpu * vcpu = & selftest_vcpu ;
1107
1150
u64 phys = hyp_virt_to_phys (virt );
1151
+ u64 ipa [2 ] = { selftest_ipa (), selftest_ipa () + PAGE_SIZE };
1108
1152
1109
1153
host_lock_component ();
1110
1154
WARN_ON (__host_check_page_state_range (phys , size , selftest_state .host ));
@@ -1113,6 +1157,11 @@ static void assert_page_state(void)
1113
1157
hyp_lock_component ();
1114
1158
WARN_ON (__hyp_check_page_state_range (phys , size , selftest_state .hyp ));
1115
1159
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 );
1116
1165
}
1117
1166
1118
1167
#define assert_transition_res (res , fn , ...) \
@@ -1121,35 +1170,44 @@ static void assert_page_state(void)
1121
1170
assert_page_state(); \
1122
1171
} while (0)
1123
1172
1124
- void pkvm_ownership_selftest (void )
1173
+ void pkvm_ownership_selftest (void * base )
1125
1174
{
1175
+ enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_RWX ;
1126
1176
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 ;
1128
1180
1129
1181
WARN_ON (!virt );
1130
1182
selftest_page = hyp_virt_to_page (virt );
1131
1183
selftest_page -> refcount = 0 ;
1184
+ init_selftest_vm (base );
1132
1185
1133
1186
size = PAGE_SIZE << selftest_page -> order ;
1134
1187
phys = hyp_virt_to_phys (virt );
1135
1188
pfn = hyp_phys_to_pfn (phys );
1189
+ gfn = hyp_phys_to_pfn (selftest_ipa ());
1136
1190
1137
1191
selftest_state .host = PKVM_NOPAGE ;
1138
1192
selftest_state .hyp = PKVM_PAGE_OWNED ;
1193
+ selftest_state .guest [0 ] = selftest_state .guest [1 ] = PKVM_NOPAGE ;
1139
1194
assert_page_state ();
1140
1195
assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1141
1196
assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1142
1197
assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1143
1198
assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1144
1199
assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1145
1200
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 );
1146
1203
1147
1204
selftest_state .host = PKVM_PAGE_OWNED ;
1148
1205
selftest_state .hyp = PKVM_NOPAGE ;
1149
1206
assert_transition_res (0 , __pkvm_hyp_donate_host , pfn , 1 );
1150
1207
assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1151
1208
assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1152
1209
assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1210
+ assert_transition_res (- ENOENT , __pkvm_host_unshare_guest , gfn , vm );
1153
1211
assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1154
1212
1155
1213
selftest_state .host = PKVM_PAGE_SHARED_OWNED ;
@@ -1159,6 +1217,8 @@ void pkvm_ownership_selftest(void)
1159
1217
assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1160
1218
assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1161
1219
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 );
1162
1222
1163
1223
assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
1164
1224
assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
@@ -1169,6 +1229,8 @@ void pkvm_ownership_selftest(void)
1169
1229
assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1170
1230
assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1171
1231
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 );
1172
1234
1173
1235
hyp_unpin_shared_mem (virt , virt + size );
1174
1236
assert_page_state ();
@@ -1186,13 +1248,37 @@ void pkvm_ownership_selftest(void)
1186
1248
assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1187
1249
assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1188
1250
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 );
1189
1253
assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1190
1254
1191
1255
selftest_state .host = PKVM_PAGE_OWNED ;
1192
1256
selftest_state .hyp = PKVM_NOPAGE ;
1193
1257
assert_transition_res (0 , __pkvm_host_unshare_ffa , pfn , 1 );
1194
1258
assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1195
1259
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
+
1196
1282
selftest_state .host = PKVM_NOPAGE ;
1197
1283
selftest_state .hyp = PKVM_PAGE_OWNED ;
1198
1284
assert_transition_res (0 , __pkvm_host_donate_hyp , pfn , 1 );
0 commit comments