]> git.saurik.com Git - apple/xnu.git/blame - osfmk/arm/machine_routines.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / arm / machine_routines.h
CommitLineData
5ba3f43e 1/*
f427ee49 2 * Copyright (c) 2007-2020 Apple Inc. All rights reserved.
5ba3f43e
A
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
0a7de745
A
32#ifndef _ARM_MACHINE_ROUTINES_H_
33#define _ARM_MACHINE_ROUTINES_H_
5ba3f43e
A
34
35#include <mach/mach_types.h>
f427ee49 36#include <mach/vm_types.h>
5ba3f43e
A
37#include <mach/boolean.h>
38#include <kern/kern_types.h>
39#include <pexpert/pexpert.h>
40
41#include <sys/cdefs.h>
42#include <sys/appleapiopts.h>
43
44#include <stdarg.h>
45
46__BEGIN_DECLS
47
f427ee49
A
48#ifdef XNU_KERNEL_PRIVATE
49#ifdef __arm64__
50typedef bool (*expected_fault_handler_t)(arm_saved_state_t *);
51#endif /* __arm64__ */
52#endif /* XNU_KERNEL_PRIVATE */
53
5ba3f43e
A
54/* Interrupt handling */
55
56void ml_cpu_signal(unsigned int cpu_id);
57void ml_cpu_signal_deferred_adjust_timer(uint64_t nanosecs);
58uint64_t ml_cpu_signal_deferred_get_timer(void);
59void ml_cpu_signal_deferred(unsigned int cpu_id);
60void ml_cpu_signal_retract(unsigned int cpu_id);
f427ee49 61bool ml_cpu_signal_is_enabled(void);
5ba3f43e
A
62
63/* Initialize Interrupts */
64void ml_init_interrupt(void);
65
66/* Get Interrupts Enabled */
67boolean_t ml_get_interrupts_enabled(void);
68
69/* Set Interrupts Enabled */
70boolean_t ml_set_interrupts_enabled(boolean_t enable);
0a7de745 71boolean_t ml_early_set_interrupts_enabled(boolean_t enable);
5ba3f43e
A
72
73/* Check if running at interrupt context */
74boolean_t ml_at_interrupt_context(void);
75
76/* Generate a fake interrupt */
77void ml_cause_interrupt(void);
78
79/* Clear interrupt spin debug state for thread */
80#if INTERRUPT_MASKED_DEBUG
f427ee49
A
81extern boolean_t interrupt_masked_debug;
82extern uint64_t interrupt_masked_timeout;
83extern uint64_t stackshot_interrupt_masked_timeout;
84
85#define INTERRUPT_MASKED_DEBUG_START(handler_addr, type) \
86do { \
87 if (interrupt_masked_debug) { \
88 thread_t thread = current_thread(); \
89 thread->machine.int_type = type; \
90 thread->machine.int_handler_addr = (uintptr_t)VM_KERNEL_STRIP_PTR(handler_addr); \
91 thread->machine.inthandler_timestamp = ml_get_timebase(); \
92 thread->machine.int_vector = (uintptr_t)NULL; \
93 } \
94} while (0)
95
96#define INTERRUPT_MASKED_DEBUG_END() \
97do { \
98 if (interrupt_masked_debug) { \
99 thread_t thread = current_thread(); \
100 ml_check_interrupt_handler_duration(thread); \
101 } \
102} while (0)
103
104void ml_irq_debug_start(uintptr_t handler, uintptr_t vector);
105void ml_irq_debug_end(void);
106
5ba3f43e
A
107void ml_spin_debug_reset(thread_t thread);
108void ml_spin_debug_clear(thread_t thread);
109void ml_spin_debug_clear_self(void);
110void ml_check_interrupts_disabled_duration(thread_t thread);
f427ee49
A
111void ml_check_stackshot_interrupt_disabled_duration(thread_t thread);
112void ml_check_interrupt_handler_duration(thread_t thread);
113#else
114#define INTERRUPT_MASKED_DEBUG_START(handler_addr, type)
115#define INTERRUPT_MASKED_DEBUG_END()
5ba3f43e
A
116#endif
117
118#ifdef XNU_KERNEL_PRIVATE
0a7de745 119extern bool ml_snoop_thread_is_on_core(thread_t thread);
5ba3f43e
A
120extern boolean_t ml_is_quiescing(void);
121extern void ml_set_is_quiescing(boolean_t);
122extern uint64_t ml_get_booter_memory_size(void);
123#endif
124
125/* Type for the Time Base Enable function */
126typedef void (*time_base_enable_t)(cpu_id_t cpu_id, boolean_t enable);
f427ee49 127#if defined(PEXPERT_KERNEL_PRIVATE) || defined(MACH_KERNEL_PRIVATE)
5ba3f43e
A
128/* Type for the Processor Cache Dispatch function */
129typedef void (*cache_dispatch_t)(cpu_id_t cpu_id, unsigned int select, unsigned int param0, unsigned int param1);
f427ee49
A
130
131typedef uint32_t (*get_decrementer_t)(void);
132typedef void (*set_decrementer_t)(uint32_t);
133typedef void (*fiq_handler_t)(void);
134
5ba3f43e
A
135#endif
136
0a7de745
A
137#define CacheConfig 0x00000000UL
138#define CacheControl 0x00000001UL
139#define CacheClean 0x00000002UL
140#define CacheCleanRegion 0x00000003UL
141#define CacheCleanFlush 0x00000004UL
142#define CacheCleanFlushRegion 0x00000005UL
143#define CacheShutdown 0x00000006UL
5ba3f43e 144
0a7de745 145#define CacheControlEnable 0x00000000UL
5ba3f43e 146
0a7de745
A
147#define CacheConfigCCSIDR 0x00000001UL
148#define CacheConfigSize 0x00000100UL
5ba3f43e
A
149
150/* Type for the Processor Idle function */
151typedef void (*processor_idle_t)(cpu_id_t cpu_id, boolean_t enter, uint64_t *new_timeout_ticks);
152
153/* Type for the Idle Tickle function */
154typedef void (*idle_tickle_t)(void);
155
156/* Type for the Idle Timer function */
157typedef void (*idle_timer_t)(void *refcon, uint64_t *new_timeout_ticks);
158
159/* Type for the IPI Hander */
160typedef void (*ipi_handler_t)(void);
161
162/* Type for the Lockdown Hander */
163typedef void (*lockdown_handler_t)(void *);
164
165/* Type for the Platform specific Error Handler */
166typedef void (*platform_error_handler_t)(void *refcon, vm_offset_t fault_addr);
167
168/*
0a7de745
A
169 * The exception callback (ex_cb) module allows kernel drivers to
170 * register and receive callbacks for exceptions, and indicate
5ba3f43e 171 * actions to be taken by the platform kernel
0a7de745 172 * Currently this is supported for ARM64 but extending support for ARM32
5ba3f43e
A
173 * should be straightforward
174 */
175
176/* Supported exception classes for callbacks */
0a7de745 177typedef enum{
5ba3f43e 178 EXCB_CLASS_ILLEGAL_INSTR_SET,
d9a64523
A
179#ifdef CONFIG_XNUPOST
180 EXCB_CLASS_TEST1,
181 EXCB_CLASS_TEST2,
182 EXCB_CLASS_TEST3,
183#endif
0a7de745 184 EXCB_CLASS_MAX // this must be last
5ba3f43e
A
185}
186ex_cb_class_t;
187
188/* Actions indicated by callbacks to be taken by platform kernel */
0a7de745
A
189typedef enum{
190 EXCB_ACTION_RERUN, // re-run the faulting instruction
191 EXCB_ACTION_NONE, // continue normal exception handling
d9a64523
A
192#ifdef CONFIG_XNUPOST
193 EXCB_ACTION_TEST_FAIL,
194#endif
5ba3f43e
A
195}
196ex_cb_action_t;
197
0a7de745
A
198/*
199 * Exception state
200 * We cannot use a private kernel data structure such as arm_saved_state_t
201 * The CPSR and ESR are not clobbered when the callback function is invoked so
5ba3f43e
A
202 * those registers can be examined by the callback function;
203 * the same is done in the platform error handlers
204 */
0a7de745 205typedef struct{
5ba3f43e
A
206 vm_offset_t far;
207}
208ex_cb_state_t;
209
210/* callback type definition */
211typedef ex_cb_action_t (*ex_cb_t) (
0a7de745
A
212 ex_cb_class_t cb_class,
213 void *refcon,// provided at registration
214 const ex_cb_state_t *state // exception state
5ba3f43e
A
215 );
216
0a7de745
A
217/*
218 * Callback registration
219 * Currently we support only one registered callback per class but
5ba3f43e
A
220 * it should be possible to support more callbacks
221 */
222kern_return_t ex_cb_register(
0a7de745
A
223 ex_cb_class_t cb_class,
224 ex_cb_t cb,
225 void *refcon );
5ba3f43e
A
226
227/*
228 * Called internally by platform kernel to invoke the registered callback for class
229 */
230ex_cb_action_t ex_cb_invoke(
0a7de745
A
231 ex_cb_class_t cb_class,
232 vm_offset_t far);
5ba3f43e
A
233
234
235void ml_parse_cpu_topology(void);
236
237unsigned int ml_get_cpu_count(void);
238
f427ee49
A
239unsigned int ml_get_cluster_count(void);
240
5ba3f43e
A
241int ml_get_boot_cpu_number(void);
242
243int ml_get_cpu_number(uint32_t phys_id);
244
f427ee49
A
245int ml_get_cluster_number(uint32_t phys_id);
246
5ba3f43e
A
247int ml_get_max_cpu_number(void);
248
f427ee49
A
249int ml_get_max_cluster_number(void);
250
251unsigned int ml_get_first_cpu_id(unsigned int cluster_id);
252
253#ifdef __arm64__
254int ml_get_cluster_number_local(void);
255unsigned int ml_get_cpu_number_local(void);
256#endif /* __arm64__ */
257
5ba3f43e
A
258/* Struct for ml_cpu_get_info */
259struct ml_cpu_info {
0a7de745
A
260 unsigned long vector_unit;
261 unsigned long cache_line_size;
262 unsigned long l1_icache_size;
263 unsigned long l1_dcache_size;
264 unsigned long l2_settings;
265 unsigned long l2_cache_size;
266 unsigned long l3_settings;
267 unsigned long l3_cache_size;
5ba3f43e
A
268};
269typedef struct ml_cpu_info ml_cpu_info_t;
270
271typedef enum {
272 CLUSTER_TYPE_SMP,
2a1bd2d3
A
273 CLUSTER_TYPE_E,
274 CLUSTER_TYPE_P,
5ba3f43e
A
275} cluster_type_t;
276
277cluster_type_t ml_get_boot_cluster(void);
278
f427ee49
A
279/*!
280 * @typedef ml_topology_cpu_t
281 * @brief Describes one CPU core in the topology.
282 *
283 * @field cpu_id Logical CPU ID (EDT: cpu-id): 0, 1, 2, 3, 4, ...
284 * @field phys_id Physical CPU ID (EDT: reg). Same as MPIDR[15:0], i.e.
285 * (cluster_id << 8) | core_number_within_cluster
286 * @field cluster_id Cluster ID (EDT: cluster-id)
287 * @field die_id Die ID (EDT: die-id)
288 * @field cluster_type The type of CPUs found in this cluster.
289 * @field l2_access_penalty Indicates that the scheduler should try to de-prioritize a core because
290 * L2 accesses are slower than on the boot processor.
291 * @field l2_cache_size Size of the L2 cache, in bytes. 0 if unknown or not present.
292 * @field l2_cache_id l2-cache-id property read from EDT.
293 * @field l3_cache_size Size of the L3 cache, in bytes. 0 if unknown or not present.
294 * @field l3_cache_id l3-cache-id property read from EDT.
295 * @field cpu_IMPL_regs IO-mapped virtual address of cpuX_IMPL (implementation-defined) register block.
296 * @field cpu_IMPL_pa Physical address of cpuX_IMPL register block.
297 * @field cpu_IMPL_len Length of cpuX_IMPL register block.
298 * @field cpu_UTTDBG_regs IO-mapped virtual address of cpuX_UTTDBG register block.
299 * @field cpu_UTTDBG_pa Physical address of cpuX_UTTDBG register block, if set in DT, else zero
300 * @field cpu_UTTDBG_len Length of cpuX_UTTDBG register block, if set in DT, else zero
301 * @field coresight_regs IO-mapped virtual address of CoreSight debug register block.
302 * @field coresight_pa Physical address of CoreSight register block.
303 * @field coresight_len Length of CoreSight register block.
f427ee49
A
304 * @field die_cluster_id Cluster ID within the local die (EDT: die-cluster-id)
305 * @field cluster_core_id Core ID within the local cluster (EDT: cluster-core-id)
306 */
307typedef struct ml_topology_cpu {
308 unsigned int cpu_id;
309 uint32_t phys_id;
310 unsigned int cluster_id;
311 unsigned int die_id;
312 cluster_type_t cluster_type;
313 uint32_t l2_access_penalty;
314 uint32_t l2_cache_size;
315 uint32_t l2_cache_id;
316 uint32_t l3_cache_size;
317 uint32_t l3_cache_id;
318 vm_offset_t cpu_IMPL_regs;
319 uint64_t cpu_IMPL_pa;
320 uint64_t cpu_IMPL_len;
321 vm_offset_t cpu_UTTDBG_regs;
322 uint64_t cpu_UTTDBG_pa;
323 uint64_t cpu_UTTDBG_len;
324 vm_offset_t coresight_regs;
325 uint64_t coresight_pa;
326 uint64_t coresight_len;
f427ee49
A
327 unsigned int die_cluster_id;
328 unsigned int cluster_core_id;
329} ml_topology_cpu_t;
330
331/*!
332 * @typedef ml_topology_cluster_t
333 * @brief Describes one cluster in the topology.
334 *
335 * @field cluster_id Cluster ID (EDT: cluster-id)
336 * @field cluster_type The type of CPUs found in this cluster.
337 * @field num_cpus Total number of usable CPU cores in this cluster.
338 * @field first_cpu_id The cpu_id of the first CPU in the cluster.
339 * @field cpu_mask A bitmask representing the cpu_id's that belong to the cluster. Example:
340 * If the cluster contains CPU4 and CPU5, cpu_mask will be 0x30.
341 * @field acc_IMPL_regs IO-mapped virtual address of acc_IMPL (implementation-defined) register block.
342 * @field acc_IMPL_pa Physical address of acc_IMPL register block.
343 * @field acc_IMPL_len Length of acc_IMPL register block.
344 * @field cpm_IMPL_regs IO-mapped virtual address of cpm_IMPL (implementation-defined) register block.
345 * @field cpm_IMPL_pa Physical address of cpm_IMPL register block.
346 * @field cpm_IMPL_len Length of cpm_IMPL register block.
347 */
348typedef struct ml_topology_cluster {
349 unsigned int cluster_id;
350 cluster_type_t cluster_type;
351 unsigned int num_cpus;
352 unsigned int first_cpu_id;
353 uint64_t cpu_mask;
354 vm_offset_t acc_IMPL_regs;
355 uint64_t acc_IMPL_pa;
356 uint64_t acc_IMPL_len;
357 vm_offset_t cpm_IMPL_regs;
358 uint64_t cpm_IMPL_pa;
359 uint64_t cpm_IMPL_len;
360} ml_topology_cluster_t;
361
362// Bump this version number any time any ml_topology_* struct changes, so
363// that KPI users can check whether their headers are compatible with
364// the running kernel.
365#define CPU_TOPOLOGY_VERSION 1
366
367/*!
368 * @typedef ml_topology_info_t
369 * @brief Describes the CPU topology for all APs in the system. Populated from EDT and read-only at runtime.
370 * @discussion This struct only lists CPU cores that are considered usable by both iBoot and XNU. Some
371 * physically present CPU cores may be considered unusable due to configuration options like
372 * the "cpus=" boot-arg. Cores that are disabled in hardware will not show up in EDT at all, so
373 * they also will not be present in this struct.
374 *
375 * @field version Version of the struct (set to CPU_TOPOLOGY_VERSION).
376 * @field num_cpus Total number of usable CPU cores.
377 * @field max_cpu_id The highest usable logical CPU ID.
378 * @field num_clusters Total number of AP CPU clusters on the system (usable or not).
379 * @field max_cluster_id The highest cluster ID found in EDT.
380 * @field cpus List of |num_cpus| entries.
381 * @field clusters List of |num_clusters| entries.
382 * @field boot_cpu Points to the |cpus| entry for the boot CPU.
383 * @field boot_cluster Points to the |clusters| entry which contains the boot CPU.
384 * @field chip_revision Silicon revision reported by iBoot, which comes from the
385 * SoC-specific fuse bits. See CPU_VERSION_xx macros for definitions.
386 */
387typedef struct ml_topology_info {
388 unsigned int version;
389 unsigned int num_cpus;
390 unsigned int max_cpu_id;
391 unsigned int num_clusters;
392 unsigned int max_cluster_id;
393 unsigned int max_die_id;
394 ml_topology_cpu_t *cpus;
395 ml_topology_cluster_t *clusters;
396 ml_topology_cpu_t *boot_cpu;
397 ml_topology_cluster_t *boot_cluster;
398 unsigned int chip_revision;
399} ml_topology_info_t;
400
401/*!
402 * @function ml_get_topology_info
403 * @result A pointer to the read-only topology struct. Does not need to be freed. Returns NULL
404 * if the struct hasn't been initialized or the feature is unsupported.
405 */
406const ml_topology_info_t *ml_get_topology_info(void);
407
408/*!
409 * @function ml_map_cpu_pio
410 * @brief Maps per-CPU and per-cluster PIO registers found in EDT. This needs to be
411 * called after arm_vm_init() so it can't be part of ml_parse_cpu_topology().
412 */
413void ml_map_cpu_pio(void);
414
5ba3f43e
A
415/* Struct for ml_processor_register */
416struct ml_processor_info {
0a7de745
A
417 cpu_id_t cpu_id;
418 vm_offset_t start_paddr;
419 boolean_t supports_nap;
420 void *platform_cache_dispatch;
421 time_base_enable_t time_base_enable;
422 processor_idle_t processor_idle;
423 idle_tickle_t *idle_tickle;
424 idle_timer_t idle_timer;
425 void *idle_timer_refcon;
426 vm_offset_t powergate_stub_addr;
427 uint32_t powergate_stub_length;
428 uint32_t powergate_latency;
429 platform_error_handler_t platform_error_handler;
430 uint64_t regmap_paddr;
431 uint32_t phys_id;
432 uint32_t log_id;
433 uint32_t l2_access_penalty;
434 uint32_t cluster_id;
435 cluster_type_t cluster_type;
436 uint32_t l2_cache_id;
437 uint32_t l2_cache_size;
438 uint32_t l3_cache_id;
439 uint32_t l3_cache_size;
5ba3f43e
A
440};
441typedef struct ml_processor_info ml_processor_info_t;
442
f427ee49 443#if defined(PEXPERT_KERNEL_PRIVATE) || defined(MACH_KERNEL_PRIVATE)
5ba3f43e
A
444/* Struct for ml_init_timebase */
445struct tbd_ops {
f427ee49
A
446 fiq_handler_t tbd_fiq_handler;
447 get_decrementer_t tbd_get_decrementer;
448 set_decrementer_t tbd_set_decrementer;
5ba3f43e
A
449};
450typedef struct tbd_ops *tbd_ops_t;
451typedef struct tbd_ops tbd_ops_data_t;
452#endif
453
0a7de745
A
454/*!
455 * @function ml_processor_register
456 *
457 * @abstract callback from platform kext to register processor
458 *
459 * @discussion This function is called by the platform kext when a processor is
460 * being registered. This is called while running on the CPU itself, as part of
461 * its initialization.
462 *
463 * @param ml_processor_info provides machine-specific information about the
464 * processor to xnu.
465 *
466 * @param processor is set as an out-parameter to an opaque handle that should
467 * be used by the platform kext when referring to this processor in the future.
468 *
469 * @param ipi_handler is set as an out-parameter to the function that should be
470 * registered as the IPI handler.
471 *
472 * @param pmi_handler is set as an out-parameter to the function that should be
473 * registered as the PMI handler.
474 *
475 * @returns KERN_SUCCESS on success and an error code, otherwise.
476 */
477kern_return_t ml_processor_register(ml_processor_info_t *ml_processor_info,
478 processor_t *processor, ipi_handler_t *ipi_handler,
479 perfmon_interrupt_handler_func *pmi_handler);
5ba3f43e
A
480
481/* Register a lockdown handler */
482kern_return_t ml_lockdown_handler_register(lockdown_handler_t, void *);
483
484#if XNU_KERNEL_PRIVATE
485void ml_lockdown_init(void);
486
5ba3f43e
A
487/* Machine layer routine for intercepting panics */
488void ml_panic_trap_to_debugger(const char *panic_format_str,
0a7de745
A
489 va_list *panic_args,
490 unsigned int reason,
491 void *ctx,
492 uint64_t panic_options_mask,
493 unsigned long panic_caller);
5ba3f43e
A
494#endif /* XNU_KERNEL_PRIVATE */
495
496/* Initialize Interrupts */
497void ml_install_interrupt_handler(
0a7de745
A
498 void *nub,
499 int source,
500 void *target,
501 IOInterruptHandler handler,
502 void *refCon);
5ba3f43e
A
503
504vm_offset_t
0a7de745 505 ml_static_vtop(
5ba3f43e
A
506 vm_offset_t);
507
f427ee49
A
508kern_return_t
509ml_static_verify_page_protections(
510 uint64_t base, uint64_t size, vm_prot_t prot);
511
5ba3f43e 512vm_offset_t
0a7de745 513 ml_static_ptovirt(
5ba3f43e
A
514 vm_offset_t);
515
d9a64523
A
516vm_offset_t ml_static_slide(
517 vm_offset_t vaddr);
518
519vm_offset_t ml_static_unslide(
520 vm_offset_t vaddr);
521
5ba3f43e
A
522/* Offset required to obtain absolute time value from tick counter */
523uint64_t ml_get_abstime_offset(void);
524
525/* Offset required to obtain continuous time value from tick counter */
526uint64_t ml_get_conttime_offset(void);
527
528#ifdef __APPLE_API_UNSTABLE
529/* PCI config cycle probing */
530boolean_t ml_probe_read(
531 vm_offset_t paddr,
532 unsigned int *val);
533boolean_t ml_probe_read_64(
534 addr64_t paddr,
535 unsigned int *val);
536
537/* Read physical address byte */
538unsigned int ml_phys_read_byte(
539 vm_offset_t paddr);
540unsigned int ml_phys_read_byte_64(
541 addr64_t paddr);
542
543/* Read physical address half word */
544unsigned int ml_phys_read_half(
545 vm_offset_t paddr);
546unsigned int ml_phys_read_half_64(
547 addr64_t paddr);
548
549/* Read physical address word*/
550unsigned int ml_phys_read(
551 vm_offset_t paddr);
552unsigned int ml_phys_read_64(
553 addr64_t paddr);
554unsigned int ml_phys_read_word(
555 vm_offset_t paddr);
556unsigned int ml_phys_read_word_64(
557 addr64_t paddr);
558
559unsigned long long ml_io_read(uintptr_t iovaddr, int iovsz);
560unsigned int ml_io_read8(uintptr_t iovaddr);
561unsigned int ml_io_read16(uintptr_t iovaddr);
562unsigned int ml_io_read32(uintptr_t iovaddr);
563unsigned long long ml_io_read64(uintptr_t iovaddr);
564
0a7de745
A
565extern void ml_io_write(uintptr_t vaddr, uint64_t val, int size);
566extern void ml_io_write8(uintptr_t vaddr, uint8_t val);
567extern void ml_io_write16(uintptr_t vaddr, uint16_t val);
568extern void ml_io_write32(uintptr_t vaddr, uint32_t val);
569extern void ml_io_write64(uintptr_t vaddr, uint64_t val);
570
5ba3f43e
A
571/* Read physical address double word */
572unsigned long long ml_phys_read_double(
573 vm_offset_t paddr);
574unsigned long long ml_phys_read_double_64(
575 addr64_t paddr);
576
577/* Write physical address byte */
578void ml_phys_write_byte(
579 vm_offset_t paddr, unsigned int data);
580void ml_phys_write_byte_64(
581 addr64_t paddr, unsigned int data);
582
583/* Write physical address half word */
584void ml_phys_write_half(
585 vm_offset_t paddr, unsigned int data);
586void ml_phys_write_half_64(
587 addr64_t paddr, unsigned int data);
588
589/* Write physical address word */
590void ml_phys_write(
591 vm_offset_t paddr, unsigned int data);
592void ml_phys_write_64(
593 addr64_t paddr, unsigned int data);
594void ml_phys_write_word(
595 vm_offset_t paddr, unsigned int data);
596void ml_phys_write_word_64(
597 addr64_t paddr, unsigned int data);
598
599/* Write physical address double word */
600void ml_phys_write_double(
601 vm_offset_t paddr, unsigned long long data);
602void ml_phys_write_double_64(
603 addr64_t paddr, unsigned long long data);
604
605void ml_static_mfree(
606 vm_offset_t,
607 vm_size_t);
608
609kern_return_t
610ml_static_protect(
0a7de745
A
611 vm_offset_t start,
612 vm_size_t size,
613 vm_prot_t new_prot);
5ba3f43e
A
614
615/* virtual to physical on wired pages */
616vm_offset_t ml_vtophys(
617 vm_offset_t vaddr);
618
f427ee49 619/* Get processor cache info */
5ba3f43e
A
620void ml_cpu_get_info(ml_cpu_info_t *ml_cpu_info);
621
622#endif /* __APPLE_API_UNSTABLE */
623
624#ifdef __APPLE_API_PRIVATE
0a7de745 625#ifdef XNU_KERNEL_PRIVATE
5ba3f43e 626vm_size_t ml_nofault_copy(
0a7de745
A
627 vm_offset_t virtsrc,
628 vm_offset_t virtdst,
5ba3f43e
A
629 vm_size_t size);
630boolean_t ml_validate_nofault(
631 vm_offset_t virtsrc, vm_size_t size);
632#endif /* XNU_KERNEL_PRIVATE */
0a7de745 633#if defined(PEXPERT_KERNEL_PRIVATE) || defined(MACH_KERNEL_PRIVATE)
5ba3f43e
A
634/* IO memory map services */
635
636/* Map memory map IO space */
637vm_offset_t ml_io_map(
0a7de745 638 vm_offset_t phys_addr,
5ba3f43e
A
639 vm_size_t size);
640
641vm_offset_t ml_io_map_wcomb(
0a7de745 642 vm_offset_t phys_addr,
5ba3f43e
A
643 vm_size_t size);
644
cb323159
A
645vm_offset_t ml_io_map_with_prot(
646 vm_offset_t phys_addr,
647 vm_size_t size,
648 vm_prot_t prot);
649
f427ee49
A
650void ml_io_unmap(
651 vm_offset_t addr,
652 vm_size_t sz);
653
5ba3f43e
A
654void ml_get_bouncepool_info(
655 vm_offset_t *phys_addr,
656 vm_size_t *size);
657
658vm_map_address_t ml_map_high_window(
0a7de745
A
659 vm_offset_t phys_addr,
660 vm_size_t len);
5ba3f43e
A
661
662/* boot memory allocation */
663vm_offset_t ml_static_malloc(
664 vm_size_t size);
665
666void ml_init_timebase(
0a7de745
A
667 void *args,
668 tbd_ops_t tbd_funcs,
669 vm_offset_t int_address,
670 vm_offset_t int_value);
5ba3f43e
A
671
672uint64_t ml_get_timebase(void);
673
2a1bd2d3
A
674uint64_t ml_get_speculative_timebase(void);
675
676uint64_t ml_get_timebase_entropy(void);
677
5ba3f43e
A
678void ml_init_lock_timeout(void);
679
c3c9b80d
A
680#if __arm64__
681uint64_t virtual_timeout_inflate_ns(unsigned int vti, uint64_t timeout);
682uint64_t virtual_timeout_inflate_abs(unsigned int vti, uint64_t timeout);
683#endif
684
5ba3f43e
A
685boolean_t ml_delay_should_spin(uint64_t interval);
686
e8c3f781
A
687void ml_delay_on_yield(void);
688
5ba3f43e
A
689uint32_t ml_get_decrementer(void);
690
f427ee49
A
691#include <machine/config.h>
692
693#if !CONFIG_SKIP_PRECISE_USER_KERNEL_TIME || HAS_FAST_CNTVCT
5ba3f43e
A
694void timer_state_event_user_to_kernel(void);
695void timer_state_event_kernel_to_user(void);
f427ee49 696#endif /* !CONFIG_SKIP_PRECISE_USER_KERNEL_TIME || HAS_FAST_CNTVCT */
5ba3f43e
A
697
698uint64_t ml_get_hwclock(void);
699
700#ifdef __arm64__
701boolean_t ml_get_timer_pending(void);
702#endif
703
704void platform_syscall(
705 struct arm_saved_state *);
706
707void ml_set_decrementer(
708 uint32_t dec_value);
709
710boolean_t is_user_contex(
711 void);
712
713void ml_init_arm_debug_interface(void *args, vm_offset_t virt_address);
714
715/* These calls are only valid if __ARM_USER_PROTECT__ is defined */
716uintptr_t arm_user_protect_begin(
0a7de745 717 thread_t thread);
5ba3f43e
A
718
719void arm_user_protect_end(
0a7de745
A
720 thread_t thread,
721 uintptr_t up,
722 boolean_t disable_interrupts);
5ba3f43e
A
723
724#endif /* PEXPERT_KERNEL_PRIVATE || MACH_KERNEL_PRIVATE */
725
726/* Zero bytes starting at a physical address */
727void bzero_phys(
728 addr64_t phys_address,
729 vm_size_t length);
730
731void bzero_phys_nc(addr64_t src64, vm_size_t bytes);
732
cb323159
A
733#if MACH_KERNEL_PRIVATE
734#ifdef __arm64__
735/* Pattern-fill buffer with zeros or a 32-bit pattern;
736 * target must be 128-byte aligned and sized a multiple of 128
737 * Both variants emit stores with non-temporal properties.
738 */
739void fill32_dczva(addr64_t, vm_size_t);
740void fill32_nt(addr64_t, vm_size_t, uint32_t);
f427ee49 741int cpu_interrupt_is_pending(void);
cb323159
A
742#endif
743#endif
744
5ba3f43e
A
745void ml_thread_policy(
746 thread_t thread,
747 unsigned policy_id,
748 unsigned policy_info);
749
0a7de745
A
750#define MACHINE_GROUP 0x00000001
751#define MACHINE_NETWORK_GROUP 0x10000000
752#define MACHINE_NETWORK_WORKLOOP 0x00000001
753#define MACHINE_NETWORK_NETISR 0x00000002
5ba3f43e 754
f427ee49
A
755/* Set the maximum number of CPUs */
756void ml_set_max_cpus(
5ba3f43e
A
757 unsigned int max_cpus);
758
f427ee49
A
759/* Return the maximum number of CPUs set by ml_set_max_cpus(), waiting if necessary */
760unsigned int ml_wait_max_cpus(
5ba3f43e
A
761 void);
762
763/* Return the maximum memory size */
764unsigned int ml_get_machine_mem(void);
765
766#ifdef XNU_KERNEL_PRIVATE
767/* Return max offset */
768vm_map_offset_t ml_get_max_offset(
0a7de745 769 boolean_t is64,
5ba3f43e 770 unsigned int option);
0a7de745
A
771#define MACHINE_MAX_OFFSET_DEFAULT 0x01
772#define MACHINE_MAX_OFFSET_MIN 0x02
773#define MACHINE_MAX_OFFSET_MAX 0x04
774#define MACHINE_MAX_OFFSET_DEVICE 0x08
5ba3f43e
A
775#endif
776
c3c9b80d 777extern void ml_cpu_init_completed(void);
0a7de745
A
778extern void ml_cpu_up(void);
779extern void ml_cpu_down(void);
780extern void ml_arm_sleep(void);
5ba3f43e
A
781
782extern uint64_t ml_get_wake_timebase(void);
783extern uint64_t ml_get_conttime_wake_time(void);
784
785/* Time since the system was reset (as part of boot/wake) */
786uint64_t ml_get_time_since_reset(void);
787
cb323159
A
788/*
789 * Called by ApplePMGR to set wake time. Units and epoch are identical
790 * to mach_continuous_time(). Has no effect on !HAS_CONTINUOUS_HWCLOCK
791 * chips. If wake_time == UINT64_MAX, that means the wake time is
792 * unknown and calls to ml_get_time_since_reset() will return UINT64_MAX.
793 */
794void ml_set_reset_time(uint64_t wake_time);
795
5ba3f43e
A
796#ifdef XNU_KERNEL_PRIVATE
797/* Just a stub on ARM */
798extern kern_return_t ml_interrupt_prewarm(uint64_t deadline);
799#define TCOAL_DEBUG(x, a, b, c, d, e) do { } while(0)
800#endif /* XNU_KERNEL_PRIVATE */
801
802/* Bytes available on current stack */
803vm_offset_t ml_stack_remaining(void);
804
805#ifdef MACH_KERNEL_PRIVATE
0a7de745
A
806uint32_t get_fpscr(void);
807void set_fpscr(uint32_t);
f427ee49
A
808void machine_conf(void);
809void machine_lockdown(void);
5ba3f43e 810
d9a64523
A
811#ifdef __arm64__
812unsigned long update_mdscr(unsigned long clear, unsigned long set);
813#endif /* __arm64__ */
814
0a7de745
A
815extern void arm_debug_set_cp14(arm_debug_state_t *debug_state);
816extern void fiq_context_init(boolean_t enable_fiq);
5ba3f43e 817
0a7de745 818extern void reenable_async_aborts(void);
f427ee49
A
819#ifdef __arm__
820extern boolean_t get_vfp_enabled(void);
0a7de745 821extern void cpu_idle_wfi(boolean_t wfi_fast);
f427ee49
A
822#endif
823
824#ifdef __arm64__
825uint64_t ml_cluster_wfe_timeout(uint32_t wfe_cluster_id);
826#endif
5ba3f43e
A
827
828#ifdef MONITOR
0a7de745
A
829#define MONITOR_SET_ENTRY 0x800 /* Set kernel entry point from monitor */
830#define MONITOR_LOCKDOWN 0x801 /* Enforce kernel text/rodata integrity */
831unsigned long monitor_call(uintptr_t callnum, uintptr_t arg1,
832 uintptr_t arg2, uintptr_t arg3);
5ba3f43e
A
833#endif /* MONITOR */
834
5c9f4661
A
835#if __ARM_KERNEL_PROTECT__
836extern void set_vbar_el1(uint64_t);
837#endif /* __ARM_KERNEL_PROTECT__ */
5ba3f43e
A
838#endif /* MACH_KERNEL_PRIVATE */
839
0a7de745 840extern uint32_t arm_debug_read_dscr(void);
5ba3f43e 841
0a7de745
A
842extern int set_be_bit(void);
843extern int clr_be_bit(void);
844extern int be_tracing(void);
5ba3f43e 845
f427ee49
A
846/* Please note that cpu_broadcast_xcall is not as simple is you would like it to be.
847 * It will sometimes put the calling thread to sleep, and it is up to your callback
848 * to wake it up as needed, where "as needed" is defined as "all other CPUs have
849 * called the broadcast func". Look around the kernel for examples, or instead use
850 * cpu_broadcast_xcall_simple() which does indeed act like you would expect, given
851 * the prototype. cpu_broadcast_immediate_xcall has the same caveats and has a similar
852 * _simple() wrapper
853 */
5ba3f43e
A
854typedef void (*broadcastFunc) (void *);
855unsigned int cpu_broadcast_xcall(uint32_t *, boolean_t, broadcastFunc, void *);
f427ee49 856unsigned int cpu_broadcast_xcall_simple(boolean_t, broadcastFunc, void *);
5ba3f43e 857kern_return_t cpu_xcall(int, broadcastFunc, void *);
cb323159 858unsigned int cpu_broadcast_immediate_xcall(uint32_t *, boolean_t, broadcastFunc, void *);
f427ee49 859unsigned int cpu_broadcast_immediate_xcall_simple(boolean_t, broadcastFunc, void *);
cb323159 860kern_return_t cpu_immediate_xcall(int, broadcastFunc, void *);
5ba3f43e
A
861
862#ifdef KERNEL_PRIVATE
863
864/* Interface to be used by the perf. controller to register a callback, in a
865 * single-threaded fashion. The callback will receive notifications of
866 * processor performance quality-of-service changes from the scheduler.
867 */
868
869#ifdef __arm64__
870typedef void (*cpu_qos_update_t)(int throughput_qos, uint64_t qos_param1, uint64_t qos_param2);
871void cpu_qos_update_register(cpu_qos_update_t);
872#endif /* __arm64__ */
873
874struct going_on_core {
0a7de745
A
875 uint64_t thread_id;
876 uint16_t qos_class;
877 uint16_t urgency; /* XCPM compatibility */
878 uint32_t is_32_bit : 1; /* uses 32-bit ISA/register state in userspace (which may differ from address space size) */
879 uint32_t is_kernel_thread : 1;
880 uint64_t thread_group_id;
881 void *thread_group_data;
882 uint64_t scheduling_latency; /* absolute time between when thread was made runnable and this ctx switch */
883 uint64_t start_time;
884 uint64_t scheduling_latency_at_same_basepri;
885 uint32_t energy_estimate_nj; /* return: In nanojoules */
886 /* smaller of the time between last change to base priority and ctx switch and scheduling_latency */
5ba3f43e
A
887};
888typedef struct going_on_core *going_on_core_t;
889
890struct going_off_core {
0a7de745
A
891 uint64_t thread_id;
892 uint32_t energy_estimate_nj; /* return: In nanojoules */
893 uint32_t reserved;
894 uint64_t end_time;
895 uint64_t thread_group_id;
896 void *thread_group_data;
5ba3f43e
A
897};
898typedef struct going_off_core *going_off_core_t;
899
900struct thread_group_data {
0a7de745
A
901 uint64_t thread_group_id;
902 void *thread_group_data;
903 uint32_t thread_group_size;
904 uint32_t thread_group_flags;
5ba3f43e
A
905};
906typedef struct thread_group_data *thread_group_data_t;
907
908struct perfcontrol_max_runnable_latency {
0a7de745 909 uint64_t max_scheduling_latencies[4 /* THREAD_URGENCY_MAX */];
5ba3f43e
A
910};
911typedef struct perfcontrol_max_runnable_latency *perfcontrol_max_runnable_latency_t;
912
913struct perfcontrol_work_interval {
0a7de745
A
914 uint64_t thread_id;
915 uint16_t qos_class;
916 uint16_t urgency;
917 uint32_t flags; // notify
918 uint64_t work_interval_id;
919 uint64_t start;
920 uint64_t finish;
921 uint64_t deadline;
922 uint64_t next_start;
923 uint64_t thread_group_id;
924 void *thread_group_data;
925 uint32_t create_flags;
5ba3f43e
A
926};
927typedef struct perfcontrol_work_interval *perfcontrol_work_interval_t;
928
a39ff7e2
A
929typedef enum {
930 WORK_INTERVAL_START,
931 WORK_INTERVAL_UPDATE,
932 WORK_INTERVAL_FINISH
933} work_interval_ctl_t;
934
935struct perfcontrol_work_interval_instance {
0a7de745
A
936 work_interval_ctl_t ctl;
937 uint32_t create_flags;
938 uint64_t complexity;
939 uint64_t thread_id;
940 uint64_t work_interval_id;
941 uint64_t instance_id; /* out: start, in: update/finish */
942 uint64_t start;
943 uint64_t finish;
944 uint64_t deadline;
945 uint64_t thread_group_id;
946 void *thread_group_data;
a39ff7e2
A
947};
948typedef struct perfcontrol_work_interval_instance *perfcontrol_work_interval_instance_t;
5ba3f43e 949
0a7de745
A
950/*
951 * Structure to export per-CPU counters as part of the CLPC callout.
952 * Contains only the fixed CPU counters (instructions and cycles); CLPC
953 * would call back into XNU to get the configurable counters if needed.
5ba3f43e
A
954 */
955struct perfcontrol_cpu_counters {
0a7de745 956 uint64_t instructions;
5ba3f43e
A
957 uint64_t cycles;
958};
959
960/*
961 * Structure used to pass information about a thread to CLPC
962 */
963struct perfcontrol_thread_data {
964 /*
965 * Energy estimate (return value)
0a7de745 966 * The field is populated by CLPC and used to update the
5ba3f43e
A
967 * energy estimate of the thread
968 */
969 uint32_t energy_estimate_nj;
970 /* Perfcontrol class for thread */
971 perfcontrol_class_t perfctl_class;
972 /* Thread ID for the thread */
973 uint64_t thread_id;
974 /* Thread Group ID */
975 uint64_t thread_group_id;
0a7de745
A
976 /*
977 * Scheduling latency for threads at the same base priority.
978 * Calculated by the scheduler and passed into CLPC. The field is
979 * populated only in the thread_data structure for the thread
980 * going on-core.
5ba3f43e
A
981 */
982 uint64_t scheduling_latency_at_same_basepri;
983 /* Thread Group data pointer */
984 void *thread_group_data;
985 /* perfctl state pointer */
986 void *perfctl_state;
987};
988
989/*
990 * All callouts from the scheduler are executed with interrupts
991 * disabled. Callouts should be implemented in C with minimal
992 * abstractions, and only use KPI exported by the mach/libkern
993 * symbolset, restricted to routines like spinlocks and atomic
994 * operations and scheduler routines as noted below. Spinlocks that
995 * are used to synchronize data in the perfcontrol_state_t should only
996 * ever be acquired with interrupts disabled, to avoid deadlocks where
997 * an quantum expiration timer interrupt attempts to perform a callout
998 * that attempts to lock a spinlock that is already held.
999 */
1000
1001/*
1002 * When a processor is switching between two threads (after the
1003 * scheduler has chosen a new thread), the low-level platform layer
1004 * will call this routine, which should perform required timestamps,
1005 * MMIO register reads, or other state switching. No scheduler locks
1006 * are held during this callout.
1007 *
1008 * This function is called with interrupts ENABLED.
1009 */
1010typedef void (*sched_perfcontrol_context_switch_t)(perfcontrol_state_t, perfcontrol_state_t);
1011
1012/*
1013 * Once the processor has switched to the new thread, the offcore
1014 * callout will indicate the old thread that is no longer being
1015 * run. The thread's scheduler lock is held, so it will not begin
1016 * running on another processor (in the case of preemption where it
1017 * remains runnable) until it completes. If the "thread_terminating"
1018 * boolean is TRUE, this will be the last callout for this thread_id.
1019 */
1020typedef void (*sched_perfcontrol_offcore_t)(perfcontrol_state_t, going_off_core_t /* populated by callee */, boolean_t);
1021
1022/*
1023 * After the offcore callout and after the old thread can potentially
1024 * start running on another processor, the oncore callout will be
1025 * called with the thread's scheduler lock held. The oncore callout is
1026 * also called any time one of the parameters in the going_on_core_t
1027 * structure changes, like priority/QoS changes, and quantum
1028 * expiration, so the callout must not assume callouts are paired with
1029 * offcore callouts.
1030 */
1031typedef void (*sched_perfcontrol_oncore_t)(perfcontrol_state_t, going_on_core_t);
1032
1033/*
1034 * Periodically (on hundreds of ms scale), the scheduler will perform
1035 * maintenance and report the maximum latency for runnable (but not currently
1036 * running) threads for each urgency class.
1037 */
1038typedef void (*sched_perfcontrol_max_runnable_latency_t)(perfcontrol_max_runnable_latency_t);
1039
1040/*
1041 * When the kernel receives information about work intervals from userland,
1042 * it is passed along using this callback. No locks are held, although the state
1043 * object will not go away during the callout.
1044 */
1045typedef void (*sched_perfcontrol_work_interval_notify_t)(perfcontrol_state_t, perfcontrol_work_interval_t);
1046
a39ff7e2
A
1047/*
1048 * Start, update and finish work interval instance with optional complexity estimate.
1049 */
1050typedef void (*sched_perfcontrol_work_interval_ctl_t)(perfcontrol_state_t, perfcontrol_work_interval_instance_t);
1051
5ba3f43e
A
1052/*
1053 * These callbacks are used when thread groups are added, removed or properties
1054 * updated.
1055 * No blocking allocations (or anything else blocking) are allowed inside these
1056 * callbacks. No locks allowed in these callbacks as well since the kernel might
1057 * be holding the thread/task locks.
1058 */
1059typedef void (*sched_perfcontrol_thread_group_init_t)(thread_group_data_t);
1060typedef void (*sched_perfcontrol_thread_group_deinit_t)(thread_group_data_t);
1061typedef void (*sched_perfcontrol_thread_group_flags_update_t)(thread_group_data_t);
1062
1063/*
1064 * Sometime after the timeout set by sched_perfcontrol_update_callback_deadline has passed,
1065 * this function will be called, passing the timeout deadline that was previously armed as an argument.
1066 *
1067 * This is called inside context-switch/quantum-interrupt context and must follow the safety rules for that context.
1068 */
1069typedef void (*sched_perfcontrol_deadline_passed_t)(uint64_t deadline);
1070
1071/*
1072 * Context Switch Callout
0a7de745 1073 *
5ba3f43e
A
1074 * Parameters:
1075 * event - The perfcontrol_event for this callout
1076 * cpu_id - The CPU doing the context switch
1077 * timestamp - The timestamp for the context switch
1078 * flags - Flags for other relevant information
1079 * offcore - perfcontrol_data structure for thread going off-core
1080 * oncore - perfcontrol_data structure for thread going on-core
1081 * cpu_counters - perfcontrol_cpu_counters for the CPU doing the switch
1082 */
1083typedef void (*sched_perfcontrol_csw_t)(
1084 perfcontrol_event event, uint32_t cpu_id, uint64_t timestamp, uint32_t flags,
1085 struct perfcontrol_thread_data *offcore, struct perfcontrol_thread_data *oncore,
1086 struct perfcontrol_cpu_counters *cpu_counters, __unused void *unused);
1087
1088
1089/*
1090 * Thread State Update Callout
1091 *
1092 * Parameters:
1093 * event - The perfcontrol_event for this callout
1094 * cpu_id - The CPU doing the state update
1095 * timestamp - The timestamp for the state update
1096 * flags - Flags for other relevant information
1097 * thr_data - perfcontrol_data structure for the thread being updated
1098 */
1099typedef void (*sched_perfcontrol_state_update_t)(
1100 perfcontrol_event event, uint32_t cpu_id, uint64_t timestamp, uint32_t flags,
1101 struct perfcontrol_thread_data *thr_data, __unused void *unused);
1102
f427ee49
A
1103/*
1104 * Thread Group Blocking Relationship Callout
1105 *
1106 * Parameters:
1107 * blocked_tg - Thread group blocking on progress of another thread group
1108 * blocking_tg - Thread group blocking progress of another thread group
1109 * flags - Flags for other relevant information
1110 * blocked_thr_state - Per-thread perfcontrol state for blocked thread
1111 */
1112typedef void (*sched_perfcontrol_thread_group_blocked_t)(
1113 thread_group_data_t blocked_tg, thread_group_data_t blocking_tg, uint32_t flags, perfcontrol_state_t blocked_thr_state);
1114
1115/*
1116 * Thread Group Unblocking Callout
1117 *
1118 * Parameters:
1119 * unblocked_tg - Thread group being unblocked from making forward progress
1120 * unblocking_tg - Thread group unblocking progress of another thread group
1121 * flags - Flags for other relevant information
1122 * unblocked_thr_state - Per-thread perfcontrol state for unblocked thread
1123 */
1124typedef void (*sched_perfcontrol_thread_group_unblocked_t)(
1125 thread_group_data_t unblocked_tg, thread_group_data_t unblocking_tg, uint32_t flags, perfcontrol_state_t unblocked_thr_state);
1126
5ba3f43e
A
1127/*
1128 * Callers should always use the CURRENT version so that the kernel can detect both older
1129 * and newer structure layouts. New callbacks should always be added at the end of the
1130 * structure, and xnu should expect existing source recompiled against newer headers
1131 * to pass NULL for unimplemented callbacks. Pass NULL as the as the callbacks parameter
1132 * to reset callbacks to their default in-kernel values.
1133 */
1134
1135#define SCHED_PERFCONTROL_CALLBACKS_VERSION_0 (0) /* up-to oncore */
1136#define SCHED_PERFCONTROL_CALLBACKS_VERSION_1 (1) /* up-to max_runnable_latency */
1137#define SCHED_PERFCONTROL_CALLBACKS_VERSION_2 (2) /* up-to work_interval_notify */
1138#define SCHED_PERFCONTROL_CALLBACKS_VERSION_3 (3) /* up-to thread_group_deinit */
1139#define SCHED_PERFCONTROL_CALLBACKS_VERSION_4 (4) /* up-to deadline_passed */
1140#define SCHED_PERFCONTROL_CALLBACKS_VERSION_5 (5) /* up-to state_update */
1141#define SCHED_PERFCONTROL_CALLBACKS_VERSION_6 (6) /* up-to thread_group_flags_update */
a39ff7e2 1142#define SCHED_PERFCONTROL_CALLBACKS_VERSION_7 (7) /* up-to work_interval_ctl */
f427ee49 1143#define SCHED_PERFCONTROL_CALLBACKS_VERSION_8 (8) /* up-to thread_group_unblocked */
5ba3f43e
A
1144#define SCHED_PERFCONTROL_CALLBACKS_VERSION_CURRENT SCHED_PERFCONTROL_CALLBACKS_VERSION_6
1145
1146struct sched_perfcontrol_callbacks {
1147 unsigned long version; /* Use SCHED_PERFCONTROL_CALLBACKS_VERSION_CURRENT */
1148 sched_perfcontrol_offcore_t offcore;
1149 sched_perfcontrol_context_switch_t context_switch;
1150 sched_perfcontrol_oncore_t oncore;
1151 sched_perfcontrol_max_runnable_latency_t max_runnable_latency;
1152 sched_perfcontrol_work_interval_notify_t work_interval_notify;
1153 sched_perfcontrol_thread_group_init_t thread_group_init;
1154 sched_perfcontrol_thread_group_deinit_t thread_group_deinit;
1155 sched_perfcontrol_deadline_passed_t deadline_passed;
1156 sched_perfcontrol_csw_t csw;
1157 sched_perfcontrol_state_update_t state_update;
1158 sched_perfcontrol_thread_group_flags_update_t thread_group_flags_update;
a39ff7e2 1159 sched_perfcontrol_work_interval_ctl_t work_interval_ctl;
f427ee49
A
1160 sched_perfcontrol_thread_group_blocked_t thread_group_blocked;
1161 sched_perfcontrol_thread_group_unblocked_t thread_group_unblocked;
5ba3f43e
A
1162};
1163typedef struct sched_perfcontrol_callbacks *sched_perfcontrol_callbacks_t;
1164
1165extern void sched_perfcontrol_register_callbacks(sched_perfcontrol_callbacks_t callbacks, unsigned long size_of_state);
1166
1167/*
1168 * Update the scheduler with the set of cores that should be used to dispatch new threads.
1169 * Non-recommended cores can still be used to field interrupts or run bound threads.
1170 * This should be called with interrupts enabled and no scheduler locks held.
1171 */
0a7de745 1172#define ALL_CORES_RECOMMENDED (~(uint32_t)0)
5ba3f43e
A
1173
1174extern void sched_perfcontrol_update_recommended_cores(uint32_t recommended_cores);
1175extern void sched_perfcontrol_thread_group_recommend(void *data, cluster_type_t recommendation);
d9a64523
A
1176extern void sched_override_recommended_cores_for_sleep(void);
1177extern void sched_restore_recommended_cores_after_sleep(void);
f427ee49 1178extern void sched_perfcontrol_inherit_recommendation_from_tg(perfcontrol_class_t perfctl_class, boolean_t inherit);
5ba3f43e 1179
0a7de745
A
1180extern void sched_usercontrol_update_recommended_cores(uint64_t recommended_cores);
1181
f427ee49
A
1182/*
1183 * Edge Scheduler-CLPC Interface
1184 *
1185 * sched_perfcontrol_thread_group_preferred_clusters_set()
1186 *
1187 * The Edge scheduler expects thread group recommendations to be specific clusters rather
1188 * than just E/P. In order to allow more fine grained control, CLPC can specify an override
1189 * preferred cluster per QoS bucket. CLPC passes a common preferred cluster `tg_preferred_cluster`
1190 * and an array of size [PERFCONTROL_CLASS_MAX] with overrides for specific perfctl classes.
1191 * The scheduler translates these preferences into sched_bucket
1192 * preferences and applies the changes.
1193 *
1194 */
1195/* Token to indicate a particular perfctl class is not overriden */
1196#define SCHED_PERFCONTROL_PREFERRED_CLUSTER_OVERRIDE_NONE ((uint32_t)~0)
1197
1198/*
1199 * CLPC can also indicate if there should be an immediate rebalancing of threads of this TG as
1200 * part of this preferred cluster change. It does that by specifying the following options.
1201 */
1202#define SCHED_PERFCONTROL_PREFERRED_CLUSTER_MIGRATE_RUNNING 0x1
1203#define SCHED_PERFCONTROL_PREFERRED_CLUSTER_MIGRATE_RUNNABLE 0x2
1204typedef uint64_t sched_perfcontrol_preferred_cluster_options_t;
1205
1206extern void sched_perfcontrol_thread_group_preferred_clusters_set(void *machine_data, uint32_t tg_preferred_cluster,
1207 uint32_t overrides[PERFCONTROL_CLASS_MAX], sched_perfcontrol_preferred_cluster_options_t options);
1208
1209/*
1210 * Edge Scheduler-CLPC Interface
1211 *
1212 * sched_perfcontrol_edge_matrix_get()/sched_perfcontrol_edge_matrix_set()
1213 *
1214 * The Edge scheduler uses edges between clusters to define the likelihood of migrating threads
1215 * across clusters. The edge config between any two clusters defines the edge weight and whether
1216 * migation and steal operations are allowed across that edge. The getter and setter allow CLPC
1217 * to query and configure edge properties between various clusters on the platform.
1218 */
1219
1220extern void sched_perfcontrol_edge_matrix_get(sched_clutch_edge *edge_matrix, bool *edge_request_bitmap, uint64_t flags, uint64_t matrix_order);
1221extern void sched_perfcontrol_edge_matrix_set(sched_clutch_edge *edge_matrix, bool *edge_changes_bitmap, uint64_t flags, uint64_t matrix_order);
1222
5ba3f43e
A
1223/*
1224 * Update the deadline after which sched_perfcontrol_deadline_passed will be called.
1225 * Returns TRUE if it successfully canceled a previously set callback,
1226 * and FALSE if it did not (i.e. one wasn't set, or callback already fired / is in flight).
1227 * The callback is automatically canceled when it fires, and does not repeat unless rearmed.
1228 *
1229 * This 'timer' executes as the scheduler switches between threads, on a non-idle core
1230 *
1231 * There can be only one outstanding timer globally.
1232 */
1233extern boolean_t sched_perfcontrol_update_callback_deadline(uint64_t deadline);
1234
1235typedef enum perfcontrol_callout_type {
0a7de745
A
1236 PERFCONTROL_CALLOUT_ON_CORE,
1237 PERFCONTROL_CALLOUT_OFF_CORE,
1238 PERFCONTROL_CALLOUT_CONTEXT,
1239 PERFCONTROL_CALLOUT_STATE_UPDATE,
1240 /* Add other callout types here */
1241 PERFCONTROL_CALLOUT_MAX
5ba3f43e
A
1242} perfcontrol_callout_type_t;
1243
1244typedef enum perfcontrol_callout_stat {
0a7de745
A
1245 PERFCONTROL_STAT_INSTRS,
1246 PERFCONTROL_STAT_CYCLES,
1247 /* Add other stat types here */
1248 PERFCONTROL_STAT_MAX
5ba3f43e
A
1249} perfcontrol_callout_stat_t;
1250
1251uint64_t perfcontrol_callout_stat_avg(perfcontrol_callout_type_t type,
0a7de745 1252 perfcontrol_callout_stat_t stat);
5ba3f43e 1253
f427ee49
A
1254#ifdef __arm64__
1255/* The performance controller may use this interface to recommend
1256 * that CPUs in the designated cluster employ WFE rather than WFI
1257 * within the idle loop, falling back to WFI after the specified
1258 * timeout. The updates are expected to be serialized by the caller,
1259 * the implementation is not required to perform internal synchronization.
1260 */
1261uint32_t ml_update_cluster_wfe_recommendation(uint32_t wfe_cluster_id, uint64_t wfe_timeout_abstime_interval, uint64_t wfe_hint_flags);
1262#endif /* __arm64__ */
1263
cb323159
A
1264#if defined(HAS_APPLE_PAC)
1265#define ONES(x) (BIT((x))-1)
1266#define PTR_MASK ONES(64-T1SZ_BOOT)
1267#define PAC_MASK ~PTR_MASK
1268#define SIGN(p) ((p) & BIT(55))
1269#define UNSIGN_PTR(p) \
1270 SIGN(p) ? ((p) | PAC_MASK) : ((p) & ~PAC_MASK)
1271
a991bd8d 1272uint64_t ml_default_rop_pid(void);
f427ee49 1273uint64_t ml_default_jop_pid(void);
cb323159 1274void ml_task_set_rop_pid(task_t task, task_t parent_task, boolean_t inherit);
f427ee49
A
1275void ml_task_set_jop_pid(task_t task, task_t parent_task, boolean_t inherit);
1276void ml_task_set_jop_pid_from_shared_region(task_t task);
1277void ml_task_set_disable_user_jop(task_t task, uint8_t disable_user_jop);
1278void ml_thread_set_disable_user_jop(thread_t thread, uint8_t disable_user_jop);
1279void ml_thread_set_jop_pid(thread_t thread, task_t task);
cb323159 1280void *ml_auth_ptr_unchecked(void *ptr, unsigned key, uint64_t modifier);
f427ee49 1281
f427ee49
A
1282uint64_t ml_enable_user_jop_key(uint64_t user_jop_key);
1283
1284/**
1285 * Restores the previous JOP key state after a previous ml_enable_user_jop_key()
1286 * call.
1287 *
1288 * @param user_jop_key The userspace JOP key previously passed to
1289 * ml_enable_user_jop_key()
1290 * @param saved_jop_state The saved JOP state returned by
1291 * ml_enable_user_jop_key()
1292 */
1293void ml_disable_user_jop_key(uint64_t user_jop_key, uint64_t saved_jop_state);
cb323159
A
1294#endif /* defined(HAS_APPLE_PAC) */
1295
2a1bd2d3 1296void ml_enable_monitor(void);
cb323159 1297
5ba3f43e
A
1298
1299#endif /* KERNEL_PRIVATE */
1300
1301boolean_t machine_timeout_suspended(void);
1302void ml_get_power_state(boolean_t *, boolean_t *);
1303
0a7de745 1304uint32_t get_arm_cpu_version(void);
5ba3f43e 1305boolean_t user_cont_hwclock_allowed(void);
cb323159 1306uint8_t user_timebase_type(void);
5ba3f43e 1307boolean_t ml_thread_is64bit(thread_t thread);
5ba3f43e
A
1308
1309#ifdef __arm64__
f427ee49 1310bool ml_feature_supported(uint32_t feature_bit);
5ba3f43e 1311void ml_set_align_checking(void);
f427ee49
A
1312extern void wfe_timeout_configure(void);
1313extern void wfe_timeout_init(void);
5ba3f43e
A
1314#endif /* __arm64__ */
1315
1316void ml_timer_evaluate(void);
1317boolean_t ml_timer_forced_evaluation(void);
1318uint64_t ml_energy_stat(thread_t);
1319void ml_gpu_stat_update(uint64_t);
1320uint64_t ml_gpu_stat(thread_t);
1321#endif /* __APPLE_API_PRIVATE */
1322
f427ee49
A
1323
1324
1325#if __arm64__ && defined(CONFIG_XNUPOST) && defined(XNU_KERNEL_PRIVATE)
1326extern void ml_expect_fault_begin(expected_fault_handler_t, uintptr_t);
1327extern void ml_expect_fault_end(void);
1328#endif /* __arm64__ && defined(CONFIG_XNUPOST) && defined(XNU_KERNEL_PRIVATE) */
1329
1330
1331void ml_hibernate_active_pre(void);
1332void ml_hibernate_active_post(void);
1333
5ba3f43e
A
1334__END_DECLS
1335
1336#endif /* _ARM_MACHINE_ROUTINES_H_ */