1/* 2 * Copyright 2014, Michael Ellerman, IBM Corp. 3 * Licensed under GPLv2. 4 */ 5 6#include <sched.h> 7#include <signal.h> 8#include <stdbool.h> 9#include <stdio.h> 10#include <stdlib.h> 11 12#include "ebb.h" 13 14 15/* 16 * Test that the kernel properly handles PMAE across context switches. 17 * 18 * We test this by calling into the kernel inside our EBB handler, where PMAE 19 * is clear. A cpu eater companion thread is running on the same CPU as us to 20 * encourage the scheduler to switch us. 21 * 22 * The kernel must make sure that when it context switches us back in, it 23 * honours the fact that we had PMAE clear. 24 * 25 * Observed to hit the failing case on the first EBB with a broken kernel. 26 */ 27 28static bool mmcr0_mismatch; 29static uint64_t before, after; 30 31static void syscall_ebb_callee(void) 32{ 33 uint64_t val; 34 35 val = mfspr(SPRN_BESCR); 36 if (!(val & BESCR_PMEO)) { 37 ebb_state.stats.spurious++; 38 goto out; 39 } 40 41 ebb_state.stats.ebb_count++; 42 count_pmc(1, sample_period); 43 44 before = mfspr(SPRN_MMCR0); 45 46 /* Try and get ourselves scheduled, to force a PMU context switch */ 47 sched_yield(); 48 49 after = mfspr(SPRN_MMCR0); 50 if (before != after) 51 mmcr0_mismatch = true; 52 53out: 54 reset_ebb(); 55} 56 57static int test_body(void) 58{ 59 struct event event; 60 61 event_init_named(&event, 0x1001e, "cycles"); 62 event_leader_ebb_init(&event); 63 64 event.attr.exclude_kernel = 1; 65 event.attr.exclude_hv = 1; 66 event.attr.exclude_idle = 1; 67 68 FAIL_IF(event_open(&event)); 69 70 setup_ebb_handler(syscall_ebb_callee); 71 ebb_global_enable(); 72 73 FAIL_IF(ebb_event_enable(&event)); 74 75 mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); 76 77 while (ebb_state.stats.ebb_count < 20 && !mmcr0_mismatch) 78 FAIL_IF(core_busy_loop()); 79 80 ebb_global_disable(); 81 ebb_freeze_pmcs(); 82 83 count_pmc(1, sample_period); 84 85 dump_ebb_state(); 86 87 if (mmcr0_mismatch) 88 printf("Saw MMCR0 before 0x%lx after 0x%lx\n", before, after); 89 90 event_close(&event); 91 92 FAIL_IF(ebb_state.stats.ebb_count == 0); 93 FAIL_IF(mmcr0_mismatch); 94 95 return 0; 96} 97 98int pmae_handling(void) 99{ 100 return eat_cpu(test_body); 101} 102 103int main(void) 104{ 105 return test_harness(pmae_handling, "pmae_handling"); 106} 107