---
name: "arch_prctl"
section: "2"
platform: "linux"
package: "man-pages"
version: "6.19-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/arch_prctl"
---

# arch\_prctl(2)

set architecture-specific thread state

## 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***);**

*Note*: glibc provides no wrapper for **arch\_prctl**(), necessitating the use of [**syscall**(2)](/syscall/2.md).

## DESCRIPTION

**arch\_prctl**() sets architecture-specific process or thread state. *op* selects an operation and passes argument *addr* to it; *addr* is interpreted as either an *unsigned long* for the "set" operations, or as an *unsigned long \**, for the "get" operations.

Subfunctions for both x86 and x86-64 are:

- **ARCH\_SET\_CPUID** (since Linux 4.12)

  Enable (*addr != 0*) or disable (*addr == 0*) the *cpuid* instruction for the calling thread. The instruction is enabled by default. If disabled, any execution of a *cpuid* instruction will instead generate a **SIGSEGV** signal. This feature can be used to emulate *cpuid* results that differ from what the underlying hardware would have produced (e.g., in a paravirtualization setting).

-

  The **ARCH\_SET\_CPUID** setting is preserved across [**fork**(2)](/fork/2.md) and [**clone**(2)](/clone/2.md) but reset to the default (i.e., *cpuid* enabled) on [**execve**(2)](/execve/2.md).

- **ARCH\_GET\_CPUID** (since Linux 4.12)

  Return the setting of the flag manipulated by **ARCH\_SET\_CPUID** as the result of the system call (1 for enabled, 0 for disabled). *addr* is ignored.

- Subfunctions for x86-64 only are:

  - **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 in 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 in 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.

## ERRORS

- **EFAULT**

  *addr* points to an unmapped address or is outside the process address space.

- **EINVAL**

  *op* is not a valid operation.

- **ENODEV**

  **ARCH\_SET\_CPUID** was requested, but the underlying hardware does not support CPUID faulting.

- **EPERM**

  *addr* is outside the process address space.

## STANDARDS

Linux/x86-64.

## NOTES

**arch\_prctl**() is supported only on Linux/x86-64 for 64-bit programs currently.

The 64-bit base changes when a new 32-bit segment selector is loaded.

**ARCH\_SET\_GS** is disabled in some kernels.

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)](/set_thread_area/2.md) had been called, instead of manipulating the segment base register directly. Memory in the first 2 GB of address space can be allocated by using [**mmap**(2)](/mmap/2.md) with the **MAP\_32BIT** flag.

Because of the aforementioned optimization, using **arch\_prctl**() and [**set\_thread\_area**(2)](/set_thread_area/2.md) in the same thread is dangerous, as they may overwrite each other's TLS entries.

*FS* may be already used by the threading library. Programs that use **ARCH\_SET\_FS** directly are very likely to crash.

## SEE ALSO

[**mmap**(2)](/mmap/2.md), [**modify\_ldt**(2)](/modify_ldt/2.md), [**prctl**(2)](/prctl/2.md), [**set\_thread\_area**(2)](/set_thread_area/2.md)

AMD X86-64 Programmer's manual
