@@ -1192,35 +1192,6 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range,
1192
1192
return flush ;
1193
1193
}
1194
1194
1195
- typedef bool (* tdp_handler_t )(struct kvm * kvm , struct tdp_iter * iter ,
1196
- struct kvm_gfn_range * range );
1197
-
1198
- static __always_inline bool kvm_tdp_mmu_handle_gfn (struct kvm * kvm ,
1199
- struct kvm_gfn_range * range ,
1200
- tdp_handler_t handler )
1201
- {
1202
- struct kvm_mmu_page * root ;
1203
- struct tdp_iter iter ;
1204
- bool ret = false;
1205
-
1206
- /*
1207
- * Don't support rescheduling, none of the MMU notifiers that funnel
1208
- * into this helper allow blocking; it'd be dead, wasteful code. Note,
1209
- * this helper must NOT be used to unmap GFNs, as it processes only
1210
- * valid roots!
1211
- */
1212
- for_each_valid_tdp_mmu_root (kvm , root , range -> slot -> as_id ) {
1213
- rcu_read_lock ();
1214
-
1215
- tdp_root_for_each_leaf_pte (iter , root , range -> start , range -> end )
1216
- ret |= handler (kvm , & iter , range );
1217
-
1218
- rcu_read_unlock ();
1219
- }
1220
-
1221
- return ret ;
1222
- }
1223
-
1224
1195
/*
1225
1196
* Mark the SPTEs range of GFNs [start, end) unaccessed and return non-zero
1226
1197
* if any of the GFNs in the range have been accessed.
@@ -1229,15 +1200,10 @@ static __always_inline bool kvm_tdp_mmu_handle_gfn(struct kvm *kvm,
1229
1200
* from the clear_young() or clear_flush_young() notifier, which uses the
1230
1201
* return value to determine if the page has been accessed.
1231
1202
*/
1232
- static bool age_gfn_range (struct kvm * kvm , struct tdp_iter * iter ,
1233
- struct kvm_gfn_range * range )
1203
+ static void kvm_tdp_mmu_age_spte (struct tdp_iter * iter )
1234
1204
{
1235
1205
u64 new_spte ;
1236
1206
1237
- /* If we have a non-accessed entry we don't need to change the pte. */
1238
- if (!is_accessed_spte (iter -> old_spte ))
1239
- return false;
1240
-
1241
1207
if (spte_ad_enabled (iter -> old_spte )) {
1242
1208
iter -> old_spte = tdp_mmu_clear_spte_bits (iter -> sptep ,
1243
1209
iter -> old_spte ,
@@ -1253,23 +1219,48 @@ static bool age_gfn_range(struct kvm *kvm, struct tdp_iter *iter,
1253
1219
1254
1220
trace_kvm_tdp_mmu_spte_changed (iter -> as_id , iter -> gfn , iter -> level ,
1255
1221
iter -> old_spte , new_spte );
1256
- return true;
1257
1222
}
1258
1223
1259
- bool kvm_tdp_mmu_age_gfn_range (struct kvm * kvm , struct kvm_gfn_range * range )
1224
+ static bool __kvm_tdp_mmu_age_gfn_range (struct kvm * kvm ,
1225
+ struct kvm_gfn_range * range ,
1226
+ bool test_only )
1260
1227
{
1261
- return kvm_tdp_mmu_handle_gfn (kvm , range , age_gfn_range );
1228
+ struct kvm_mmu_page * root ;
1229
+ struct tdp_iter iter ;
1230
+ bool ret = false;
1231
+
1232
+ /*
1233
+ * Don't support rescheduling, none of the MMU notifiers that funnel
1234
+ * into this helper allow blocking; it'd be dead, wasteful code. Note,
1235
+ * this helper must NOT be used to unmap GFNs, as it processes only
1236
+ * valid roots!
1237
+ */
1238
+ for_each_valid_tdp_mmu_root (kvm , root , range -> slot -> as_id ) {
1239
+ guard (rcu )();
1240
+
1241
+ tdp_root_for_each_leaf_pte (iter , root , range -> start , range -> end ) {
1242
+ if (!is_accessed_spte (iter .old_spte ))
1243
+ continue ;
1244
+
1245
+ if (test_only )
1246
+ return true;
1247
+
1248
+ ret = true;
1249
+ kvm_tdp_mmu_age_spte (& iter );
1250
+ }
1251
+ }
1252
+
1253
+ return ret ;
1262
1254
}
1263
1255
1264
- static bool test_age_gfn (struct kvm * kvm , struct tdp_iter * iter ,
1265
- struct kvm_gfn_range * range )
1256
+ bool kvm_tdp_mmu_age_gfn_range (struct kvm * kvm , struct kvm_gfn_range * range )
1266
1257
{
1267
- return is_accessed_spte ( iter -> old_spte );
1258
+ return __kvm_tdp_mmu_age_gfn_range ( kvm , range , false );
1268
1259
}
1269
1260
1270
1261
bool kvm_tdp_mmu_test_age_gfn (struct kvm * kvm , struct kvm_gfn_range * range )
1271
1262
{
1272
- return kvm_tdp_mmu_handle_gfn (kvm , range , test_age_gfn );
1263
+ return __kvm_tdp_mmu_age_gfn_range (kvm , range , true );
1273
1264
}
1274
1265
1275
1266
/*
0 commit comments