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