1/** 2 * \file 3 * \brief AMD performance monitoring infrastructure. 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <kernel.h> 16#include <stdio.h> 17#include <stdint.h> 18#include <stdbool.h> 19#include <string.h> 20#include <capabilities.h> 21#include <arch/x86/perfmon_amd.h> 22#include <arch/x86/perfmon_intel.h> 23#include <arch/x86/perfmon.h> 24#include <arch/x86/apic.h> 25 26static bool perfmon_amd = false, perfmon_intel = false; 27/* static bool perfmon_measurement_running = false; */ 28/* static bool perfmon_apic_activated = false; */ 29static uint64_t perfmon_cntr_init = 0; 30struct capability perfmon_callback_ep = { 31 .type = ObjType_Null, 32}; 33 34void perfmon_init(void) 35{ 36 // Return if init already done .. 37 if(perfmon_amd || perfmon_intel) { 38 return; 39 } 40 41 // Try to initialize on intel. 42 if(err_is_fail(perfmon_intel_init())) { 43 // Try amd 44 perfmon_amd_init(); 45 // Check amd 46 perfmon_amd = perfmon_amd_supported(); 47 } else { 48 perfmon_intel = true; 49 } 50 51 // Debug output 52 if(perfmon_intel) { 53 printf("Activated perfmon for Intel!\n"); 54 } else if(perfmon_amd) { 55 printf("Activated perfmon for AMD!\n"); 56 } else { 57 printf("Perfmon activation failed. " 58 "Neither Intel nor AMD support detected\n"); 59 } 60} 61 62/* 63 * \brief Initialize measuring for performance analysis. 64 * 65 * An overflow will be registered and the counter will set such that this 66 * overflow occures every ctr counter steps. 67 */ 68void perfmon_measure_start(uint8_t event, uint8_t umask, 69 uint8_t counter_id, bool kernel, uint64_t ctr) 70{ 71 // Activate APIC interrupts for overflow if init successful 72 if(ctr!=0) { 73 if(perfmon_amd || perfmon_intel) { 74 apic_perfcnt_init(); 75 } 76 } 77 78 if(perfmon_amd) { 79 perfmon_amd_measure_write(ctr*-1, 0); 80 perfmon_amd_measure_start(event, umask, kernel, counter_id, ctr!=0); 81 } 82 83 // Activate performance measurement for Intel 84 if(perfmon_intel) { 85 perfmon_intel_measure_write(ctr*-1); 86 perfmon_intel_measure_start(event, umask, kernel, counter_id, ctr!=0); 87 } 88 89 perfmon_cntr_init = ctr; 90} 91 92/* 93 * Re-Initialize counter after overflow. 94 * This function is called from the interrupt processing. 95 */ 96void perfmon_measure_reset(void) 97{ 98 if(perfmon_amd) { 99 perfmon_amd_measure_write(perfmon_cntr_init*-1, 0); 100 } 101 if(perfmon_intel) { 102 perfmon_intel_reset(); 103 perfmon_intel_measure_write(perfmon_cntr_init*-1); 104 } 105} 106 107uint64_t perfmon_measure_read(void) 108{ 109 if(perfmon_amd) { 110 return perfmon_amd_measure_read(0); 111 } 112 113 if(perfmon_intel) { 114 return perfmon_intel_measure_read(); 115 } 116 117 return 0; 118 119} 120 121void perfmon_measure_write(uint8_t counter_id, uint64_t val) 122{ 123 124 if(perfmon_amd) { 125 perfmon_amd_measure_write(val, counter_id); 126 } 127 128 if(perfmon_intel) { 129 perfmon_intel_measure_write(val); 130 } 131 132} 133 134/* 135 * \brief Deactivate performance measuring 136 */ 137void perfmon_measure_stop(void) 138{ 139 if(perfmon_amd) { 140 perfmon_amd_measure_stop(0); 141 } 142 143 // Mask out performance counter overflow interrupts on APIC 144 apic_perfcnt_stop(); 145} 146