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 50 struct ledger_info { 51 char li_name[LEDGER_NAME_MAX]; 52 int64_t li_id; 53 int64_t li_entries; 54 }; 55 56 struct 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 */ 67 struct 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 */ 100 struct ledger_entry_small { 101 volatile uint32_t les_flags; 102 volatile ledger_amount_t les_credit __attribute__((aligned(8))); 103 } __attribute__((aligned(8))); 104 105 struct 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 114 struct 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 123 struct 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 131 typedef 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 148 typedef void (*ledger_callback_t)(int warning, const void * param0, const void *param1); 149 150 extern ledger_template_t ledger_template_create(const char *name); 151 extern ledger_template_t ledger_template_copy(ledger_template_t template, const char *name); 152 extern void ledger_template_dereference(ledger_template_t template); 153 /* 154 * DEPRECATED. Use ledger_entry_add_with_flags instead. 155 */ 156 extern int ledger_entry_add(ledger_template_t template, const char *key, 157 const char *group, const char *units); 158 extern kern_return_t ledger_set_callback(ledger_template_t template, int entry, 159 ledger_callback_t callback, const void *param0, const void *param1); 160 extern kern_return_t ledger_track_maximum(ledger_template_t template, int entry, 161 int period_in_secs); 162 extern kern_return_t ledger_panic_on_negative(ledger_template_t template, 163 int entry); 164 extern kern_return_t ledger_track_credit_only(ledger_template_t template, 165 int entry); 166 extern 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 */ 192 extern 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 198 extern ledger_t ledger_instantiate(ledger_template_t template, int entry_type); 199 extern void ledger_template_complete(ledger_template_t template); 200 extern void ledger_template_complete_secure_alloc(ledger_template_t template); 201 extern kern_return_t ledger_disable_callback(ledger_t ledger, int entry); 202 extern kern_return_t ledger_enable_callback(ledger_t ledger, int entry); 203 extern kern_return_t ledger_get_limit(ledger_t ledger, int entry, 204 ledger_amount_t *limit); 205 extern 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 208 extern 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 */ 211 extern kern_return_t ledger_get_lifetime_max(ledger_t ledger, int entry, 212 ledger_amount_t *max_lifetime_balance); 213 extern kern_return_t ledger_get_actions(ledger_t ledger, int entry, int *actions); 214 extern kern_return_t ledger_set_action(ledger_t ledger, int entry, int action); 215 extern kern_return_t ledger_get_period(ledger_t ledger, int entry, 216 uint64_t *period); 217 extern kern_return_t ledger_set_period(ledger_t ledger, int entry, 218 uint64_t period); 219 extern kern_return_t ledger_disable_refill(ledger_t l, int entry); 220 extern kern_return_t ledger_entry_setactive(ledger_t ledger, int entry); 221 extern void ledger_check_new_balance(thread_t thread, ledger_t ledger, int entry); 222 extern kern_return_t ledger_credit(ledger_t ledger, int entry, 223 ledger_amount_t amount); 224 extern kern_return_t ledger_credit_nocheck(ledger_t ledger, int entry, 225 ledger_amount_t amount); 226 extern kern_return_t ledger_debit(ledger_t ledger, int entry, 227 ledger_amount_t amount); 228 extern kern_return_t ledger_debit_nocheck(ledger_t ledger, int entry, 229 ledger_amount_t amount); 230 extern kern_return_t ledger_credit_thread(thread_t thread, ledger_t ledger, 231 int entry, ledger_amount_t amount); 232 extern kern_return_t ledger_debit_thread(thread_t thread, ledger_t ledger, 233 int entry, ledger_amount_t amount); 234 extern kern_return_t ledger_zero_balance(ledger_t ledger, int entry); 235 extern kern_return_t ledger_get_entries(ledger_t ledger, int entry, 236 ledger_amount_t *credit, ledger_amount_t *debit); 237 extern kern_return_t ledger_get_balance(ledger_t ledger, int entry, 238 ledger_amount_t *balance); 239 extern kern_return_t ledger_reset_callback_state(ledger_t ledger, int entry); 240 extern kern_return_t ledger_disable_panic_on_negative(ledger_t ledger, int entry); 241 extern kern_return_t ledger_get_panic_on_negative(ledger_t ledger, int entry, int *panic_on_negative); 242 243 extern kern_return_t ledger_rollup(ledger_t to_ledger, ledger_t from_ledger); 244 extern kern_return_t ledger_rollup_entry(ledger_t to_ledger, ledger_t from_ledger, int entry); 245 246 extern void ledger_ast(thread_t thread); 247 248 extern void ledger_reference(ledger_t ledger); 249 extern void ledger_dereference(ledger_t ledger); 250 251 extern ledger_amount_t ledger_get_remaining(ledger_t ledger, int entry); 252 extern void ledger_restart(ledger_t ledger, int entry, uint64_t now); 253 extern uint64_t ledger_get_interval_remaining(ledger_t ledger, int entry, uint64_t now); 254 255 /* Support for ledger() syscall */ 256 #ifdef LEDGER_DEBUG 257 extern int ledger_limit(task_t task, struct ledger_limit_args *args); 258 #endif 259 extern int ledger_info(task_t task, struct ledger_info *info); 260 261 extern int 262 ledger_get_task_entry_info_multiple(task_t task, void **buf, int *len); 263 264 extern void 265 ledger_get_entry_info(ledger_t ledger, int entry, 266 struct ledger_entry_info *lei); 267 268 extern int ledger_template_info(void **buf, int *len); 269 270 #if DEBUG || DEVELOPMENT 271 extern kern_return_t ledger_get_diag_mem_threshold(ledger_t ledger, int entry, 272 ledger_amount_t *limit); 273 274 extern kern_return_t ledger_set_diag_mem_threshold(ledger_t ledger, int entry, 275 ledger_amount_t limit); 276 extern kern_return_t ledger_set_diag_mem_threshold_disabled(ledger_t ledger, int entry); 277 extern kern_return_t ledger_set_diag_mem_threshold_enabled(ledger_t ledger, int entry); 278 extern 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