55 * Copyright (c) 2023 Google LLC.
66 *
77 * This test checks if the guest can see the same number of the PMU event
8- * counters (PMCR_EL0.N) that userspace sets.
8+ * counters (PMCR_EL0.N) that userspace sets, and if the guest can access
9+ * those counters.
910 * This test runs only when KVM_CAP_ARM_PMU_V3 is supported on the host.
1011 */
1112#include <kvm_util.h>
@@ -37,6 +38,255 @@ static void set_pmcr_n(uint64_t *pmcr, uint64_t pmcr_n)
3738 * pmcr |= (pmcr_n << ARMV8_PMU_PMCR_N_SHIFT );
3839}
3940
41+ /* Read PMEVTCNTR<n>_EL0 through PMXEVCNTR_EL0 */
42+ static inline unsigned long read_sel_evcntr (int sel )
43+ {
44+ write_sysreg (sel , pmselr_el0 );
45+ isb ();
46+ return read_sysreg (pmxevcntr_el0 );
47+ }
48+
49+ /* Write PMEVTCNTR<n>_EL0 through PMXEVCNTR_EL0 */
50+ static inline void write_sel_evcntr (int sel , unsigned long val )
51+ {
52+ write_sysreg (sel , pmselr_el0 );
53+ isb ();
54+ write_sysreg (val , pmxevcntr_el0 );
55+ isb ();
56+ }
57+
58+ /* Read PMEVTYPER<n>_EL0 through PMXEVTYPER_EL0 */
59+ static inline unsigned long read_sel_evtyper (int sel )
60+ {
61+ write_sysreg (sel , pmselr_el0 );
62+ isb ();
63+ return read_sysreg (pmxevtyper_el0 );
64+ }
65+
66+ /* Write PMEVTYPER<n>_EL0 through PMXEVTYPER_EL0 */
67+ static inline void write_sel_evtyper (int sel , unsigned long val )
68+ {
69+ write_sysreg (sel , pmselr_el0 );
70+ isb ();
71+ write_sysreg (val , pmxevtyper_el0 );
72+ isb ();
73+ }
74+
75+ static inline void enable_counter (int idx )
76+ {
77+ uint64_t v = read_sysreg (pmcntenset_el0 );
78+
79+ write_sysreg (BIT (idx ) | v , pmcntenset_el0 );
80+ isb ();
81+ }
82+
83+ static inline void disable_counter (int idx )
84+ {
85+ uint64_t v = read_sysreg (pmcntenset_el0 );
86+
87+ write_sysreg (BIT (idx ) | v , pmcntenclr_el0 );
88+ isb ();
89+ }
90+
91+ static void pmu_disable_reset (void )
92+ {
93+ uint64_t pmcr = read_sysreg (pmcr_el0 );
94+
95+ /* Reset all counters, disabling them */
96+ pmcr &= ~ARMV8_PMU_PMCR_E ;
97+ write_sysreg (pmcr | ARMV8_PMU_PMCR_P , pmcr_el0 );
98+ isb ();
99+ }
100+
101+ #define RETURN_READ_PMEVCNTRN (n ) \
102+ return read_sysreg(pmevcntr##n##_el0)
103+ static unsigned long read_pmevcntrn (int n )
104+ {
105+ PMEVN_SWITCH (n , RETURN_READ_PMEVCNTRN );
106+ return 0 ;
107+ }
108+
109+ #define WRITE_PMEVCNTRN (n ) \
110+ write_sysreg(val, pmevcntr##n##_el0)
111+ static void write_pmevcntrn (int n , unsigned long val )
112+ {
113+ PMEVN_SWITCH (n , WRITE_PMEVCNTRN );
114+ isb ();
115+ }
116+
117+ #define READ_PMEVTYPERN (n ) \
118+ return read_sysreg(pmevtyper##n##_el0)
119+ static unsigned long read_pmevtypern (int n )
120+ {
121+ PMEVN_SWITCH (n , READ_PMEVTYPERN );
122+ return 0 ;
123+ }
124+
125+ #define WRITE_PMEVTYPERN (n ) \
126+ write_sysreg(val, pmevtyper##n##_el0)
127+ static void write_pmevtypern (int n , unsigned long val )
128+ {
129+ PMEVN_SWITCH (n , WRITE_PMEVTYPERN );
130+ isb ();
131+ }
132+
133+ /*
134+ * The pmc_accessor structure has pointers to PMEV{CNTR,TYPER}<n>_EL0
135+ * accessors that test cases will use. Each of the accessors will
136+ * either directly reads/writes PMEV{CNTR,TYPER}<n>_EL0
137+ * (i.e. {read,write}_pmev{cnt,type}rn()), or reads/writes them through
138+ * PMXEV{CNTR,TYPER}_EL0 (i.e. {read,write}_sel_ev{cnt,type}r()).
139+ *
140+ * This is used to test that combinations of those accessors provide
141+ * the consistent behavior.
142+ */
143+ struct pmc_accessor {
144+ /* A function to be used to read PMEVTCNTR<n>_EL0 */
145+ unsigned long (* read_cntr )(int idx );
146+ /* A function to be used to write PMEVTCNTR<n>_EL0 */
147+ void (* write_cntr )(int idx , unsigned long val );
148+ /* A function to be used to read PMEVTYPER<n>_EL0 */
149+ unsigned long (* read_typer )(int idx );
150+ /* A function to be used to write PMEVTYPER<n>_EL0 */
151+ void (* write_typer )(int idx , unsigned long val );
152+ };
153+
154+ struct pmc_accessor pmc_accessors [] = {
155+ /* test with all direct accesses */
156+ { read_pmevcntrn , write_pmevcntrn , read_pmevtypern , write_pmevtypern },
157+ /* test with all indirect accesses */
158+ { read_sel_evcntr , write_sel_evcntr , read_sel_evtyper , write_sel_evtyper },
159+ /* read with direct accesses, and write with indirect accesses */
160+ { read_pmevcntrn , write_sel_evcntr , read_pmevtypern , write_sel_evtyper },
161+ /* read with indirect accesses, and write with direct accesses */
162+ { read_sel_evcntr , write_pmevcntrn , read_sel_evtyper , write_pmevtypern },
163+ };
164+
165+ /*
166+ * Convert a pointer of pmc_accessor to an index in pmc_accessors[],
167+ * assuming that the pointer is one of the entries in pmc_accessors[].
168+ */
169+ #define PMC_ACC_TO_IDX (acc ) (acc - &pmc_accessors[0])
170+
171+ #define GUEST_ASSERT_BITMAP_REG (regname , mask , set_expected ) \
172+ { \
173+ uint64_t _tval = read_sysreg(regname); \
174+ \
175+ if (set_expected) \
176+ __GUEST_ASSERT((_tval & mask), \
177+ "tval: 0x%lx; mask: 0x%lx; set_expected: 0x%lx", \
178+ _tval, mask, set_expected); \
179+ else \
180+ __GUEST_ASSERT(!(_tval & mask), \
181+ "tval: 0x%lx; mask: 0x%lx; set_expected: 0x%lx", \
182+ _tval, mask, set_expected); \
183+ }
184+
185+ /*
186+ * Check if @mask bits in {PMCNTEN,PMINTEN,PMOVS}{SET,CLR} registers
187+ * are set or cleared as specified in @set_expected.
188+ */
189+ static void check_bitmap_pmu_regs (uint64_t mask , bool set_expected )
190+ {
191+ GUEST_ASSERT_BITMAP_REG (pmcntenset_el0 , mask , set_expected );
192+ GUEST_ASSERT_BITMAP_REG (pmcntenclr_el0 , mask , set_expected );
193+ GUEST_ASSERT_BITMAP_REG (pmintenset_el1 , mask , set_expected );
194+ GUEST_ASSERT_BITMAP_REG (pmintenclr_el1 , mask , set_expected );
195+ GUEST_ASSERT_BITMAP_REG (pmovsset_el0 , mask , set_expected );
196+ GUEST_ASSERT_BITMAP_REG (pmovsclr_el0 , mask , set_expected );
197+ }
198+
199+ /*
200+ * Check if the bit in {PMCNTEN,PMINTEN,PMOVS}{SET,CLR} registers corresponding
201+ * to the specified counter (@pmc_idx) can be read/written as expected.
202+ * When @set_op is true, it tries to set the bit for the counter in
203+ * those registers by writing the SET registers (the bit won't be set
204+ * if the counter is not implemented though).
205+ * Otherwise, it tries to clear the bits in the registers by writing
206+ * the CLR registers.
207+ * Then, it checks if the values indicated in the registers are as expected.
208+ */
209+ static void test_bitmap_pmu_regs (int pmc_idx , bool set_op )
210+ {
211+ uint64_t pmcr_n , test_bit = BIT (pmc_idx );
212+ bool set_expected = false;
213+
214+ if (set_op ) {
215+ write_sysreg (test_bit , pmcntenset_el0 );
216+ write_sysreg (test_bit , pmintenset_el1 );
217+ write_sysreg (test_bit , pmovsset_el0 );
218+
219+ /* The bit will be set only if the counter is implemented */
220+ pmcr_n = get_pmcr_n (read_sysreg (pmcr_el0 ));
221+ set_expected = (pmc_idx < pmcr_n ) ? true : false;
222+ } else {
223+ write_sysreg (test_bit , pmcntenclr_el0 );
224+ write_sysreg (test_bit , pmintenclr_el1 );
225+ write_sysreg (test_bit , pmovsclr_el0 );
226+ }
227+ check_bitmap_pmu_regs (test_bit , set_expected );
228+ }
229+
230+ /*
231+ * Tests for reading/writing registers for the (implemented) event counter
232+ * specified by @pmc_idx.
233+ */
234+ static void test_access_pmc_regs (struct pmc_accessor * acc , int pmc_idx )
235+ {
236+ uint64_t write_data , read_data ;
237+
238+ /* Disable all PMCs and reset all PMCs to zero. */
239+ pmu_disable_reset ();
240+
241+ /*
242+ * Tests for reading/writing {PMCNTEN,PMINTEN,PMOVS}{SET,CLR}_EL1.
243+ */
244+
245+ /* Make sure that the bit in those registers are set to 0 */
246+ test_bitmap_pmu_regs (pmc_idx , false);
247+ /* Test if setting the bit in those registers works */
248+ test_bitmap_pmu_regs (pmc_idx , true);
249+ /* Test if clearing the bit in those registers works */
250+ test_bitmap_pmu_regs (pmc_idx , false);
251+
252+ /*
253+ * Tests for reading/writing the event type register.
254+ */
255+
256+ /*
257+ * Set the event type register to an arbitrary value just for testing
258+ * of reading/writing the register.
259+ * Arm ARM says that for the event from 0x0000 to 0x003F,
260+ * the value indicated in the PMEVTYPER<n>_EL0.evtCount field is
261+ * the value written to the field even when the specified event
262+ * is not supported.
263+ */
264+ write_data = (ARMV8_PMU_EXCLUDE_EL1 | ARMV8_PMUV3_PERFCTR_INST_RETIRED );
265+ acc -> write_typer (pmc_idx , write_data );
266+ read_data = acc -> read_typer (pmc_idx );
267+ __GUEST_ASSERT (read_data == write_data ,
268+ "pmc_idx: 0x%lx; acc_idx: 0x%lx; read_data: 0x%lx; write_data: 0x%lx" ,
269+ pmc_idx , PMC_ACC_TO_IDX (acc ), read_data , write_data );
270+
271+ /*
272+ * Tests for reading/writing the event count register.
273+ */
274+
275+ read_data = acc -> read_cntr (pmc_idx );
276+
277+ /* The count value must be 0, as it is disabled and reset */
278+ __GUEST_ASSERT (read_data == 0 ,
279+ "pmc_idx: 0x%lx; acc_idx: 0x%lx; read_data: 0x%lx" ,
280+ pmc_idx , PMC_ACC_TO_IDX (acc ), read_data );
281+
282+ write_data = read_data + pmc_idx + 0x12345 ;
283+ acc -> write_cntr (pmc_idx , write_data );
284+ read_data = acc -> read_cntr (pmc_idx );
285+ __GUEST_ASSERT (read_data == write_data ,
286+ "pmc_idx: 0x%lx; acc_idx: 0x%lx; read_data: 0x%lx; write_data: 0x%lx" ,
287+ pmc_idx , PMC_ACC_TO_IDX (acc ), read_data , write_data );
288+ }
289+
40290static void guest_sync_handler (struct ex_regs * regs )
41291{
42292 uint64_t esr , ec ;
@@ -49,11 +299,14 @@ static void guest_sync_handler(struct ex_regs *regs)
49299/*
50300 * The guest is configured with PMUv3 with @expected_pmcr_n number of
51301 * event counters.
52- * Check if @expected_pmcr_n is consistent with PMCR_EL0.N.
302+ * Check if @expected_pmcr_n is consistent with PMCR_EL0.N, and
303+ * if reading/writing PMU registers for implemented counters works
304+ * as expected.
53305 */
54306static void guest_code (uint64_t expected_pmcr_n )
55307{
56308 uint64_t pmcr , pmcr_n ;
309+ int i , pmc ;
57310
58311 __GUEST_ASSERT (expected_pmcr_n <= ARMV8_PMU_MAX_GENERAL_COUNTERS ,
59312 "Expected PMCR.N: 0x%lx; ARMv8 general counters: 0x%lx" ,
@@ -67,6 +320,15 @@ static void guest_code(uint64_t expected_pmcr_n)
67320 "Expected PMCR.N: 0x%lx, PMCR.N: 0x%lx" ,
68321 expected_pmcr_n , pmcr_n );
69322
323+ /*
324+ * Tests for reading/writing PMU registers for implemented counters.
325+ * Use each combination of PMEVT{CNTR,TYPER}<n>_EL0 accessor functions.
326+ */
327+ for (i = 0 ; i < ARRAY_SIZE (pmc_accessors ); i ++ ) {
328+ for (pmc = 0 ; pmc < pmcr_n ; pmc ++ )
329+ test_access_pmc_regs (& pmc_accessors [i ], pmc );
330+ }
331+
70332 GUEST_DONE ();
71333}
72334
@@ -179,7 +441,7 @@ static void test_create_vpmu_vm_with_pmcr_n(uint64_t pmcr_n, bool expect_fail)
179441 * Create a guest with one vCPU, set the PMCR_EL0.N for the vCPU to @pmcr_n,
180442 * and run the test.
181443 */
182- static void run_test (uint64_t pmcr_n )
444+ static void run_access_test (uint64_t pmcr_n )
183445{
184446 uint64_t sp ;
185447 struct kvm_vcpu * vcpu ;
@@ -246,7 +508,7 @@ int main(void)
246508
247509 pmcr_n = get_pmcr_n_limit ();
248510 for (i = 0 ; i <= pmcr_n ; i ++ )
249- run_test (i );
511+ run_access_test (i );
250512
251513 for (i = pmcr_n + 1 ; i < ARMV8_PMU_MAX_COUNTERS ; i ++ )
252514 run_error_test (i );
0 commit comments