@@ -294,10 +294,99 @@ static int cat_run_test(const struct resctrl_test *test, const struct user_param
294
294
return ret ;
295
295
}
296
296
297
+ static int noncont_cat_run_test (const struct resctrl_test * test ,
298
+ const struct user_params * uparams )
299
+ {
300
+ unsigned long full_cache_mask , cont_mask , noncont_mask ;
301
+ unsigned int eax , ebx , ecx , edx , sparse_masks ;
302
+ int bit_center , ret ;
303
+ char schemata [64 ];
304
+
305
+ /* Check to compare sparse_masks content to CPUID output. */
306
+ ret = resource_info_unsigned_get (test -> resource , "sparse_masks" , & sparse_masks );
307
+ if (ret )
308
+ return ret ;
309
+
310
+ if (!strcmp (test -> resource , "L3" ))
311
+ __cpuid_count (0x10 , 1 , eax , ebx , ecx , edx );
312
+ else if (!strcmp (test -> resource , "L2" ))
313
+ __cpuid_count (0x10 , 2 , eax , ebx , ecx , edx );
314
+ else
315
+ return - EINVAL ;
316
+
317
+ if (sparse_masks != ((ecx >> 3 ) & 1 )) {
318
+ ksft_print_msg ("CPUID output doesn't match 'sparse_masks' file content!\n" );
319
+ return 1 ;
320
+ }
321
+
322
+ /* Write checks initialization. */
323
+ ret = get_full_cbm (test -> resource , & full_cache_mask );
324
+ if (ret < 0 )
325
+ return ret ;
326
+ bit_center = count_bits (full_cache_mask ) / 2 ;
327
+
328
+ /*
329
+ * The bit_center needs to be at least 3 to properly calculate the CBM
330
+ * hole in the noncont_mask. If it's smaller return an error since the
331
+ * cache mask is too short and that shouldn't happen.
332
+ */
333
+ if (bit_center < 3 )
334
+ return - EINVAL ;
335
+ cont_mask = full_cache_mask >> bit_center ;
336
+
337
+ /* Contiguous mask write check. */
338
+ snprintf (schemata , sizeof (schemata ), "%lx" , cont_mask );
339
+ ret = write_schemata ("" , schemata , uparams -> cpu , test -> resource );
340
+ if (ret ) {
341
+ ksft_print_msg ("Write of contiguous CBM failed\n" );
342
+ return 1 ;
343
+ }
344
+
345
+ /*
346
+ * Non-contiguous mask write check. CBM has a 0xf hole approximately in the middle.
347
+ * Output is compared with support information to catch any edge case errors.
348
+ */
349
+ noncont_mask = ~(0xfUL << (bit_center - 2 )) & full_cache_mask ;
350
+ snprintf (schemata , sizeof (schemata ), "%lx" , noncont_mask );
351
+ ret = write_schemata ("" , schemata , uparams -> cpu , test -> resource );
352
+ if (ret && sparse_masks )
353
+ ksft_print_msg ("Non-contiguous CBMs supported but write of non-contiguous CBM failed\n" );
354
+ else if (ret && !sparse_masks )
355
+ ksft_print_msg ("Non-contiguous CBMs not supported and write of non-contiguous CBM failed as expected\n" );
356
+ else if (!ret && !sparse_masks )
357
+ ksft_print_msg ("Non-contiguous CBMs not supported but write of non-contiguous CBM succeeded\n" );
358
+
359
+ return !ret == !sparse_masks ;
360
+ }
361
+
362
+ static bool noncont_cat_feature_check (const struct resctrl_test * test )
363
+ {
364
+ if (!resctrl_resource_exists (test -> resource ))
365
+ return false;
366
+
367
+ return resource_info_file_exists (test -> resource , "sparse_masks" );
368
+ }
369
+
297
370
struct resctrl_test l3_cat_test = {
298
371
.name = "L3_CAT" ,
299
372
.group = "CAT" ,
300
373
.resource = "L3" ,
301
374
.feature_check = test_resource_feature_check ,
302
375
.run_test = cat_run_test ,
303
376
};
377
+
378
+ struct resctrl_test l3_noncont_cat_test = {
379
+ .name = "L3_NONCONT_CAT" ,
380
+ .group = "CAT" ,
381
+ .resource = "L3" ,
382
+ .feature_check = noncont_cat_feature_check ,
383
+ .run_test = noncont_cat_run_test ,
384
+ };
385
+
386
+ struct resctrl_test l2_noncont_cat_test = {
387
+ .name = "L2_NONCONT_CAT" ,
388
+ .group = "CAT" ,
389
+ .resource = "L2" ,
390
+ .feature_check = noncont_cat_feature_check ,
391
+ .run_test = noncont_cat_run_test ,
392
+ };
0 commit comments