@@ -120,6 +120,8 @@ enum m1_pmu_events {
120
120
*/
121
121
M1_PMU_CFG_COUNT_USER = BIT (8 ),
122
122
M1_PMU_CFG_COUNT_KERNEL = BIT (9 ),
123
+ M1_PMU_CFG_COUNT_HOST = BIT (10 ),
124
+ M1_PMU_CFG_COUNT_GUEST = BIT (11 ),
123
125
};
124
126
125
127
/*
@@ -327,11 +329,10 @@ static void m1_pmu_disable_counter_interrupt(unsigned int index)
327
329
__m1_pmu_enable_counter_interrupt (index , false);
328
330
}
329
331
330
- static void m1_pmu_configure_counter (unsigned int index , u8 event ,
331
- bool user , bool kernel )
332
+ static void __m1_pmu_configure_event_filter (unsigned int index , bool user ,
333
+ bool kernel , bool host )
332
334
{
333
- u64 val , user_bit , kernel_bit ;
334
- int shift ;
335
+ u64 clear , set , user_bit , kernel_bit ;
335
336
336
337
switch (index ) {
337
338
case 0 ... 7 :
@@ -346,19 +347,27 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
346
347
BUG ();
347
348
}
348
349
349
- val = read_sysreg_s (SYS_IMP_APL_PMCR1_EL1 );
350
-
350
+ clear = set = 0 ;
351
351
if (user )
352
- val |= user_bit ;
352
+ set |= user_bit ;
353
353
else
354
- val &= ~ user_bit ;
354
+ clear |= user_bit ;
355
355
356
356
if (kernel )
357
- val |= kernel_bit ;
357
+ set |= kernel_bit ;
358
358
else
359
- val &= ~ kernel_bit ;
359
+ clear |= kernel_bit ;
360
360
361
- write_sysreg_s (val , SYS_IMP_APL_PMCR1_EL1 );
361
+ if (host )
362
+ sysreg_clear_set_s (SYS_IMP_APL_PMCR1_EL1 , clear , set );
363
+ else if (is_kernel_in_hyp_mode ())
364
+ sysreg_clear_set_s (SYS_IMP_APL_PMCR1_EL12 , clear , set );
365
+ }
366
+
367
+ static void __m1_pmu_configure_eventsel (unsigned int index , u8 event )
368
+ {
369
+ u64 clear = 0 , set = 0 ;
370
+ int shift ;
362
371
363
372
/*
364
373
* Counters 0 and 1 have fixed events. For anything else,
@@ -371,21 +380,32 @@ static void m1_pmu_configure_counter(unsigned int index, u8 event,
371
380
break ;
372
381
case 2 ... 5 :
373
382
shift = (index - 2 ) * 8 ;
374
- val = read_sysreg_s (SYS_IMP_APL_PMESR0_EL1 );
375
- val &= ~((u64 )0xff << shift );
376
- val |= (u64 )event << shift ;
377
- write_sysreg_s (val , SYS_IMP_APL_PMESR0_EL1 );
383
+ clear |= (u64 )0xff << shift ;
384
+ set |= (u64 )event << shift ;
385
+ sysreg_clear_set_s (SYS_IMP_APL_PMESR0_EL1 , clear , set );
378
386
break ;
379
387
case 6 ... 9 :
380
388
shift = (index - 6 ) * 8 ;
381
- val = read_sysreg_s (SYS_IMP_APL_PMESR1_EL1 );
382
- val &= ~((u64 )0xff << shift );
383
- val |= (u64 )event << shift ;
384
- write_sysreg_s (val , SYS_IMP_APL_PMESR1_EL1 );
389
+ clear |= (u64 )0xff << shift ;
390
+ set |= (u64 )event << shift ;
391
+ sysreg_clear_set_s (SYS_IMP_APL_PMESR1_EL1 , clear , set );
385
392
break ;
386
393
}
387
394
}
388
395
396
+ static void m1_pmu_configure_counter (unsigned int index , unsigned long config_base )
397
+ {
398
+ bool kernel = config_base & M1_PMU_CFG_COUNT_KERNEL ;
399
+ bool guest = config_base & M1_PMU_CFG_COUNT_GUEST ;
400
+ bool host = config_base & M1_PMU_CFG_COUNT_HOST ;
401
+ bool user = config_base & M1_PMU_CFG_COUNT_USER ;
402
+ u8 evt = config_base & M1_PMU_CFG_EVENT ;
403
+
404
+ __m1_pmu_configure_event_filter (index , user && host , kernel && host , true);
405
+ __m1_pmu_configure_event_filter (index , user && guest , kernel && guest , false);
406
+ __m1_pmu_configure_eventsel (index , evt );
407
+ }
408
+
389
409
/* arm_pmu backend */
390
410
static void m1_pmu_enable_event (struct perf_event * event )
391
411
{
@@ -396,7 +416,7 @@ static void m1_pmu_enable_event(struct perf_event *event)
396
416
user = event -> hw .config_base & M1_PMU_CFG_COUNT_USER ;
397
417
kernel = event -> hw .config_base & M1_PMU_CFG_COUNT_KERNEL ;
398
418
399
- m1_pmu_configure_counter (event -> hw .idx , evt , user , kernel );
419
+ m1_pmu_configure_counter (event -> hw .idx , event -> hw . config_base );
400
420
m1_pmu_enable_counter (event -> hw .idx );
401
421
m1_pmu_enable_counter_interrupt (event -> hw .idx );
402
422
isb ();
@@ -554,14 +574,18 @@ static int m1_pmu_set_event_filter(struct hw_perf_event *event,
554
574
{
555
575
unsigned long config_base = 0 ;
556
576
557
- if (!attr -> exclude_guest ) {
577
+ if (!attr -> exclude_guest && ! is_kernel_in_hyp_mode () ) {
558
578
pr_debug ("ARM performance counters do not support mode exclusion\n" );
559
579
return - EOPNOTSUPP ;
560
580
}
561
581
if (!attr -> exclude_kernel )
562
582
config_base |= M1_PMU_CFG_COUNT_KERNEL ;
563
583
if (!attr -> exclude_user )
564
584
config_base |= M1_PMU_CFG_COUNT_USER ;
585
+ if (!attr -> exclude_host )
586
+ config_base |= M1_PMU_CFG_COUNT_HOST ;
587
+ if (!attr -> exclude_guest )
588
+ config_base |= M1_PMU_CFG_COUNT_GUEST ;
565
589
566
590
event -> config_base = config_base ;
567
591
0 commit comments