1/*
2 * Copyright (c) 2010-2018 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32#ifndef _KERN_LEDGER_H_
33#define _KERN_LEDGER_H_
34
35#include <mach/mach_types.h> /* ledger_t */
36
37#ifdef MACH_KERNEL_PRIVATE
38#include <os/refcnt.h>
39#endif /* MACH_KERNEL_PRIVATE */
40
41#define LEDGER_INFO 0
42#define LEDGER_ENTRY_INFO 1
43#define LEDGER_TEMPLATE_INFO 2
44#define LEDGER_LIMIT 3
45/* LEDGER_MAX_CMD always tracks the index of the last ledger command. */
46#define LEDGER_MAX_CMD LEDGER_LIMIT
47
48#define LEDGER_NAME_MAX 32
49
50struct ledger_info {
51 char li_name[LEDGER_NAME_MAX];
52 int64_t li_id;
53 int64_t li_entries;
54};
55
56struct ledger_template_info {
57 char lti_name[LEDGER_NAME_MAX];
58 char lti_group[LEDGER_NAME_MAX];
59 char lti_units[LEDGER_NAME_MAX];
60};
61
62#ifdef MACH_KERNEL_PRIVATE
63/*
64 * The explicit alignment is to ensure that atomic operations don't panic
65 * on ARM.
66 */
67struct ledger_entry {
68 volatile uint32_t le_flags;
69#define LEDGER_PERCENT_NONE UINT16_MAX
70#define LEDGER_DIAG_MEM_THRESHOLD_INFINITY ((int16_t)((1ULL << 16) - 1))
71
72 uint16_t le_warn_percent;
73 int16_t le_diag_threshold_scaled; /* Diag mem threshold for this entry, handled in Mbytes */
74 ledger_amount_t le_limit;
75 volatile ledger_amount_t le_credit __attribute__((aligned(8)));
76 volatile ledger_amount_t le_debit __attribute__((aligned(8)));
77 union {
78 struct {
79 /*
80 * XXX - the following two fields can go away if we move all of
81 * the refill logic into process policy
82 */
83 uint64_t le_refill_period;
84 uint64_t le_last_refill;
85 } le_refill;
86 struct {
87 ledger_amount_t le_lifetime_max; /* Process lifetime peak */
88#if CONFIG_LEDGER_INTERVAL_MAX
89 ledger_amount_t le_interval_max; /* Interval peak XXX better name needed */
90#endif
91 } _le_max;
92 } _le;
93} __attribute__((aligned(8)));
94
95/*
96 * Many ledger entries just need to track an amount
97 * and have a few flags (panic on negative, active / inactive, etc...).
98 * Those entries use this struct to save memory.
99 */
100struct ledger_entry_small {
101 volatile uint32_t les_flags;
102 volatile ledger_amount_t les_credit __attribute__((aligned(8)));
103} __attribute__((aligned(8)));
104
105struct ledger {
106 uint64_t l_id;
107 os_refcnt_t l_refs;
108 int32_t l_size;
109 struct ledger_template * l_template;
110 struct ledger_entry_small l_entries[] __attribute__((aligned(8)));
111};
112#endif /* MACH_KERNEL_PRIVATE */
113
114struct ledger_entry_info {
115 int64_t lei_balance;
116 int64_t lei_credit;
117 int64_t lei_debit;
118 uint64_t lei_limit;
119 uint64_t lei_refill_period; /* In nanoseconds */
120 uint64_t lei_last_refill; /* Time since last refill */
121};
122
123struct ledger_limit_args {
124 char lla_name[LEDGER_NAME_MAX];
125 uint64_t lla_limit;
126 uint64_t lla_refill_period;
127};
128
129#ifdef KERNEL_PRIVATE
130
131typedef struct ledger_template *ledger_template_t;
132
133#define LEDGER_VALID(ledger) (ledger != LEDGER_NULL)
134
135/* Action to take when a ledger goes into deficit */
136#define LEDGER_ACTION_IGNORE 0x0000
137#define LEDGER_ACTION_BLOCK 0x0010
138#define LEDGER_ACTION_CALLBACK 0x0020
139#define LEDGER_ACTION_MASK 0x00f0
140
141/*
142 * Types of warnings that trigger a callback.
143 */
144#define LEDGER_WARNING_ROSE_ABOVE 1
145#define LEDGER_WARNING_DIPPED_BELOW 2
146#define LEDGER_WARNING_DIAG_MEM_THRESHOLD 3
147
148typedef void (*ledger_callback_t)(int warning, const void * param0, const void *param1);
149
150extern ledger_template_t ledger_template_create(const char *name);
151extern ledger_template_t ledger_template_copy(ledger_template_t template, const char *name);
152extern void ledger_template_dereference(ledger_template_t template);
153/*
154 * DEPRECATED. Use ledger_entry_add_with_flags instead.
155 */
156extern int ledger_entry_add(ledger_template_t template, const char *key,
157 const char *group, const char *units);
158extern kern_return_t ledger_set_callback(ledger_template_t template, int entry,
159 ledger_callback_t callback, const void *param0, const void *param1);
160extern kern_return_t ledger_track_maximum(ledger_template_t template, int entry,
161 int period_in_secs);
162extern kern_return_t ledger_panic_on_negative(ledger_template_t template,
163 int entry);
164extern kern_return_t ledger_track_credit_only(ledger_template_t template,
165 int entry);
166extern int ledger_key_lookup(ledger_template_t template, const char *key);
167
168/*
169 * Supported ledger features.
170 * Passed in as a bitwise OR to ledger_entry_add_with_flags
171 */
172__options_decl(ledger_entry_flags, uint64_t, {
173 LEDGER_ENTRY_ALLOW_CALLBACK = 0x1,
174 LEDGER_ENTRY_ALLOW_MAXIMUM = 0x2,
175 LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE = 0x4,
176 LEDGER_ENTRY_ALLOW_DEBIT = 0x8,
177 LEDGER_ENTRY_ALLOW_LIMIT = 0x10,
178 LEDGER_ENTRY_ALLOW_ACTION = 0x20,
179 LEDGER_ENTRY_ALLOW_INACTIVE = 0x40,
180});
181
182/*
183 * Create a new ledger entry that only supports the feature set passed in via
184 * flags.
185 *
186 * This is the recommended way to create new ledger entries, as it allows
187 * the ledger code to allocate less memory for simpler entries.
188 * ledger_entry_add is kept for backwards compatibility.
189 *
190 * See below for the set of valid flags.
191 */
192extern int ledger_entry_add_with_flags(ledger_template_t template, const char *key,
193 const char *group, const char *units, ledger_entry_flags flags);
194
195/* value of entry type */
196#define LEDGER_CREATE_ACTIVE_ENTRIES 0
197#define LEDGER_CREATE_INACTIVE_ENTRIES 1
198extern ledger_t ledger_instantiate(ledger_template_t template, int entry_type);
199extern void ledger_template_complete(ledger_template_t template);
200extern void ledger_template_complete_secure_alloc(ledger_template_t template);
201extern kern_return_t ledger_disable_callback(ledger_t ledger, int entry);
202extern kern_return_t ledger_enable_callback(ledger_t ledger, int entry);
203extern kern_return_t ledger_get_limit(ledger_t ledger, int entry,
204 ledger_amount_t *limit);
205extern kern_return_t ledger_set_limit(ledger_t ledger, int entry,
206 ledger_amount_t limit, uint8_t warn_level_percentage);
207#if CONFIG_LEDGER_INTERVAL_MAX
208extern kern_return_t ledger_get_interval_max(ledger_t ledger, int entry,
209 ledger_amount_t *max_interval_balance, int reset);
210#endif /* CONFIG_LEDGER_INTERVAL_MAX */
211extern kern_return_t ledger_get_lifetime_max(ledger_t ledger, int entry,
212 ledger_amount_t *max_lifetime_balance);
213extern kern_return_t ledger_get_actions(ledger_t ledger, int entry, int *actions);
214extern kern_return_t ledger_set_action(ledger_t ledger, int entry, int action);
215extern kern_return_t ledger_get_period(ledger_t ledger, int entry,
216 uint64_t *period);
217extern kern_return_t ledger_set_period(ledger_t ledger, int entry,
218 uint64_t period);
219extern kern_return_t ledger_disable_refill(ledger_t l, int entry);
220extern kern_return_t ledger_entry_setactive(ledger_t ledger, int entry);
221extern void ledger_check_new_balance(thread_t thread, ledger_t ledger, int entry);
222extern kern_return_t ledger_credit(ledger_t ledger, int entry,
223 ledger_amount_t amount);
224extern kern_return_t ledger_credit_nocheck(ledger_t ledger, int entry,
225 ledger_amount_t amount);
226extern kern_return_t ledger_debit(ledger_t ledger, int entry,
227 ledger_amount_t amount);
228extern kern_return_t ledger_debit_nocheck(ledger_t ledger, int entry,
229 ledger_amount_t amount);
230extern kern_return_t ledger_credit_thread(thread_t thread, ledger_t ledger,
231 int entry, ledger_amount_t amount);
232extern kern_return_t ledger_debit_thread(thread_t thread, ledger_t ledger,
233 int entry, ledger_amount_t amount);
234extern kern_return_t ledger_zero_balance(ledger_t ledger, int entry);
235extern kern_return_t ledger_get_entries(ledger_t ledger, int entry,
236 ledger_amount_t *credit, ledger_amount_t *debit);
237extern kern_return_t ledger_get_balance(ledger_t ledger, int entry,
238 ledger_amount_t *balance);
239extern kern_return_t ledger_reset_callback_state(ledger_t ledger, int entry);
240extern kern_return_t ledger_disable_panic_on_negative(ledger_t ledger, int entry);
241extern kern_return_t ledger_get_panic_on_negative(ledger_t ledger, int entry, int *panic_on_negative);
242
243extern kern_return_t ledger_rollup(ledger_t to_ledger, ledger_t from_ledger);
244extern kern_return_t ledger_rollup_entry(ledger_t to_ledger, ledger_t from_ledger, int entry);
245
246extern void ledger_ast(thread_t thread);
247
248extern void ledger_reference(ledger_t ledger);
249extern void ledger_dereference(ledger_t ledger);
250
251extern ledger_amount_t ledger_get_remaining(ledger_t ledger, int entry);
252extern void ledger_restart(ledger_t ledger, int entry, uint64_t now);
253extern uint64_t ledger_get_interval_remaining(ledger_t ledger, int entry, uint64_t now);
254
255/* Support for ledger() syscall */
256#ifdef LEDGER_DEBUG
257extern int ledger_limit(task_t task, struct ledger_limit_args *args);
258#endif
259extern int ledger_info(task_t task, struct ledger_info *info);
260
261extern int
262ledger_get_task_entry_info_multiple(task_t task, void **buf, int *len);
263
264extern void
265ledger_get_entry_info(ledger_t ledger, int entry,
266 struct ledger_entry_info *lei);
267
268extern int ledger_template_info(void **buf, int *len);
269
270#if DEBUG || DEVELOPMENT
271extern kern_return_t ledger_get_diag_mem_threshold(ledger_t ledger, int entry,
272 ledger_amount_t *limit);
273
274extern kern_return_t ledger_set_diag_mem_threshold(ledger_t ledger, int entry,
275 ledger_amount_t limit);
276extern kern_return_t ledger_set_diag_mem_threshold_disabled(ledger_t ledger, int entry);
277extern kern_return_t ledger_set_diag_mem_threshold_enabled(ledger_t ledger, int entry);
278extern kern_return_t ledger_is_diag_threshold_enabled(ledger_t ledger, int entry, bool *status);
279#endif // DEBUG || DEVELOPMENT
280
281#endif /* KERNEL_PRIVATE */
282
283#endif /* _KERN_LEDGER_H_ */
284