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