/** * \file * \brief AMD performance monitoring infrastructure. */ /* * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #include #include #include #include #include #include #include #include #include #include static bool perfmon_amd = false, perfmon_intel = false; /* static bool perfmon_measurement_running = false; */ /* static bool perfmon_apic_activated = false; */ static uint64_t perfmon_cntr_init = 0; struct capability perfmon_callback_ep = { .type = ObjType_Null, }; void perfmon_init(void) { // Return if init already done .. if(perfmon_amd || perfmon_intel) { return; } // Try to initialize on intel. if(err_is_fail(perfmon_intel_init())) { // Try amd perfmon_amd_init(); // Check amd perfmon_amd = perfmon_amd_supported(); } else { perfmon_intel = true; } // Debug output if(perfmon_intel) { printf("Activated perfmon for Intel!\n"); } else if(perfmon_amd) { printf("Activated perfmon for AMD!\n"); } else { printf("Perfmon activation failed. " "Neither Intel nor AMD support detected\n"); } } /* * \brief Initialize measuring for performance analysis. * * An overflow will be registered and the counter will set such that this * overflow occures every ctr counter steps. */ void perfmon_measure_start(uint8_t event, uint8_t umask, uint8_t counter_id, bool kernel, uint64_t ctr) { // Activate APIC interrupts for overflow if init successful if(ctr!=0) { if(perfmon_amd || perfmon_intel) { apic_perfcnt_init(); } } if(perfmon_amd) { perfmon_amd_measure_write(ctr*-1, 0); perfmon_amd_measure_start(event, umask, kernel, counter_id, ctr!=0); } // Activate performance measurement for Intel if(perfmon_intel) { perfmon_intel_measure_write(ctr*-1); perfmon_intel_measure_start(event, umask, kernel, counter_id, ctr!=0); } perfmon_cntr_init = ctr; } /* * Re-Initialize counter after overflow. * This function is called from the interrupt processing. */ void perfmon_measure_reset(void) { if(perfmon_amd) { perfmon_amd_measure_write(perfmon_cntr_init*-1, 0); } if(perfmon_intel) { perfmon_intel_reset(); perfmon_intel_measure_write(perfmon_cntr_init*-1); } } uint64_t perfmon_measure_read(void) { if(perfmon_amd) { return perfmon_amd_measure_read(0); } if(perfmon_intel) { return perfmon_intel_measure_read(); } return 0; } void perfmon_measure_write(uint8_t counter_id, uint64_t val) { if(perfmon_amd) { perfmon_amd_measure_write(val, counter_id); } if(perfmon_intel) { perfmon_intel_measure_write(val); } } /* * \brief Deactivate performance measuring */ void perfmon_measure_stop(void) { if(perfmon_amd) { perfmon_amd_measure_stop(0); } // Mask out performance counter overflow interrupts on APIC apic_perfcnt_stop(); }