@@ -1090,3 +1090,114 @@ int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu)
1090
1090
1091
1091
return 0 ;
1092
1092
}
1093
+
1094
+ #ifdef CONFIG_NVHE_EL2_DEBUG
1095
+ struct pkvm_expected_state {
1096
+ enum pkvm_page_state host ;
1097
+ enum pkvm_page_state hyp ;
1098
+ };
1099
+
1100
+ static struct pkvm_expected_state selftest_state ;
1101
+ static struct hyp_page * selftest_page ;
1102
+
1103
+ static void assert_page_state (void )
1104
+ {
1105
+ void * virt = hyp_page_to_virt (selftest_page );
1106
+ u64 size = PAGE_SIZE << selftest_page -> order ;
1107
+ u64 phys = hyp_virt_to_phys (virt );
1108
+
1109
+ host_lock_component ();
1110
+ WARN_ON (__host_check_page_state_range (phys , size , selftest_state .host ));
1111
+ host_unlock_component ();
1112
+
1113
+ hyp_lock_component ();
1114
+ WARN_ON (__hyp_check_page_state_range (phys , size , selftest_state .hyp ));
1115
+ hyp_unlock_component ();
1116
+ }
1117
+
1118
+ #define assert_transition_res (res , fn , ...) \
1119
+ do { \
1120
+ WARN_ON(fn(__VA_ARGS__) != res); \
1121
+ assert_page_state(); \
1122
+ } while (0)
1123
+
1124
+ void pkvm_ownership_selftest (void )
1125
+ {
1126
+ void * virt = hyp_alloc_pages (& host_s2_pool , 0 );
1127
+ u64 phys , size , pfn ;
1128
+
1129
+ WARN_ON (!virt );
1130
+ selftest_page = hyp_virt_to_page (virt );
1131
+ selftest_page -> refcount = 0 ;
1132
+
1133
+ size = PAGE_SIZE << selftest_page -> order ;
1134
+ phys = hyp_virt_to_phys (virt );
1135
+ pfn = hyp_phys_to_pfn (phys );
1136
+
1137
+ selftest_state .host = PKVM_NOPAGE ;
1138
+ selftest_state .hyp = PKVM_PAGE_OWNED ;
1139
+ assert_page_state ();
1140
+ assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1141
+ assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1142
+ assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1143
+ assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1144
+ assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1145
+ assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1146
+
1147
+ selftest_state .host = PKVM_PAGE_OWNED ;
1148
+ selftest_state .hyp = PKVM_NOPAGE ;
1149
+ assert_transition_res (0 , __pkvm_hyp_donate_host , pfn , 1 );
1150
+ assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1151
+ assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1152
+ assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1153
+ assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1154
+
1155
+ selftest_state .host = PKVM_PAGE_SHARED_OWNED ;
1156
+ selftest_state .hyp = PKVM_PAGE_SHARED_BORROWED ;
1157
+ assert_transition_res (0 , __pkvm_host_share_hyp , pfn );
1158
+ assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1159
+ assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1160
+ assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1161
+ assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1162
+
1163
+ assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
1164
+ assert_transition_res (0 , hyp_pin_shared_mem , virt , virt + size );
1165
+ hyp_unpin_shared_mem (virt , virt + size );
1166
+ WARN_ON (hyp_page_count (virt ) != 1 );
1167
+ assert_transition_res (- EBUSY , __pkvm_host_unshare_hyp , pfn );
1168
+ assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1169
+ assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1170
+ assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1171
+ assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1172
+
1173
+ hyp_unpin_shared_mem (virt , virt + size );
1174
+ assert_page_state ();
1175
+ WARN_ON (hyp_page_count (virt ));
1176
+
1177
+ selftest_state .host = PKVM_PAGE_OWNED ;
1178
+ selftest_state .hyp = PKVM_NOPAGE ;
1179
+ assert_transition_res (0 , __pkvm_host_unshare_hyp , pfn );
1180
+
1181
+ selftest_state .host = PKVM_PAGE_SHARED_OWNED ;
1182
+ selftest_state .hyp = PKVM_NOPAGE ;
1183
+ assert_transition_res (0 , __pkvm_host_share_ffa , pfn , 1 );
1184
+ assert_transition_res (- EPERM , __pkvm_host_share_ffa , pfn , 1 );
1185
+ assert_transition_res (- EPERM , __pkvm_host_donate_hyp , pfn , 1 );
1186
+ assert_transition_res (- EPERM , __pkvm_host_share_hyp , pfn );
1187
+ assert_transition_res (- EPERM , __pkvm_host_unshare_hyp , pfn );
1188
+ assert_transition_res (- EPERM , __pkvm_hyp_donate_host , pfn , 1 );
1189
+ assert_transition_res (- EPERM , hyp_pin_shared_mem , virt , virt + size );
1190
+
1191
+ selftest_state .host = PKVM_PAGE_OWNED ;
1192
+ selftest_state .hyp = PKVM_NOPAGE ;
1193
+ assert_transition_res (0 , __pkvm_host_unshare_ffa , pfn , 1 );
1194
+ assert_transition_res (- EPERM , __pkvm_host_unshare_ffa , pfn , 1 );
1195
+
1196
+ selftest_state .host = PKVM_NOPAGE ;
1197
+ selftest_state .hyp = PKVM_PAGE_OWNED ;
1198
+ assert_transition_res (0 , __pkvm_host_donate_hyp , pfn , 1 );
1199
+
1200
+ selftest_page -> refcount = 1 ;
1201
+ hyp_put_page (& host_s2_pool , virt );
1202
+ }
1203
+ #endif
0 commit comments