1// Copyright (c) 2023 Apple Inc. All rights reserved.
2//
3// @APPLE_OSREFERENCE_LICENSE_HEADER_START@
4//
5// This file contains Original Code and/or Modifications of Original Code
6// as defined in and that are subject to the Apple Public Source License
7// Version 2.0 (the 'License'). You may not use this file except in
8// compliance with the License. The rights granted to you under the License
9// may not be used to create, or enable the creation or redistribution of,
10// unlawful or unlicensed copies of an Apple operating system, or to
11// circumvent, violate, or enable the circumvention or violation of, any
12// terms of an Apple operating system software license agreement.
13//
14// Please obtain a copy of the License at
15// http://www.opensource.apple.com/apsl/ and read it before using this file.
16//
17// The Original Code and all software distributed under the License are
18// distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
19// EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
20// INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
22// Please see the License for the specific language governing rights and
23// limitations under the License.
24//
25// @APPLE_OSREFERENCE_LICENSE_HEADER_END@
26
27#include <kern/cpc.h>
28#include <stdbool.h>
29#include <kern/assert.h>
30#include <kern/debug.h>
31#include <os/atomic.h>
32#include <os/atomic_private.h>
33
34#if __arm64__
35#include <arm64/cpc_arm64.h>
36#endif // __arm64__
37
38#pragma mark - Ownership
39
40#if CONFIG_CPU_COUNTERS
41static const char * _Atomic _cpc_hw_owners[CPC_HW_COUNT] = { NULL };
42#endif // CONFIG_CPU_COUNTERS
43
44__result_use_check bool
45cpc_hw_acquire(cpc_hw_t hw, const char *owner_name)
46{
47#if CONFIG_CPU_COUNTERS
48 assert3u(hw, <, CPC_HW_COUNT);
49 extern int kpc_get_force_all_ctrs(void);
50 if (hw == CPC_HW_CPMU && kpc_get_force_all_ctrs()) {
51 return false;
52 }
53 return os_atomic_cmpxchg(&_cpc_hw_owners[hw], NULL, owner_name, acq_rel);
54#else // CONFIG_CPU_COUNTERS
55#pragma unused(hw, owner_name)
56 return false;
57#endif // !CONFIG_CPU_COUNTERS
58}
59
60bool
61cpc_hw_in_use(cpc_hw_t hw)
62{
63#if CONFIG_CPU_COUNTERS
64 assert3u(hw, <, CPC_HW_COUNT);
65 return os_atomic_load(&_cpc_hw_owners[hw], acquire) != NULL;
66#else // CONFIG_CPU_COUNTERS
67#pragma unused(hw)
68 return false;
69#endif // !CONFIG_CPU_COUNTERS
70}
71
72void
73cpc_hw_release(cpc_hw_t hw, const char *owner_name)
74{
75#if CONFIG_CPU_COUNTERS
76 assert3u(hw, <, CPC_HW_COUNT);
77 if (!os_atomic_cmpxchg(&_cpc_hw_owners[hw], owner_name, NULL, acq_rel)) {
78 panic("CPC: unpaired HW release: %s on %u", owner_name, hw);
79 }
80#else // CONFIG_CPU_COUNTERS
81#pragma unused(hw, owner_name)
82#endif // !CONFIG_CPU_COUNTERS
83}
84
85bool
86cpc_is_secure(void)
87{
88#if CONFIG_CPU_COUNTERS
89#if __arm64__
90 cpc_event_policy_t policy = cpc_get_event_policy();
91 return policy == CPC_EVPOL_RESTRICT_TO_KNOWN || policy == CPC_EVPOL_DENY_ALL;
92#else // __arm64__
93 return false;
94#endif // !__arm64__
95#else // CONFIG_CPU_COUNTERS
96 return true;
97#endif // !CONFIG_CPU_COUNTERS
98}
99
100#if CPC_INSECURE
101
102void
103cpc_change_security(bool enforce_security)
104{
105#if CONFIG_CPU_COUNTERS
106#if __arm64__
107 cpc_set_event_policy(enforce_security ? CPC_EVPOL_RESTRICT_TO_KNOWN : CPC_EVPOL_DEFAULT);
108#else // __arm64__
109#pragma unused(enforce_security)
110 // Intel has no event policy or other security features.
111#endif // !__arm64__
112#else // CONFIG_CPU_COUNTERS
113#pragma unused(enforce_security)
114#endif // !CONFIG_CPU_COUNTERS
115}
116
117#endif // CPC_INSECURE
118