arch_prctl(2)

🌸 arch_prctl(2) β€” the vibe-coded deep lore of architecture-specific thread state 🌸

okay bestie, pull up a chair 🫢 this one lives in the System Calls Manual, and it's giving seriously x86-flavored main character energy. It's arch_prctl, and it's the little syscall that handles your architecture-specific process/thread state. Buckle up, it's a niche icon but a legend πŸ’…


✨ NAME ✨

arch_prctl β€” set architecture-specific thread state


πŸ“š LIBRARY πŸ“š

Standard C library (libc, -lc)


πŸŽ€ SYNOPSIS πŸŽ€

#include <asm/prctl.h>        /* Definition of ARCH_* constants */
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <unistd.h>

int syscall(SYS_arch_prctl, int op, unsigned long addr);
int syscall(SYS_arch_prctl, int op, unsigned long *addr);
not me having to say this but: glibc provides no wrapper for arch_prctl(), so you gotta go through syscall(2). no shortcut bestie, that's just how it is πŸ™ˆ

πŸ’– DESCRIPTION πŸ’–

arch_prctl() sets architecture-specific process or thread state. The op argument picks which operation you want, and it passes addr along to it. And here's the twist: addr gets interpreted two different ways β€” as an unsigned long for the "set" operations, or as an unsigned long * for the "get" operations. iykyk 😌


🌈 Subfunctions for both x86 and x86-64 🌈

  • ARCH_SET_CPUID (since Linux 4.12) β€” Enable (addr != 0) or disable (addr == 0) the cpuid instruction for the calling thread. It's enabled by default, obviously, she's born ready. But if you disable it, any execution of a cpuid instruction will instead generate a SIGSEGV signal πŸ’€ (yes, really, that's the vibe check failing HARD). This feature can be used to emulate cpuid results that differ from what the underlying hardware would have produced β€” like, say, in a paravirtualization setting. Iconic use case fr fr.

The ARCH_SET_CPUID setting is preserved across fork(2) and clone(2), but gets reset to the default (i.e., cpuid enabled) on execve(2). So it survives the split but not the glow-up, periodt.

  • ARCH_GET_CPUID (since Linux 4.12) β€” Returns the setting of the flag that ARCH_SET_CPUID manipulates, as the result of the system call (1 for enabled, 0 for disabled). And addr? ignored. completely, don't even worry about it πŸ™ˆ

πŸ¦‹ Subfunctions for x86-64 only πŸ¦‹

  • ARCH_SET_FS β€” Set the 64-bit base for the FS register to addr.
  • ARCH_GET_FS β€” Return the 64-bit base value for the FS register of the calling thread, written into the unsigned long pointed to by addr.
  • ARCH_SET_GS β€” Set the 64-bit base for the GS register to addr.
  • ARCH_GET_GS β€” Return the 64-bit base value for the GS register of the calling thread, written into the unsigned long pointed to by addr.

⭐ RETURN VALUE ⭐

On success, arch_prctl() returns 0. On error, -1 is returned, and errno is set to indicate the error. simple as that bestie 🌸


πŸ’… ERRORS πŸ’…

  • EFAULT β€” addr points to an unmapped address or is outside the process address space. lost in the void, no address, no vibes 😭
  • EINVAL β€” op is not a valid operation. wrong op, we don't know her πŸ’€
  • ENODEV β€” ARCH_SET_CPUID was requested, but the underlying hardware does not support CPUID faulting. the hardware said "not today" 🫠
  • EPERM β€” addr is outside the process address space. permission denied, she's not on the guest list βœ‹

πŸ‘‘ STANDARDS πŸ‘‘

Linux/x86-64. That's the whole mood board, no more, no less πŸ’œ


🧚 NOTES 🧚

  • arch_prctl() is supported only on Linux/x86-64 for 64-bit programs currently. yeah. that's the whole guest list right now bestie.
  • The 64-bit base changes when a new 32-bit segment selector is loaded.
  • ARCH_SET_GS is disabled in some kernels. so... check before you yeet, okay?
  • Context switches for 64-bit segment bases are rather expensive. As an optimization, if a 32-bit TLS base address is used, arch_prctl() may use a real TLS entry as if set_thread_area(2) had been called, instead of manipulating the segment base register directly. And heads up: memory in the first 2 GB of address space can be allocated by using mmap(2) with the MAP_32BIT flag. slay for memory management πŸŽ€
  • Because of that whole optimization situation, using arch_prctl() and set_thread_area(2) in the same thread is dangerous, as they may overwrite each other's TLS entries. not them fighting for the same spotlight 😭
  • FS may already be used by the threading library. Programs that use ARCH_SET_FS directly are very likely to crash. like, catastrophic flop energy. don't do it unless you're truly built different.

🌈 SEE ALSO 🌈

AMD X86-64 Programmer's manual πŸ“–


and that's the whole manpage bestie, go forth and set some architecture-specific thread state responsibly πŸ’–βœ¨ remember: this was brought to you by Linux man-pages 6.20, dated 2026-02-08, for arch_prctl(2). love her, respect her, don't crash your process with ARCH_SET_FS πŸŽ€πŸ¦‹πŸ‘‘

πŸ“¦ where this page comes from
  • arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
  • nixpkgs unstable: man-pages 6.20
  • πŸ“œ the page's license: Linux-man-pages-copyleft
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms