2 * Copyright (c) 2007-2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <machine/asm.h>
30 #include <arm64/machine_machdep.h>
31 #include <arm64/proc_reg.h>
33 #include <pexpert/arm64/board_config.h>
34 #include <sys/errno.h>
39 /* uint32_t get_fpscr(void):
40 * Returns (FPSR | FPCR).
46 mrs x1, FPSR // Grab FPSR
47 mov x4, #(FPSR_MASK & 0xFFFF)
48 mov x5, #(FPSR_MASK & 0xFFFF0000)
50 and x1, x1, x0 // Be paranoid, and clear bits we expect to
52 mrs x2, FPCR // Grab FPCR
53 mov x4, #(FPCR_MASK & 0xFFFF)
54 mov x5, #(FPCR_MASK & 0xFFFF0000)
56 and x2, x2, x0 // Be paranoid, and clear bits we expect to
58 orr x0, x1, x2 // OR them to get FPSCR equivalent state
65 /* void set_fpscr(uint32_t value):
66 * Set the FPCR and FPSR registers, based on the given value; a
67 * noteworthy point is that unlike 32-bit mode, 64-bit mode FPSR
68 * and FPCR are not responsible for condition codes.
72 mov x4, #(FPSR_MASK & 0xFFFF)
73 mov x5, #(FPSR_MASK & 0xFFFF0000)
75 and x1, x1, x0 // Clear the bits that don't apply to FPSR
76 mov x4, #(FPCR_MASK & 0xFFFF)
77 mov x5, #(FPCR_MASK & 0xFFFF0000)
79 and x2, x2, x0 // Clear the bits that don't apply to FPCR
80 msr FPSR, x1 // Write FPCR
81 msr FPCR, x2 // Write FPSR
82 dsb ish // FPCR requires synchronization
87 * void update_mdscr(unsigned long clear, unsigned long set)
88 * Clears and sets the specified bits in MDSCR_EL1.
90 * Setting breakpoints in EL1 is effectively a KTRR bypass. The ability to do so is
91 * controlled by MDSCR.KDE. The MSR to set MDSCR must be present to allow
92 * self-hosted user mode debug. Any checks before the MRS can be skipped with ROP,
93 * so we need to put the checks after the MRS where they can't be skipped. That
94 * still leaves a small window if a breakpoint is set on the instruction
95 * immediately after the MRS. To handle that, we also do a check and then set of
96 * the breakpoint control registers. This allows us to guarantee that a given
97 * core will never have both KDE set and a breakpoint targeting EL1.
99 * If KDE gets set, unset it and then panic
102 .globl EXT(update_mdscr)
111 #if defined(CONFIG_KERNEL_INTEGRITY)
113 * verify KDE didn't get set (including via ROP)
114 * If set, clear it and then panic
120 b.ne Lupdate_mdscr_panic
125 adrp x0, Lupdate_mdscr_panic_str@page
126 add x0, x0, Lupdate_mdscr_panic_str@pageoff
130 Lupdate_mdscr_panic_str:
131 .asciz "MDSCR.KDE was set"
134 #if __ARM_KERNEL_PROTECT__
136 * __ARM_KERNEL_PROTECT__ adds two complications to TLB management:
138 * 1. As each pmap has two ASIDs, every TLB operation that targets an ASID must
139 * target both ASIDs for the pmap that owns the target ASID.
141 * 2. Any TLB operation targeting the kernel_pmap ASID (ASID 0) must target all
142 * ASIDs (as kernel_pmap mappings may be referenced while using an ASID that
143 * belongs to another pmap). We expect these routines to be called with the
144 * EL0 ASID for the target; not the EL1 ASID.
146 #endif /* __ARM_KERNEL_PROTECT__ */
148 .macro SYNC_TLB_FLUSH
155 * void sync_tlb_flush(void)
157 * Synchronize one or more prior TLB flush operations
161 .globl EXT(sync_tlb_flush)
171 * void flush_mmu_tlb_async(void)
173 * Flush all TLBs, don't wait for completion
177 .globl EXT(flush_mmu_tlb_async)
178 LEXT(flush_mmu_tlb_async)
183 * void flush_mmu_tlb(void)
189 .globl EXT(flush_mmu_tlb)
195 .macro FLUSH_CORE_TLB
200 * void flush_core_tlb_async(void)
202 * Flush local core TLB, don't wait for completion
206 .globl EXT(flush_core_tlb_async)
207 LEXT(flush_core_tlb_async)
212 * void flush_core_tlb(void)
214 * Flush local core TLB
218 .globl EXT(flush_core_tlb)
224 .macro FLUSH_MMU_TLB_ALLENTRIES
229 * The code below is not necessarily correct. From an overview of
230 * the client code, the expected contract for TLB flushes is that
231 * we will expand from an "address, length" pair to "start address,
232 * end address" in the course of a TLB flush. This suggests that
233 * a flush for "X, X+4" is actually only asking for a flush of a
234 * single 16KB page. At the same time, we'd like to be prepared
235 * for bad inputs (X, X+3), so add 3 and then truncate the 4KB page
236 * number to a 16KB page boundary. This should deal correctly with
239 * If our expecations about client behavior are wrong however, this
240 * will lead to occasional TLB corruption on platforms with 16KB
246 1: // Lflush_mmu_tlb_allentries_loop:
248 add x0, x0, #(ARM_PGBYTES / 4096) // Units are 4KB pages, as defined by the ISA
250 b.lt 1b // Lflush_mmu_tlb_allentries_loop
254 * void flush_mmu_tlb_allentries_async(uint64_t, uint64_t)
256 * Flush TLB entries, don't wait for completion
260 .globl EXT(flush_mmu_tlb_allentries_async)
261 LEXT(flush_mmu_tlb_allentries_async)
262 FLUSH_MMU_TLB_ALLENTRIES
266 * void flush_mmu_tlb_allentries(uint64_t, uint64_t)
270 .globl EXT(flush_mmu_tlb_allentries)
271 LEXT(flush_mmu_tlb_allentries)
272 FLUSH_MMU_TLB_ALLENTRIES
276 .macro FLUSH_MMU_TLB_ENTRY
277 #if __ARM_KERNEL_PROTECT__
279 * If we are flushing ASID 0, this is a kernel operation. With this
280 * ASID scheme, this means we should flush all ASIDs.
282 lsr x2, x0, #TLBI_ASID_SHIFT
284 b.eq 1f // Lflush_mmu_tlb_entry_globally
286 bic x0, x0, #(1 << TLBI_ASID_SHIFT)
288 orr x0, x0, #(1 << TLBI_ASID_SHIFT)
289 #endif /* __ARM_KERNEL_PROTECT__ */
291 #if __ARM_KERNEL_PROTECT__
292 b 2f // Lflush_mmu_tlb_entry_done
293 1: // Lflush_mmu_tlb_entry_globally:
295 2: // Lflush_mmu_tlb_entry_done
296 #endif /* __ARM_KERNEL_PROTECT__ */
299 * void flush_mmu_tlb_entry_async(uint64_t)
301 * Flush TLB entry, don't wait for completion
305 .globl EXT(flush_mmu_tlb_entry_async)
306 LEXT(flush_mmu_tlb_entry_async)
311 * void flush_mmu_tlb_entry(uint64_t)
317 .globl EXT(flush_mmu_tlb_entry)
318 LEXT(flush_mmu_tlb_entry)
323 .macro FLUSH_MMU_TLB_ENTRIES
328 * The code below is not necessarily correct. From an overview of
329 * the client code, the expected contract for TLB flushes is that
330 * we will expand from an "address, length" pair to "start address,
331 * end address" in the course of a TLB flush. This suggests that
332 * a flush for "X, X+4" is actually only asking for a flush of a
333 * single 16KB page. At the same time, we'd like to be prepared
334 * for bad inputs (X, X+3), so add 3 and then truncate the 4KB page
335 * number to a 16KB page boundary. This should deal correctly with
338 * If our expecations about client behavior are wrong however, this
339 * will lead to occasional TLB corruption on platforms with 16KB
344 #endif /* __ARM_16K_PG__ */
345 #if __ARM_KERNEL_PROTECT__
347 * If we are flushing ASID 0, this is a kernel operation. With this
348 * ASID scheme, this means we should flush all ASIDs.
350 lsr x2, x0, #TLBI_ASID_SHIFT
352 b.eq 2f // Lflush_mmu_tlb_entries_globally_loop
354 bic x0, x0, #(1 << TLBI_ASID_SHIFT)
355 #endif /* __ARM_KERNEL_PROTECT__ */
356 1: // Lflush_mmu_tlb_entries_loop
358 #if __ARM_KERNEL_PROTECT__
359 orr x0, x0, #(1 << TLBI_ASID_SHIFT)
361 bic x0, x0, #(1 << TLBI_ASID_SHIFT)
362 #endif /* __ARM_KERNEL_PROTECT__ */
363 add x0, x0, #(ARM_PGBYTES / 4096) // Units are pages
365 b.lt 1b // Lflush_mmu_tlb_entries_loop
366 #if __ARM_KERNEL_PROTECT__
367 b 3f // Lflush_mmu_tlb_entries_done
368 2: // Lflush_mmu_tlb_entries_globally_loop:
370 add x0, x0, #(ARM_PGBYTES / 4096) // Units are pages
372 b.lt 2b // Lflush_mmu_tlb_entries_globally_loop
373 3: // Lflush_mmu_tlb_entries_done
374 #endif /* __ARM_KERNEL_PROTECT__ */
378 * void flush_mmu_tlb_entries_async(uint64_t, uint64_t)
380 * Flush TLB entries, don't wait for completion
384 .globl EXT(flush_mmu_tlb_entries_async)
385 LEXT(flush_mmu_tlb_entries_async)
386 FLUSH_MMU_TLB_ENTRIES
390 * void flush_mmu_tlb_entries(uint64_t, uint64_t)
396 .globl EXT(flush_mmu_tlb_entries)
397 LEXT(flush_mmu_tlb_entries)
398 FLUSH_MMU_TLB_ENTRIES
402 .macro FLUSH_MMU_TLB_ASID
403 #if __ARM_KERNEL_PROTECT__
405 * If we are flushing ASID 0, this is a kernel operation. With this
406 * ASID scheme, this means we should flush all ASIDs.
408 lsr x1, x0, #TLBI_ASID_SHIFT
410 b.eq 1f // Lflush_mmu_tlb_globally
412 bic x0, x0, #(1 << TLBI_ASID_SHIFT)
414 orr x0, x0, #(1 << TLBI_ASID_SHIFT)
415 #endif /* __ARM_KERNEL_PROTECT__ */
417 #if __ARM_KERNEL_PROTECT__
418 b 2f // Lflush_mmu_tlb_asid_done
419 1: // Lflush_mmu_tlb_globally:
421 2: // Lflush_mmu_tlb_asid_done:
422 #endif /* __ARM_KERNEL_PROTECT__ */
426 * void flush_mmu_tlb_asid_async(uint64_t)
428 * Flush TLB entriesfor requested asid, don't wait for completion
432 .globl EXT(flush_mmu_tlb_asid_async)
433 LEXT(flush_mmu_tlb_asid_async)
438 * void flush_mmu_tlb_asid(uint64_t)
440 * Flush TLB entriesfor requested asid
444 .globl EXT(flush_mmu_tlb_asid)
445 LEXT(flush_mmu_tlb_asid)
450 .macro FLUSH_CORE_TLB_ASID
451 #if __ARM_KERNEL_PROTECT__
453 * If we are flushing ASID 0, this is a kernel operation. With this
454 * ASID scheme, this means we should flush all ASIDs.
456 lsr x1, x0, #TLBI_ASID_SHIFT
458 b.eq 1f // Lflush_core_tlb_asid_globally
460 bic x0, x0, #(1 << TLBI_ASID_SHIFT)
462 orr x0, x0, #(1 << TLBI_ASID_SHIFT)
463 #endif /* __ARM_KERNEL_PROTECT__ */
465 #if __ARM_KERNEL_PROTECT__
466 b 2f // Lflush_core_tlb_asid_done
467 1: // Lflush_core_tlb_asid_globally:
469 2: // Lflush_core_tlb_asid_done:
470 #endif /* __ARM_KERNEL_PROTECT__ */
474 * void flush_core_tlb_asid_async(uint64_t)
476 * Flush TLB entries for core for requested asid, don't wait for completion
480 .globl EXT(flush_core_tlb_asid_async)
481 LEXT(flush_core_tlb_asid_async)
485 * void flush_core_tlb_asid(uint64_t)
487 * Flush TLB entries for core for requested asid
491 .globl EXT(flush_core_tlb_asid)
492 LEXT(flush_core_tlb_asid)
498 * Set MMU Translation Table Base Alternate
502 .globl EXT(set_mmu_ttb_alternate)
503 LEXT(set_mmu_ttb_alternate)
505 #if defined(KERNEL_INTEGRITY_KTRR)
507 bl EXT(pinst_set_ttbr1)
511 #endif /* defined(KERNEL_INTEGRITY_KTRR) */
517 .globl EXT(set_mmu_ttb)
519 #if __ARM_KERNEL_PROTECT__
520 /* All EL1-mode ASIDs are odd. */
521 orr x0, x0, #(1 << TTBR_ASID_SHIFT)
522 #endif /* __ARM_KERNEL_PROTECT__ */
529 * set AUX control register
533 .globl EXT(set_aux_control)
534 LEXT(set_aux_control)
536 // Synchronize system
541 #if __ARM_KERNEL_PROTECT__
544 .globl EXT(set_vbar_el1)
546 #if defined(KERNEL_INTEGRITY_KTRR)
547 b EXT(pinst_set_vbar)
552 #endif /* __ARM_KERNEL_PROTECT__ */
556 * set translation control register
562 #if defined(APPLE_ARM64_ARCH_FAMILY)
563 // Assert that T0Z is always equal to T1Z
564 eor x1, x0, x0, lsr #(TCR_T1SZ_SHIFT - TCR_T0SZ_SHIFT)
565 and x1, x1, #(TCR_TSZ_MASK << TCR_T0SZ_SHIFT)
566 cbnz x1, L_set_tcr_panic
567 #if defined(KERNEL_INTEGRITY_KTRR)
573 #endif /* defined(KERNEL_INTRITY_KTRR) */
581 adr x0, L_set_tcr_panic_str
584 L_set_locked_reg_panic:
588 adr x0, L_set_locked_reg_panic_str
593 .asciz "set_tcr: t0sz, t1sz not equal (%llx)\n"
596 L_set_locked_reg_panic_str:
597 .asciz "attempt to set locked register: (%llx)\n"
599 #if defined(KERNEL_INTEGRITY_KTRR)
608 #endif // defined(APPLE_ARM64_ARCH_FAMILY)
611 * MMU kernel virtual to physical address translation
615 .globl EXT(mmu_kvtop)
617 mrs x2, DAIF // Load current DAIF
618 msr DAIFSet, #(DAIFSC_IRQF | DAIFSC_FIQF) // Disable IRQ
619 at s1e1r, x0 // Translation Stage 1 EL1
620 mrs x1, PAR_EL1 // Read result
621 msr DAIF, x2 // Restore interrupt state
622 tbnz x1, #0, L_mmu_kvtop_invalid // Test Translation not valid
623 bfm x1, x0, #0, #11 // Add page offset
624 and x0, x1, #0x0000ffffffffffff // Clear non-address bits
627 mov x0, #0 // Return invalid
631 * MMU user virtual to physical address translation
635 .globl EXT(mmu_uvtop)
637 lsr x8, x0, #56 // Extract top byte
638 cbnz x8, L_mmu_uvtop_invalid // Tagged pointers are invalid
639 mrs x2, DAIF // Load current DAIF
640 msr DAIFSet, #(DAIFSC_IRQF | DAIFSC_FIQF) // Disable IRQ
641 at s1e0r, x0 // Translation Stage 1 EL0
642 mrs x1, PAR_EL1 // Read result
643 msr DAIF, x2 // Restore interrupt state
644 tbnz x1, #0, L_mmu_uvtop_invalid // Test Translation not valid
645 bfm x1, x0, #0, #11 // Add page offset
646 and x0, x1, #0x0000ffffffffffff // Clear non-address bits
649 mov x0, #0 // Return invalid
653 * MMU kernel virtual to physical address preflight write access
657 .globl EXT(mmu_kvtop_wpreflight)
658 LEXT(mmu_kvtop_wpreflight)
659 mrs x2, DAIF // Load current DAIF
660 msr DAIFSet, #(DAIFSC_IRQF | DAIFSC_FIQF) // Disable IRQ
661 at s1e1w, x0 // Translation Stage 1 EL1
662 mrs x1, PAR_EL1 // Read result
663 msr DAIF, x2 // Restore interrupt state
664 tbnz x1, #0, L_mmu_kvtop_wpreflight_invalid // Test Translation not valid
665 bfm x1, x0, #0, #11 // Add page offset
666 and x0, x1, #0x0000ffffffffffff // Clear non-address bits
668 L_mmu_kvtop_wpreflight_invalid:
669 mov x0, #0 // Return invalid
673 * SET_RECOVERY_HANDLER
675 * Sets up a page fault recovery handler
677 * arg0 - persisted thread pointer
678 * arg1 - persisted recovery handler
680 * arg3 - recovery label
682 .macro SET_RECOVERY_HANDLER
683 mrs $0, TPIDR_EL1 // Load thread pointer
684 adrp $2, $3@page // Load the recovery handler address
685 add $2, $2, $3@pageoff
687 ldr $1, [$0, TH_RECOVER] // Save previous recovery handler
688 str $2, [$0, TH_RECOVER] // Set new signed recovery handler
692 * CLEAR_RECOVERY_HANDLER
694 * Clears page fault handler set by SET_RECOVERY_HANDLER
696 * arg0 - thread pointer saved by SET_RECOVERY_HANDLER
697 * arg1 - old recovery handler saved by SET_RECOVERY_HANDLER
699 .macro CLEAR_RECOVERY_HANDLER
700 str $1, [$0, TH_RECOVER] // Restore the previous recovery handler
707 CLEAR_RECOVERY_HANDLER x10, x11
708 mov x0, #EFAULT // Return an EFAULT error
713 * int _bcopyin(const char *src, char *dst, vm_size_t len)
721 SET_RECOVERY_HANDLER x10, x11, x3, copyio_error
722 /* If len is less than 16 bytes, just do a bytewise copy */
727 /* 16 bytes at a time */
728 ldp x3, x4, [x0], #16
729 stp x3, x4, [x1], #16
732 /* Fixup the len and test for completion */
741 CLEAR_RECOVERY_HANDLER x10, x11
747 * int _copyin_word(const char *src, uint64_t *dst, vm_size_t len)
751 .globl EXT(_copyin_word)
755 SET_RECOVERY_HANDLER x10, x11, x3, copyio_error
764 b L_copyin_word_store
770 CLEAR_RECOVERY_HANDLER x10, x11
778 * int _bcopyout(const char *src, char *dst, vm_size_t len)
782 .globl EXT(_bcopyout)
786 SET_RECOVERY_HANDLER x10, x11, x3, copyio_error
787 /* If len is less than 16 bytes, just do a bytewise copy */
792 /* 16 bytes at a time */
793 ldp x3, x4, [x0], #16
794 stp x3, x4, [x1], #16
797 /* Fixup the len and test for completion */
806 CLEAR_RECOVERY_HANDLER x10, x11
813 * const user_addr_t user_addr,
820 .globl EXT(_bcopyinstr)
824 adr x4, Lcopyinstr_error // Get address for recover
825 mrs x10, TPIDR_EL1 // Get thread pointer
826 ldr x11, [x10, TH_RECOVER] // Save previous recover
828 str x4, [x10, TH_RECOVER] // Store new recover
830 mov x4, #0 // x4 - total bytes copied
832 ldrb w5, [x0], #1 // Load a byte from the user source
833 strb w5, [x1], #1 // Store a byte to the kernel dest
834 add x4, x4, #1 // Increment bytes copied
835 cbz x5, Lcopyinstr_done // If this byte is null, we're done
836 cmp x4, x2 // If we're out of space, return an error
839 mov x5, #ENAMETOOLONG // Set current byte to error code for later return
841 str x4, [x3] // Return number of bytes copied
842 mov x0, x5 // Set error code (0 on success, ENAMETOOLONG on failure)
845 mov x0, #EFAULT // Return EFAULT on error
847 str x11, [x10, TH_RECOVER] // Restore old recover
852 * int copyinframe(const vm_address_t frame_addr, char *kernel_addr, bool is64bit)
854 * Safely copy sixteen bytes (the fixed top of an ARM64 frame) from
855 * either user or kernel memory, or 8 bytes (AArch32) from user only.
857 * x0 : address of frame to copy.
858 * x1 : kernel address at which to store data.
859 * w2 : whether to copy an AArch32 or AArch64 frame.
861 * x5 : temp (kernel virtual base)
863 * x10 : thread pointer (set by SET_RECOVERY_HANDLER)
864 * x11 : old recovery function (set by SET_RECOVERY_HANDLER)
865 * x12, x13 : backtrace data
870 .globl EXT(copyinframe)
874 SET_RECOVERY_HANDLER x10, x11, x3, copyio_error
875 cbnz w2, Lcopyinframe64 // Check frame size
876 adrp x5, EXT(gVirtBase)@page // For 32-bit frame, make sure we're not trying to copy from kernel
877 add x5, x5, EXT(gVirtBase)@pageoff
879 cmp x5, x0 // See if address is in kernel virtual range
880 b.hi Lcopyinframe32 // If below kernel virtual range, proceed.
881 mov w0, #EFAULT // Should never have a 32-bit frame in kernel virtual range
885 ldr x12, [x0] // Copy 8 bytes
887 mov w0, #0 // Success
891 mov x3, VM_MIN_KERNEL_ADDRESS // Check if kernel address
892 orr x9, x0, TBI_MASK // Hide tags in address comparison
893 cmp x9, x3 // If in kernel address range, skip tag test
894 b.hs Lcopyinframe_valid
895 tst x0, TBI_MASK // Detect tagged pointers
896 b.eq Lcopyinframe_valid
897 mov w0, #EFAULT // Tagged address, fail
900 ldp x12, x13, [x0] // Copy 16 bytes
902 mov w0, #0 // Success
905 CLEAR_RECOVERY_HANDLER x10, x11
911 * uint32_t arm_debug_read_dscr(void)
915 .globl EXT(arm_debug_read_dscr)
916 LEXT(arm_debug_read_dscr)
920 * void arm_debug_set_cp14(arm_debug_state_t *debug_state)
922 * Set debug registers to match the current thread state
923 * (NULL to disable). Assume 6 breakpoints and 2
924 * watchpoints, since that has been the case in all cores
929 .globl EXT(arm_debug_set_cp14)
930 LEXT(arm_debug_set_cp14)
933 #if defined(APPLE_ARM64_ARCH_FAMILY)
935 * Note: still have to ISB before executing wfi!
939 .globl EXT(arm64_prepare_for_sleep)
940 LEXT(arm64_prepare_for_sleep)
943 #if defined(APPLECYCLONE) || defined(APPLETYPHOON)
944 // <rdar://problem/15827409> CPU1 Stuck in WFIWT Because of MMU Prefetch
945 mrs x0, ARM64_REG_HID2 // Read HID2
946 orr x0, x0, #(ARM64_REG_HID2_disMMUmtlbPrefetch) // Set HID.DisableMTLBPrefetch
947 msr ARM64_REG_HID2, x0 // Write HID2
952 #if __ARM_GLOBAL_SLEEP_BIT__
954 mrs x1, ARM64_REG_ACC_OVRD
955 orr x1, x1, #(ARM64_REG_ACC_OVRD_enDeepSleep)
956 and x1, x1, #(~(ARM64_REG_ACC_OVRD_disL2Flush4AccSlp_mask))
957 orr x1, x1, #( ARM64_REG_ACC_OVRD_disL2Flush4AccSlp_deepsleep)
958 and x1, x1, #(~(ARM64_REG_ACC_OVRD_ok2PwrDnSRM_mask))
959 orr x1, x1, #( ARM64_REG_ACC_OVRD_ok2PwrDnSRM_deepsleep)
960 and x1, x1, #(~(ARM64_REG_ACC_OVRD_ok2TrDnLnk_mask))
961 orr x1, x1, #( ARM64_REG_ACC_OVRD_ok2TrDnLnk_deepsleep)
962 and x1, x1, #(~(ARM64_REG_ACC_OVRD_ok2PwrDnCPM_mask))
963 orr x1, x1, #( ARM64_REG_ACC_OVRD_ok2PwrDnCPM_deepsleep)
964 msr ARM64_REG_ACC_OVRD, x1
969 mov x1, ARM64_REG_CYC_CFG_deepSleep
970 msr ARM64_REG_CYC_CFG, x1
972 // Set "OK to power down" (<rdar://problem/12390433>)
973 mrs x0, ARM64_REG_CYC_OVRD
974 orr x0, x0, #(ARM64_REG_CYC_OVRD_ok2pwrdn_force_down)
975 msr ARM64_REG_CYC_OVRD, x0
977 #if defined(APPLEMONSOON)
979 cbz x0, Lwfi_inst // skip if not p-core
981 /* <rdar://problem/32512947>: Flush the GUPS prefetcher prior to
982 * wfi. A Skye HW bug can cause the GUPS prefetcher on p-cores
983 * to be left with valid entries that fail to drain if a
984 * subsequent wfi is issued. This can prevent the core from
985 * power-gating. For the idle case that is recoverable, but
986 * for the deep-sleep (S2R) case in which cores MUST power-gate,
987 * it can lead to a hang. This can be prevented by disabling
988 * and re-enabling GUPS, which forces the prefetch queue to
989 * drain. This should be done as close to wfi as possible, i.e.
990 * at the very end of arm64_prepare_for_sleep(). */
991 mrs x0, ARM64_REG_HID10
992 orr x0, x0, #(ARM64_REG_HID10_DisHwpGups)
993 msr ARM64_REG_HID10, x0
995 and x0, x0, #(~(ARM64_REG_HID10_DisHwpGups))
996 msr ARM64_REG_HID10, x0
1006 * Force WFI to use clock gating only
1011 .globl EXT(arm64_force_wfi_clock_gate)
1012 LEXT(arm64_force_wfi_clock_gate)
1016 mrs x0, ARM64_REG_CYC_OVRD
1017 orr x0, x0, #(ARM64_REG_CYC_OVRD_ok2pwrdn_force_up)
1018 msr ARM64_REG_CYC_OVRD, x0
1025 #if defined(APPLECYCLONE) || defined(APPLETYPHOON)
1029 .globl EXT(cyclone_typhoon_prepare_for_wfi)
1031 LEXT(cyclone_typhoon_prepare_for_wfi)
1034 // <rdar://problem/15827409> CPU1 Stuck in WFIWT Because of MMU Prefetch
1035 mrs x0, ARM64_REG_HID2 // Read HID2
1036 orr x0, x0, #(ARM64_REG_HID2_disMMUmtlbPrefetch) // Set HID.DisableMTLBPrefetch
1037 msr ARM64_REG_HID2, x0 // Write HID2
1047 .globl EXT(cyclone_typhoon_return_from_wfi)
1048 LEXT(cyclone_typhoon_return_from_wfi)
1051 // <rdar://problem/15827409> CPU1 Stuck in WFIWT Because of MMU Prefetch
1052 mrs x0, ARM64_REG_HID2 // Read HID2
1053 mov x1, #(ARM64_REG_HID2_disMMUmtlbPrefetch) //
1054 bic x0, x0, x1 // Clear HID.DisableMTLBPrefetchMTLBPrefetch
1055 msr ARM64_REG_HID2, x0 // Write HID2
1065 #define HID0_DEFEATURES_1 0x0000a0c000064010ULL
1066 #define HID1_DEFEATURES_1 0x000000004005bf20ULL
1067 #define HID2_DEFEATURES_1 0x0000000000102074ULL
1068 #define HID3_DEFEATURES_1 0x0000000000400003ULL
1069 #define HID4_DEFEATURES_1 0x83ff00e100000268ULL
1070 #define HID7_DEFEATURES_1 0x000000000000000eULL
1072 #define HID0_DEFEATURES_2 0x0000a1c000020010ULL
1073 #define HID1_DEFEATURES_2 0x000000000005d720ULL
1074 #define HID2_DEFEATURES_2 0x0000000000002074ULL
1075 #define HID3_DEFEATURES_2 0x0000000000400001ULL
1076 #define HID4_DEFEATURES_2 0x8390000200000208ULL
1077 #define HID7_DEFEATURES_2 0x0000000000000000ULL
1080 arg0 = target register
1081 arg1 = 64-bit constant
1084 movz $0, #(($1 >> 48) & 0xffff), lsl #48
1085 movk $0, #(($1 >> 32) & 0xffff), lsl #32
1086 movk $0, #(($1 >> 16) & 0xffff), lsl #16
1087 movk $0, #(($1) & 0xffff)
1092 .globl EXT(cpu_defeatures_set)
1093 LEXT(cpu_defeatures_set)
1096 b.eq cpu_defeatures_set_2
1098 b.ne cpu_defeatures_set_ret
1099 LOAD_UINT64 x1, HID0_DEFEATURES_1
1100 mrs x0, ARM64_REG_HID0
1102 msr ARM64_REG_HID0, x0
1103 LOAD_UINT64 x1, HID1_DEFEATURES_1
1104 mrs x0, ARM64_REG_HID1
1106 msr ARM64_REG_HID1, x0
1107 LOAD_UINT64 x1, HID2_DEFEATURES_1
1108 mrs x0, ARM64_REG_HID2
1110 msr ARM64_REG_HID2, x0
1111 LOAD_UINT64 x1, HID3_DEFEATURES_1
1112 mrs x0, ARM64_REG_HID3
1114 msr ARM64_REG_HID3, x0
1115 LOAD_UINT64 x1, HID4_DEFEATURES_1
1116 mrs x0, ARM64_REG_HID4
1118 msr ARM64_REG_HID4, x0
1119 LOAD_UINT64 x1, HID7_DEFEATURES_1
1120 mrs x0, ARM64_REG_HID7
1122 msr ARM64_REG_HID7, x0
1125 b cpu_defeatures_set_ret
1126 cpu_defeatures_set_2:
1127 LOAD_UINT64 x1, HID0_DEFEATURES_2
1128 mrs x0, ARM64_REG_HID0
1130 msr ARM64_REG_HID0, x0
1131 LOAD_UINT64 x1, HID1_DEFEATURES_2
1132 mrs x0, ARM64_REG_HID1
1134 msr ARM64_REG_HID1, x0
1135 LOAD_UINT64 x1, HID2_DEFEATURES_2
1136 mrs x0, ARM64_REG_HID2
1138 msr ARM64_REG_HID2, x0
1139 LOAD_UINT64 x1, HID3_DEFEATURES_2
1140 mrs x0, ARM64_REG_HID3
1142 msr ARM64_REG_HID3, x0
1143 LOAD_UINT64 x1, HID4_DEFEATURES_2
1144 mrs x0, ARM64_REG_HID4
1146 msr ARM64_REG_HID4, x0
1147 LOAD_UINT64 x1, HID7_DEFEATURES_2
1148 mrs x0, ARM64_REG_HID7
1150 msr ARM64_REG_HID7, x0
1153 b cpu_defeatures_set_ret
1154 cpu_defeatures_set_ret:
1159 #else /* !defined(APPLE_ARM64_ARCH_FAMILY) */
1162 .globl EXT(arm64_prepare_for_sleep)
1163 LEXT(arm64_prepare_for_sleep)
1172 * Force WFI to use clock gating only
1173 * Note: for non-Apple device, do nothing.
1177 .globl EXT(arm64_force_wfi_clock_gate)
1178 LEXT(arm64_force_wfi_clock_gate)
1183 #endif /* defined(APPLE_ARM64_ARCH_FAMILY) */
1186 * void arm64_replace_bootstack(cpu_data_t *cpu_data)
1188 * This must be called from a kernel thread context running on the boot CPU,
1189 * after setting up new exception stacks in per-CPU data. That will guarantee
1190 * that the stack(s) we're trying to replace aren't currently in use. For
1191 * KTRR-protected devices, this must also be called prior to VM prot finalization
1192 * and lockdown, as updating SP1 requires a sensitive instruction.
1196 .globl EXT(arm64_replace_bootstack)
1197 LEXT(arm64_replace_bootstack)
1200 // Set the exception stack pointer
1201 ldr x0, [x0, CPU_EXCEPSTACK_TOP]
1202 mrs x4, DAIF // Load current DAIF; use x4 as pinst may trash x1-x3
1203 msr DAIFSet, #(DAIFSC_IRQF | DAIFSC_FIQF | DAIFSC_ASYNCF) // Disable IRQ/FIQ/serror
1204 // Set SP_EL1 to exception stack
1205 #if defined(KERNEL_INTEGRITY_KTRR)
1214 msr DAIF, x4 // Restore interrupt state
1220 * unsigned long monitor_call(uintptr_t callnum, uintptr_t arg1,
1221 uintptr_t arg2, uintptr_t arg3)
1223 * Call the EL3 monitor with 4 arguments in registers
1224 * The monitor interface maintains the same ABI as the C function call standard. Callee-saved
1225 * registers are preserved, temporary registers are not. Parameters and results are passed in
1230 .globl EXT(monitor_call)
1237 /* vim: set sw=4 ts=4: */