summaryrefslogtreecommitdiffstats
path: root/lib/cpus/aarch64/cpuamu.c
blob: 3a2fa819f8788d9fbfea8bbdc8e807e72e73697d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <cpuamu.h>
#include <lib/el3_runtime/pubsub_events.h>
#include <plat/common/platform.h>

#define CPUAMU_NR_COUNTERS	5U

struct cpuamu_ctx {
	uint64_t cnts[CPUAMU_NR_COUNTERS];
	unsigned int mask;
};

static struct cpuamu_ctx cpuamu_ctxs[PLATFORM_CORE_COUNT];

int midr_match(unsigned int cpu_midr)
{
	unsigned int midr, midr_mask;

	midr = (unsigned int)read_midr();
	midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) |
		(MIDR_PN_MASK << MIDR_PN_SHIFT);
	return ((midr & midr_mask) == (cpu_midr & midr_mask));
}

void cpuamu_context_save(unsigned int nr_counters)
{
	struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()];
	unsigned int i;

	assert(nr_counters <= CPUAMU_NR_COUNTERS);

	/* Save counter configuration */
	ctx->mask = cpuamu_read_cpuamcntenset_el0();

	/* Disable counters */
	cpuamu_write_cpuamcntenclr_el0(ctx->mask);
	isb();

	/* Save counters */
	for (i = 0; i < nr_counters; i++)
		ctx->cnts[i] = cpuamu_cnt_read(i);
}

void cpuamu_context_restore(unsigned int nr_counters)
{
	struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()];
	unsigned int i;

	assert(nr_counters <= CPUAMU_NR_COUNTERS);

	/*
	 * Disable counters.  They were enabled early in the
	 * CPU reset function.
	 */
	cpuamu_write_cpuamcntenclr_el0(ctx->mask);
	isb();

	/* Restore counters */
	for (i = 0; i < nr_counters; i++)
		cpuamu_cnt_write(i, ctx->cnts[i]);
	isb();

	/* Restore counter configuration */
	cpuamu_write_cpuamcntenset_el0(ctx->mask);
}