1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12#pragma once 13 14#include <stdint.h> 15#include <sel4bench/cpu/events.h> 16 17//function attributes 18//functions that need to be forced inline 19#define FASTFN inline __attribute__((always_inline)) 20 21//functions that must not cache miss 22#define CACHESENSFN __attribute__((noinline, aligned(32))) 23 24//functions that will be called through pointers, but need to be fast 25#define KERNELFN __attribute__((noinline, flatten)) 26 27//counters and related constants 28#define SEL4BENCH_ARM1136_NUM_COUNTERS 2 29 30#define SEL4BENCH_ARM1136_COUNTER_CCNT "1" 31#define SEL4BENCH_ARM1136_COUNTER_PMN0 "2" 32#define SEL4BENCH_ARM1136_COUNTER_PMN1 "3" 33 34/* 35 * PMNC: ARM1136 Performance Monitor Control Register 36 * 37 * bits 31:28 = SBZ 38 * bits 27:20 = EvtCount1 = event monitored by counter 1 39 * bits 19:12 = EvtCount2 = event monitored by counter 2 40 * bit 11 = X = export events to ETM 41 * bits 10: 8 = Flag = read: determines if C0 (bit 8)/ 42 * C1 (bit 9)/CCNT (bit 10) 43 * overflowed 44 * write: clears overflow flag 45 * bit 7 = SBZ 46 * bits 6: 4 = IntEn = Enable interrupt reporting for 47 * C0 (bit 4)/C1 (bit 5)/CCNT (bit 6) 48 * bit 3 = D = cycle counter divides by 64 49 * bit 2 = C = write 1 to reset CCNT to zero 50 * bit 1 = P = write 1 to reset C0 and C1 to zero 51 * bit 0 = E = enable all three counters 52 */ 53typedef union { 54 struct { 55 uint32_t E : 1; 56 uint32_t P : 1; 57 uint32_t C : 1; 58 uint32_t D : 1; 59 uint32_t IntEn : 3; 60 uint32_t SBZ1 : 1; 61 uint32_t Flag : 3; 62 uint32_t X : 1; 63 uint32_t EvtCount2 : 8; 64 uint32_t EvtCount1 : 8; 65 uint32_t SBZ2 : 4; 66 }; 67 uint32_t raw; 68} sel4bench_arm1136_pmnc_t; 69 70static CACHESENSFN void sel4bench_private_set_pmnc(sel4bench_arm1136_pmnc_t val) 71{ 72 /* 73 * The ARM1136 has a 3-cycle delay between changing the PMNC and the 74 * counters reacting. So we insert 3 nops to cover for that. Aligning on a 75 * cache line boundary guarantees that the nops won't cause anything 76 * interesting to happen. 77 */ 78 asm volatile ( 79 "mcr p15, 0, %0, c15, c12, 0;" 80 "nop;" 81 "nop;" 82 "nop;" 83 : 84 : "r"(val.raw) 85 ); 86} 87static FASTFN sel4bench_arm1136_pmnc_t sel4bench_private_get_pmnc(void) 88{ 89 sel4bench_arm1136_pmnc_t val; 90 asm volatile ( 91 "mrc p15, 0, %0, c15, c12, 0" 92 : "=r"(val.raw) 93 : 94 ); 95 return val; 96} 97 98/* 99 * CCNT: cycle counter 100 */ 101static FASTFN uint32_t sel4bench_private_get_ccnt() 102{ 103 uint32_t val; 104 asm volatile ( 105 "mrc p15, 0, %0, c15, c12," SEL4BENCH_ARM1136_COUNTER_CCNT 106 : "=r"(val) 107 ); 108 return val; 109} 110 111/* 112 * PMN0: event count 0 113 */ 114static FASTFN uint32_t sel4bench_private_get_pmn0() 115{ 116 uint32_t val; 117 asm volatile ( 118 "mrc p15, 0, %0, c15, c12,"SEL4BENCH_ARM1136_COUNTER_PMN0 119 : "=r"(val) 120 ); 121 return val; 122} 123static FASTFN void sel4bench_private_set_pmn0(uint32_t val) 124{ 125 asm volatile ( 126 "mcr p15, 0, %0, c15, c12,"SEL4BENCH_ARM1136_COUNTER_PMN0 127 : "=r"(val) 128 ); 129} 130 131/* 132 * PMN1: event count 1 133 */ 134static FASTFN uint32_t sel4bench_private_get_pmn1() 135{ 136 uint32_t val; 137 asm volatile ( 138 "mrc p15, 0, %0, c15, c12,"SEL4BENCH_ARM1136_COUNTER_PMN1 139 : "=r"(val) 140 ); 141 return val; 142} 143static FASTFN void sel4bench_private_set_pmn1(uint32_t val) 144{ 145 asm volatile ( 146 "mcr p15, 0, %0, c15, c12,"SEL4BENCH_ARM1136_COUNTER_PMN1 147 : "=r"(val) 148 ); 149} 150