2 * Copyright (c) 2007 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@
28 #include <machine/asm.h>
29 #include <arm64/machine_machdep.h>
30 #include <arm64/proc_reg.h>
34 * save_general_registers
36 * Saves variable registers to kernel PCB.
37 * arg0 - thread_kernel_state pointer
38 * arg1 - Scratch register
41 .macro save_general_registers
44 * A subroutine invocation must preserve the contents of the registers r19-r29
45 * and SP. We also save IP0 and IP1, as machine_idle uses IP0 for saving the LR.
47 stp x16, x17, [$0, SS64_X16]
48 stp x19, x20, [$0, SS64_X19]
49 stp x21, x22, [$0, SS64_X21]
50 stp x23, x24, [$0, SS64_X23]
51 stp x25, x26, [$0, SS64_X25]
52 stp x27, x28, [$0, SS64_X27]
53 stp fp, lr, [$0, SS64_FP]
59 * Registers d8-d15 (s8-s15) must be preserved by a callee across subroutine
60 * calls; the remaining registers (v0-v7, v16-v31) do not need to be preserved
61 * (or should be preserved by the caller).
65 str d10,[$0, NS64_D10]
66 str d11,[$0, NS64_D11]
67 str d12,[$0, NS64_D12]
68 str d13,[$0, NS64_D13]
69 str d14,[$0, NS64_D14]
70 str d15,[$0, NS64_D15]
74 * load_general_registers
76 * Loads variable registers from kernel PCB.
77 * arg0 - thread_kernel_state pointer
78 * arg1 - Scratch register
80 .macro load_general_registers
81 ldp x16, x17, [$0, SS64_X16]
82 ldp x19, x20, [$0, SS64_X19]
83 ldp x21, x22, [$0, SS64_X21]
84 ldp x23, x24, [$0, SS64_X23]
85 ldp x25, x26, [$0, SS64_X25]
86 ldp x27, x28, [$0, SS64_X27]
87 ldp fp, lr, [$0, SS64_FP]
93 ldr d10,[$0, NS64_D10]
94 ldr d11,[$0, NS64_D11]
95 ldr d12,[$0, NS64_D12]
96 ldr d13,[$0, NS64_D13]
97 ldr d14,[$0, NS64_D14]
98 ldr d15,[$0, NS64_D15]
102 * set_thread_registers
104 * Updates thread registers during context switch
105 * arg0 - New thread pointer
106 * arg1 - Scratch register
107 * arg2 - Scratch register
109 .macro set_thread_registers
110 msr TPIDR_EL1, $0 // Write new thread pointer to TPIDR_EL1
111 ldr $1, [$0, TH_CTH_SELF] // Get cthread pointer
112 mrs $2, TPIDRRO_EL0 // Extract cpu number from TPIDRRO_EL0
113 and $2, $2, #(MACHDEP_CPUNUM_MASK)
114 orr $2, $1, $2 // Save new cthread/cpu to TPIDRRO_EL0
116 ldr $1, [$0, TH_CTH_DATA] // Get new cthread data pointer
117 msr TPIDR_EL0, $1 // Save data pointer to TPIDRRW_EL0
118 /* ARM64_TODO Reserve x18 until we decide what to do with it */
119 mov x18, $1 // ... and trash reserved x18
124 * void machine_load_context(thread_t thread)
126 * Load the context for the first thread to run on a
131 .globl EXT(machine_load_context)
133 LEXT(machine_load_context)
134 set_thread_registers x0, x1, x2
135 ldr x1, [x0, TH_KSTACKPTR] // Get top of kernel stack
136 load_general_registers x1, x2
137 mov x0, xzr // Clear argument to thread_continue
141 * void Call_continuation( void (*continuation)(void),
143 * wait_result_t wresult,
144 * vm_offset_t stack_ptr)
148 .globl EXT(Call_continuation)
150 LEXT(Call_continuation)
151 mrs x4, TPIDR_EL1 // Get the current thread pointer
153 /* ARM64_TODO arm loads the kstack top instead of arg4. What should we use? */
154 ldr x5, [x4, TH_KSTACKPTR] // Get the top of the kernel stack
155 mov sp, x5 // Set stack pointer
157 mov fp, xzr // Clear the frame pointer
158 mov x4, x0 // Load the continuation
159 mov x0, x1 // Set the first parameter
160 mov x1, x2 // Set the wait result arg
161 blr x4 // Branch to the continuation
162 mrs x0, TPIDR_EL1 // Get the current thread pointer
163 b EXT(thread_terminate) // Kill the thread
167 * thread_t Switch_context(thread_t old,
168 * void (*cont)(void),
173 .globl EXT(Switch_context)
176 cbnz x1, Lswitch_threads // Skip saving old state if blocking on continuation
177 ldr x3, [x0, TH_KSTACKPTR] // Get the old kernel stack top
178 save_general_registers x3, x4
180 set_thread_registers x2, x3, x4
181 ldr x3, [x2, TH_KSTACKPTR]
182 load_general_registers x3, x4
186 * thread_t Shutdown_context(void (*doshutdown)(processor_t), processor_t processor)
191 .globl EXT(Shutdown_context)
193 LEXT(Shutdown_context)
194 mrs x10, TPIDR_EL1 // Get thread pointer
195 ldr x11, [x10, TH_KSTACKPTR] // Get the top of the kernel stack
196 save_general_registers x11, x12
197 msr DAIFSet, #(DAIFSC_FIQF | DAIFSC_IRQF) // Disable interrupts
198 ldr x11, [x10, ACT_CPUDATAP] // Get current cpu
199 ldr x12, [x11, CPU_ISTACKPTR] // Switch to interrupt stack
201 b EXT(cpu_doshutdown)
205 * thread_t Idle_context(void)
210 .globl EXT(Idle_context)
213 mrs x0, TPIDR_EL1 // Get thread pointer
214 ldr x1, [x0, TH_KSTACKPTR] // Get the top of the kernel stack
215 save_general_registers x1, x2
216 ldr x1, [x0, ACT_CPUDATAP] // Get current cpu
217 ldr x2, [x1, CPU_ISTACKPTR] // Switch to interrupt stack
222 * thread_t Idle_context(void)
227 .globl EXT(Idle_load_context)
229 LEXT(Idle_load_context)
230 mrs x0, TPIDR_EL1 // Get thread pointer
231 ldr x1, [x0, TH_KSTACKPTR] // Get the top of the kernel stack
232 load_general_registers x1, x2
236 .globl EXT(machine_set_current_thread)
237 LEXT(machine_set_current_thread)
238 set_thread_registers x0, x1, x2