1.\"- 2.\" SPDX-License-Identifier: BSD-2-Clause 3.\" 4.\" Copyright (c) 2024 (holder) 5.\" 6.\" This software was developed by SRI International, the University of 7.\" Cambridge Computer Laboratory (Department of Computer Science and 8.\" Technology), and Capabilities Limited under Defense Advanced Research 9.\" Projects Agency (DARPA) Contract No. FA8750-24-C-B047 ("DEC"). 10.\" 11.Dd January 3, 2025 12.Dt cpu_machdep 9 13.Os 14.Sh NAME 15.Nm cpu_machdep , 16.Nm cpu_copy_thread , 17.Nm cpu_exec_vmspace_reuse , 18.Nm cpu_exit , 19.Nm cpu_fetch_syscall_args , 20.Nm cpu_fork , 21.Nm cpu_fork_kthread_handler , 22.Nm cpu_idle , 23.Nm cpu_idle_wakeup , 24.Nm cpu_procctl , 25.Nm cpu_set_syscall_retval , 26.Nm cpu_set_upcall , 27.Nm cpu_set_user_tls , 28.Nm cpu_switch , 29.Nm cpu_sync_core , 30.Nm cpu_thread_alloc , 31.Nm cpu_thread_clean , 32.Nm cpu_thread_exit , 33.Nm cpu_thread_free , 34.Nm cpu_throw 35.Nd machine-dependent interfaces to handle CPU and thread state 36.Sh SYNOPSIS 37.In sys/proc.h 38.In sys/ptrace.h 39.Ft void 40.Fn cpu_copy_thread "struct thread *td" "struct thread *td0" 41.Ft bool 42.Fn cpu_exec_vmspace_reuse "struct proc *p" "struct vm_map *map" 43.Ft void 44.Fn cpu_exit "struct thread *td" 45.Ft int 46.Fn cpu_fetch_syscall_args "struct thread *td" 47.Ft void 48.Fo cpu_fork 49.Fa "struct thread *td1" "struct proc *p2" "struct thread *td2" "int flags" 50.Fc 51.Ft void 52.Fo cpu_fork_kthread_handler 53.Fa "struct thread *td" "void (*func)(void *)" "void *arg" 54.Fc 55.Ft void 56.Fn cpu_idle "int busy" 57.Ft int 58.Fn cpu_idle_wakeup "int cpu" 59.Ft int 60.Fo cpu_procctl 61.Fa "struct thread *td" "int idtype" "id_t id" "int com" "void *data" 62.Fc 63.Ft int 64.Fn cpu_ptrace "struct thread *_td" "int req" "void *addr" "int data" 65.Ft void 66.Fn cpu_set_syscall_retval "struct thread *td" "int error" 67.Ft int 68.Fo cpu_set_upcall 69.Fa "struct thread *td" "void (*entry)(void *)" "void *arg" "stack_t *stack" 70.Fc 71.Ft int 72.Fn cpu_set_user_tls "struct thread *td" "void *tls_base" 73.Ft void 74.Fn cpu_switch "struct thread *old" "struct thread *new" "struct mtx *mtx" 75.Ft void 76.Fn cpu_sync_core "void" 77.Ft void 78.Fn cpu_thread_alloc "struct thread *td" 79.Ft void 80.Fn cpu_thread_clean "struct thread *td" 81.Ft void 82.Fn cpu_thread_exit "struct thread *td" 83.Ft void 84.Fn cpu_thread_free "struct thread *td" 85.Ft void 86.Fn cpu_throw "struct thread *old" "struct thread *new" 87.Sh DESCRIPTION 88These functions provide architecture-specific implementations of 89machine-independent abstractions. 90.Pp 91.Fn cpu_exec_vmspace_reuse 92returns true if 93.Fn exec_new_vmspace 94can reuse an existing 95.Vt struct vmspace 96.Pq Fa map 97for the process 98.Fa p 99during 100.Xr execve 2 . 101This is only invoked if 102.Fa map 103is not shared with any other consumers. 104If this returns false, 105.Fn exec_new_vmspace 106will create a new 107.Vt struct vmspace . 108.Pp 109.Fn cpu_exit 110releases machine-dependent resources other than the address space for the 111process containing 112.Fa td 113during process exit. 114.Pp 115.Fn cpu_fork 116copies and updates machine-dependent state 117(for example, the pcb and user registers) from the forking thread 118.Fa td1 119in an existing process to the new thread 120.Fa td2 121in the new process 122.Fa p2 . 123This function must set up the new thread's kernel stack and pcb so that 124.Fa td2 125calls 126.Fn fork_exit 127when it begins execution passing a pointer to 128.Fn fork_return 129as the 130.Fa callout 131argument and 132.Fa td2 133as the 134.Fa arg 135argument. 136.Pp 137.Fn cpu_fork_kthread_handler 138adjusts a new thread's initial pcb and/or kernel stack to pass 139.Fa func 140and 141.Fa arg 142as the 143.Fa callout 144and 145.Fa arg 146arguments to 147.Fn fork_exit . 148This must be called before a new thread is scheduled to run and is 149used to set the 150.Dq main 151function for kernel threads. 152.Pp 153.Fn cpu_copy_thread 154copies machine-dependent state (for example, the pcb and user registers) from 155.Fa td 156to 157.Fa td0 158when creating a new thread in the same process. 159This function must set up the new thread's kernel stack and pcb so that 160.Fa td0 161calls 162.Fn fork_exit 163when it begins execution passing a pointer to 164.Fn fork_return 165as the 166.Fa callout 167argument and 168.Fa td0 169as the 170.Fa arg 171argument. 172.Pp 173.Fn cpu_set_upcall 174updates a new thread's initial user register state to call 175.Fa entry 176with 177.Fa arg 178as the sole argument using the user stack described in 179.Fa stack . 180.Pp 181.Fn cpu_set_user_tls 182sets a new thread's initial user thread pointer register to 183reference the user TLS base pointer 184.Fa tls_base . 185.Pp 186.Fn cpu_fetch_syscall_args 187fetches the current system call arguments for the native FreeBSD ABI from the 188current thread's user register state and/or user stack. 189The arguments are saved in the 190.Fa td_sa 191member of 192.Fa td . 193.Pp 194.Fn cpu_set_syscall_retval 195updates the user register state for 196.Fa td 197to store system call error and return values. 198If 199.Fa error 200is 0, 201indicate success and return the two values in 202.Fa td_retval . 203If 204.Fa error 205is 206.Dv ERESTART, 207adjust the user PC to re-invoke the current system call after returning 208to user mode. 209If 210.Fa error 211is 212.Dv EJUSTRETURN , 213leave the current user register state unchanged. 214For any other value of 215.Fa error , 216indicate error and return 217.Fa error 218as the error code. 219.Pp 220.Fn cpu_idle 221waits for the next interrupt to occur on the current CPU. 222If an architecture supports low power idling, 223this function should place the CPU into a low power state while waiting. 224.Fa busy 225is a hint from the scheduler. 226If 227.Fa busy 228is non-zero, 229the scheduler expects a short sleep, 230so the CPU should prefer low-latency over maximum power savings. 231If 232.Fa busy 233is zero, 234the CPU should maximumize power savings including deferring unnecessary 235clock interrupts via 236.Fn cpu_idleclock . 237.Pp 238.Fn cpu_idle_wakeup 239awakens the idle CPU with the ID 240.Fa cpu 241from a low-power state. 242.Pp 243.Fn cpu_procctl 244handles any machine-dependent 245.Xr procctl 2 246requests. 247.Pp 248.Fn cpu_ptrace 249handles any machine-dependent 250.Xr ptrace 2 251requests. 252.Pp 253.Fn cpu_switch 254switches the current CPU between threads by swapping register state. 255This function saves the current CPU register state in the pcb of 256.Fa old 257and loads register values from the pcb of 258.Fa new 259before returning. 260While the pcb generally contains caller-save kernel register state, 261it can also contain user registers that are not saved in the trapframe. 262.Pp 263After saving the current CPU register state of 264.Fa old , 265.Fn cpu_switch 266stores 267.Fa mtx 268in the 269.Fa td_lock 270member of 271.Fa old 272transferring ownership of the old thread. 273No data belonging to 274.Fa old 275can be accessed after that store. 276Specifically, the old thread's kernel stack must not be accessed after 277this point. 278.Pp 279When 280.Dv SCHED_ULE 281is being used, 282this function must wait (via spinning) for the 283.Fa td_lock 284member of 285.Fa new 286to change to a value not equal to 287.Va &blocked_lock 288before loading register values from 289.Fa new 290or accessing its kernel stack. 291.Pp 292From the caller's perspective, 293.Fn cpu_switch 294returns when 295.Fa old 296is rescheduled in the future, 297possibly on a different CPU. 298However, the implementation of 299.Fn cpu_switch 300returns immediately on the same CPU into the previously-saved context of 301.Fa new . 302.Pp 303.Fn cpu_throw 304is similar to 305.Fn cpu_switch 306but does not save any state for 307.Fa old 308or write to the old thread's 309.Fa td_lock 310member. 311.Pp 312.Fn cpu_sync_core 313ensures that all possible speculation and out-of-order execution is 314serialized on the current CPU. 315Note that this is called from an IPI handler so only has to handle 316additional serialization beyond that provided by handling an IPI. 317.Ss Thread Object Lifecycle 318These functions support the management of machine-dependent thread 319state in conjunction with a thread object's lifecycle. 320.Pp 321The general model is that a thread object is allocated each time a 322new kernel thread is created either by system calls like 323.Xr fork 2 324or 325.Xr thr_new 2 326or when kernel-only threads are created via 327.Xr kproc_create 9 , 328.Xr kproc_kthread_add 9 , 329or 330.Xr kthread_add 9 . 331When a kernel thread exits, 332the thread object is freed. 333However, there is one special case to support an optimization where each 334free process object caches a thread object. 335When a process exits, the last thread object is not freed but remains 336attached to the process. 337When the process object is later reused for a new process in 338.Xr fork 2 , 339the kernel recycles that last thread object and uses it as the initial 340thread in the new process. 341When a thread is recycled, some of the steps in the thread allocation 342and free cycle are skipped as an optimization. 343.Pp 344.Fn cpu_thread_alloc 345initializes machine-dependent fields in 346.Fa td 347after allocating a new kernel stack. 348This function typically sets the 349.Fa td_pcb 350and initial 351.Fa td_frame 352pointers. 353.Fn cpu_thread_alloc 354is called both when allocating a new thread object and 355when a recycled thread allocates a new kernel stack. 356Note that this function is 357.Em not 358called if a recycled thread reuses its existing kernel stack. 359.Pp 360.Fn cpu_thread_clean 361releases any machine-dependent resources for the last thread in a 362process during 363.Xr wait 2 . 364The thread is a candidate for recycling so should be reset to run as a 365new thread in case it is recycled by a future 366.Xr fork 2 . 367.Pp 368.Fn cpu_thread_exit 369cleans any machine-dependent state in 370.Fa td 371while it is exiting. 372This is called by the exiting thread so cannot free state needed during 373in-kernel execution. 374.Pp 375.Fn cpu_thread_free 376releases any machine-dependent state in 377.Fa td 378when it is being freed. 379This is called for any thread that was not the last thread in a process 380once it has finished execution. 381.Sh SEE ALSO 382.Xr fork 2 , 383.Xr procctl 2 , 384.Xr ptrace 2 , 385.Xr thr_new 2 , 386.Xr wait 2 , 387.Xr kproc_create 9 , 388.Xr kproc_kthread_add 9 , 389.Xr kthread_add 9 , 390.Xr mi_switch 9 391.Sh AUTHORS 392This manual page was 393developed by SRI International, the University of Cambridge Computer 394Laboratory (Department of Computer Science and Technology), and 395Capabilities Limited under contract 396.Pq FA8750-24-C-B047 397.Pq Do DEC Dc . 398