Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173586698
D60047.id187761.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D60047.id187761.diff
View Options
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -361,6 +361,7 @@
symlink.2 \
sync.2 \
sysarch.2 \
+ sysarch.x86.2 \
syscall.2 \
thr_exit.2 \
thr_kill.2 \
diff --git a/lib/libsys/sysarch.2 b/lib/libsys/sysarch.2
--- a/lib/libsys/sysarch.2
+++ b/lib/libsys/sysarch.2
@@ -72,7 +72,8 @@
.Sh SEE ALSO
.Xr i386_get_ioperm 2 ,
.Xr i386_get_ldt 2 ,
-.Xr i386_vm86 2
+.Xr i386_vm86 2 ,
+.Xr sysarch.x86.2
.Sh HISTORY
This manual page was taken from
.Nx .
diff --git a/lib/libsys/sysarch.x86.2 b/lib/libsys/sysarch.x86.2
new file mode 100644
--- /dev/null
+++ b/lib/libsys/sysarch.x86.2
@@ -0,0 +1,655 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright 2026 The FreeBSD Foundation.
+.\"
+.\" This documentation was written by Konstantin Belousov <kib@FreeBSD.org>
+.\" under sponsorship of The FreeBSD Foundation.
+.\"
+.Dd September 26, 2026
+.Dt SYSARCH.X86 2 i386
+.Os
+.Sh NAME
+.Nm sysarch.x86
+.Nd architecture-dependent system call on x86
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In machine/sysarch.h
+.Ft int
+.Fn sysarch "int number" "void *args"
+.Sh DESCRIPTION
+The
+manual page descibes the functions provided by the
+.Fn sysarch
+system call on x86 architectures, that is i386 and amd64, see
+.Xr arch 7 .
+.Ss Parameter Types
+The following structures are used as the arguments pointed t by the
+.Fa args
+parameter.
+Refer to the description of the requests for the specification of the
+fields meaning:
+.Pp
+The
+.Dv I386_GET_IOPERM
+and
+.Dv I386_SET_IOPERM
+requests take the
+.Vt struct i386_ioperm_args ,
+which is defined as following:
+.Bd -literal
+struct i386_ioperm_args {
+ unsigned int start;
+ unsigned int length;
+ int enable;
+};
+.Ed
+.Pp
+The
+.Dv I386_GET_LDT
+and
+.Dv I386_SET_LDT
+requests take
+.Vt struct i386_ldt_args ,
+which definition differs between i386 and amd64.
+The i386 variant is
+.Bd -literal
+struct i386_ldt_args {
+ unsigned int start;
+ union descriptor *descs;
+ unsigned int num;
+};
+.Ed
+the amd64 variant is:
+.Bd -literal
+struct i386_ldt_args {
+ unsigned int start;
+ struct user_segment_descriptor *descs __packed;
+ unsigned int num;
+};
+.Ed
+.Pp
+i386-only request
+.Dv I386_VM86
+takes
+.Bd -literal
+struct i386_vm86_args {
+ int sub_op;
+ char *sub_args;
+};
+.Ed
+.Pp
+The
+.Dv I386_GET_XFPUSTATE ,
+takes the
+.Vt struct i386_get_xfpustate
+argument, and
+.Dv AMD64_GET_XFPUSTATE
+.Vt struct amd64_get_xfpustate
+argument.
+The structures have the same members, but their layout differs due to the
+pointer size differences.
+Only amd64 variant is listed for clarity.
+.Bd -literal
+struct amd64_get_xfpustate {
+ void *addr;
+ int len;
+};
+.Ed
+.Pp
+The
+.Dv I386_GET_PKRU ,
+.Dv I386_SET_PKRU ,
+take the
+.Vt struct i386_set_pkru
+argument, and
+.Dv AMD64_GET_PKRU
+and
+.Dv AMD64_SET_PKRU
+take the
+.Vt struct amd64_set_pkru
+argument.
+The structures have the same members, but their layout differs due to the
+pointer size differences.
+Only amd64 variant is listed for clarity.
+.Bd -literal
+struct amd64_set_pkru {
+ void *addr;
+ unsigned long len;
+ unsigned int keyidx;
+ int flags;
+};
+.Ed
+.Ss Requests
+The following requests can be specified by the
+.Fa number
+argument:
+.Bl -tag -width AMD64_DISABLE_TLSBASE
+.It Dv I386_GET_LDT
+Queries the specified range of the LDT descriptors for the
+calling process.
+.Pp
+The request takes the pointer to the
+.Vt struct i386_ldt_args
+structure as the
+.Fa args
+parameter.
+Its
+.Va start
+member specifies the starting index, and
+.Va num
+the number of descriptors which are queried.
+The LDT descriptor's content in the requested range is copied into
+the memory specified by the
+.Fa descs
+member.
+.It Dv I386_SET_LDT
+Set the specified range of the LDT descriptors for the calling process.
+.Pp
+LDT is process-global, all process threads share the table.
+On the other hand, if several processes share the address space,
+they still each have its own LDT.
+.Pp
+The request takes the pointer to the
+.Vt struct i386_ldt_args
+structure as the
+.Fa args
+parameter.
+Its
+.Va start
+member specifies the starting index, and
+.Va num
+the number of descriptors which are queried.
+The LDT descriptor's content in the requested range is copied into
+the memory specified by the
+.Fa descs
+member.
+.Pp
+If the
+.Va descs
+member value is
+.Dv NULL,
+the content of the specified descriptors is cleared (zeroed).
+If the
+.Va start
+starting descriptor index has the special value
+.Dv LDT_AUTO_ALLOC
+and the number of descriptors to allocate is 1, then system looks for
+some free descriptor index and allocates it.
+The resulting index is returned as the system call return value.
+.Pp
+Only memory read or read/write normal or expand down, and execute only
+or execute read segment types are allowed.
+Any system segments descriptors, or memory conforming execute segments
+are rejected with the
+.Ev EACCESS
+error.
+.Pp
+X86 hardware supports LDT sized up to 8192 descriptors.
+This size is regarded as excessive for needs of modern applications.
+The
+.Dv machdep.max_ldt_segment
+loader tunable establishes the system-global maximum size of LDT
+(in number of descriptors).
+.It Dv I386_GET_IOPERM
+Queries the state of the userspace access to the specified range
+of i/o ports for the calling thread.
+.Pp
+The function takes the pointer
+.Vt struct i386_ioperm_args
+structure as the
+.Fa args
+argument.
+The
+.Va start
+is the starting port number for which the state is queried.
+Upon successful return, the argument structure'
+.Va enable
+member records the state of the access to the starting port.
+The
+.Va length
+member indicates how many ports after the starting port number
+have the same access permissions.
+.Pp
+For instance, if the
+.Va start
+was set to 10,
+and the request set the
+.Va length
+field to 3, with
+.Va enable
+set to 1, then access to the ports 10, 11, 12 is enabled, while
+access to the port 13 is disallowed.
+.It Dv I386_SET_IOPERM
+Grants or revoke access from userspace to IO ports using the
+TSS io permission bitmap for the calling thread.
+The bitmap has the thread scope.
+.Pp
+The function takes the pointer
+.Vt struct i386_ioperm_args
+structure as the
+.Fa args
+argument.
+Depending on the
+.Va enable
+member value, it either grant (enable) or revoke (disable) access to the
+range of i/o ports specified by the
+.Va start
+and
+.Va length
+members.
+.Pp
+There is total of 65536 ports, the set of ports specified must fit into the
+0..65535 range.
+.Pp
+The call requires super-user privileges.
+.It Dv I386_VM86
+Manage the VM86 mode of execution.
+i386 only, the function is not exposed by hardware in the long mode.
+To use the request, additional header
+.In machine/vm86.h
+must be included, existing only on i386.
+.Pp
+.Pp
+The request takes the pointer to the
+.Vt struct i386_vm86_args
+structure as the
+.Fa args
+argument.
+Its
+.Va sub_op
+member specifies one of the following sub-requests:
+.Pp
+.Bl -tag -width VM86_SET_VME
+.It Dv VM86_INIT
+Initialize the vm86 in-kernel extended pcb.
+Without the initialization, the vm86 mode cannot be entered.
+.Pp
+The sub-request takes the
+.Vt struct vm86_init_args
+additional argument pointed to by the
+.Fa sub_args
+pointer in the
+.Vt struct i386_vm86_args
+structure.
+.Pp
+Currently only the
+.Va int_map
+member of the structure is implemented.
+Each bit N in the
+.Va int_map
+bit-string set to 1 causes the
+.Dv SIGTRAP
+signal to be delivered to the thread on the execution
+of the
+.Dv INT N
+instruction.
+Otherwise, if the bit is zero, the execution of the
+.Dv INT N
+instruction is reflected to the vm86 mode to the interrupt
+handler as designated by the real-mode interrupt table.
+.It Dv VM86_SET_VME
+Reserved but not implemented.
+.It Dv VM86_GET_VME
+Returns the state of the VME extensions, implemented started with
+the Pentium microarchitecture.
+The
+.Va sub_args
+must point to
+.Vt struct vm86_vme_args
+structure.
+.It Dv VM86_INTCALL
+Arrange execution in vm86 mode as if the specified interrupt
+was delivered.
+Takes the
+.Vt struct vm86_intcall_args
+argument as the
+.Va sub_args
+pointer.
+The
+.Va intnum
+member of it provides the interrupt number to emulate delivery of,
+and the
+.Va vmf
+gives the vm86 mode machine context to load for the interrupt
+handler.
+.El
+.Pp
+To switch thread to the vm86 execution mode, several preparations
+must be done:
+.Bl -dash
+.It
+The alt signal stack must be created, since otherwise signal
+delivery in vm86 mode would try to use vm86 stack.
+See
+.Xr sigaltstack 2 .
+.It
+The vm86 mode kernel state must be initialized with the
+.Dv VM86_INIT
+sub-request.
+.It
+The memory must be mapped in the first megabyte of the user address
+space, which will be accessible to the vm86 mode execution.
+.It
+Signal handlers must be established that can handle vm86 exceptions.
+Most importantly, the
+.Dv SIGSEGV
+handler must be provided to assist vm86 code to handle exits due to
+IOPL-sensitive instructions.
+.It
+Finally, the vm86 mode can be entered by switching to the context
+with %eflags register having the
+.Dv eflags.VM
+bit set.
+This can be done, among other ways, by loading the full
+machine context with the
+.Xr sigreturn 2
+system call.
+.El
+.Pp
+The thread continues to execute in vm86 mode until a signal
+is delivered to it.
+Note that exceptions generate appropriate signal same as
+for the protected execution mode.
+.Pp
+See
+.Pa src:tools/tests/vm86
+for a minimal example of the vm86 monitor and sample code.
+.It Dv I386_GET_FSBASE
+Read the 32bit fsbase context value for the calling thread into the
+32bit
+.Vt int
+variable pointed to by the
+.Fa args
+argument.
+.It Dv I386_SET_FSBASE
+Set the 32bit fsbase context value for the calling thread.
+The
+.Fa args
+argument must point to 32bit
+.Vt int
+variable that has the new fsbase value stored.
+.Pp
+The fsbase is maintained by writing the fsbase value into the
+base field of the user 32bit %fs GDT descriptor, which has index 2.
+.It Dv I386_GET_GSBASE
+Read the 32bit gsbase context value for the calling thread into the
+32bit
+.Vt int
+variable pointed to by the
+.Fa args
+argument.
+.It Dv I386_SET_GSBASE
+Set the 32bit gsbase context value for the calling thread.
+The
+.Fa args
+argument must point to 32bit
+.Vt int
+variable that has the new gsbase value stored.
+.Pp
+The gsbase is maintained by writing the gsbase value into the
+base field of the user 32bit %gs GDT descriptor, which has index 3.
+.It Dv I386_GET_XFPUSTATE
+Same as
+.Dv AMD64_GET_XFPUSTATE ,
+but takes the address of the
+.Vt struct i386_get_xfpustate
+structure as the
+.Fa args
+argument.
+.It Dv I386_SET_PKRU
+Provided only when running i386 binaries on the amd64 host kernel.
+.Pp
+See description of the
+.Dv AMD64_SET_PKRU
+request.
+.It Dv I386_CLEAR_PKRU
+Provided only when running i386 binaries on the amd64 host kernel.
+.Pp
+See description of the
+.Dv AMD64_CLEAR_PKRU
+request.
+.It Dv I386_SET_SPLITLOCK
+Change the requesting thread splitlock detection control.
+For i386 binaries, the function is only available when running
+on the amd64 host kernel.
+.Pp
+The argument must point to the 32bit
+.Vt int
+variable, holding one of the following values:
+.Bl -tag
+.It Dv 0
+Disable detection of split locking.
+.It Dv 1
+Enable detection of split locking.
+.El
+.Pp
+The split lock is the situation where the read-modify-write atomic
+instruction is performed on the memory location that is split over
+more than one CPU cache line.
+Some CPUs can be configured to generate the Alignment Fault exception
+.Ql #AC
+if split locking is detected.
+The request makes it possible for the thread to control the detector.
+.Pp
+The
+.Xr _umtx_op 2
+operations that pass unaligned locks to kernel requests returns
+.Ev EFAULT
+when splitlock detection is enabled.
+.Pp
+Presence of the detector can be queried with the
+.Dv hw.splitlock
+.Xr sysctl 2
+MIB.
+.It Dv I386_GET_SPLITLOCK
+Returns the state of the splitlock detection control.
+For i386 binaries, the function is only available when running
+on the amd64 host kernel.
+.Pp
+The argument must point to the 32bit
+.Vt int
+variable.
+The function writes the value 0 if the control is disabled
+and 1 if enabled.
+.Pp
+.It Dv AMD64_GET_FSBASE
+Returns the value of the
+.Dv fsbase
+register for the calling thread.
+The
+.Fa args
+argument must point to the 64bit
+.Vt unsigned long variable
+where the value is written.
+.Pp
+On CPUs that do not support the RDFSBASE instruction, the call is the only
+way to read the current value of fsbase.
+.It Dv AMD64_SET_FSBASE
+Sets the
+.Dv fsbase
+register to the 64bit value pointed to by the
+.Fa args
+argument.
+.Pp
+The value is checked to not point outside of the allowed user address
+space, which is subset of possible canonical addresses.
+If the WRFSBASE instruction is supported, the fsbase register can
+be updated either by the call or by the instruction.
+For 64bit processes, the fsbase register is always restored on return
+to user mode from kernel calls or interrupts, regardless of the value
+of the %fs segment register.
+.It Dv AMD64_GET_GSBASE
+Get the
+.Dv gsbase
+register, see description of
+.Dv AMD64_GET_FSBASE .
+.It Dv AMD64_SET_GSBASE
+Set the
+.Dv gsbase
+register, see description of
+.Dv AMD64_GET_GSBASE .
+.It Dv AMD64_GET_XFPUSTATE
+Fills the extended FPU state as defined by the architecture and the
+running CPU hardware into the memory described by the
+.Vt struct amd64_get_xfpustate
+structure.
+The
+.Fa args
+argument must point to the structure, the extended state (that is, full
+XSAVE area exclusing the legacy region) is written to the
+.Va addr
+up to the
+.Va len
+bytes.
+If the
+.Va len
+member value is smaller then the XSAVE area size, the result is truncated.
+.It Dv AMD64_SET_PKRU
+Set the 4bit protection key for the page table entries used to map
+the given userspace virtual address range.
+.Pp
+The request takes the
+.Vt struct amd64_set_pkru
+structure pointed to by the
+.Fa args
+parameter.
+The
+.Va addr
+and
+.Va len
+members of the structure specify starting address and the length in bytes
+of the region.
+The
+.Va keyidx
+member value must be between 0 and 15 and provides the protection key
+index applied to the region.
+The
+.Va flags
+member is or-ed with the following flags:
+.Bl -tag -width AMD64_PKRU_PERSIST
+.It Dv AMD64_PKRU_EXCL
+Requires that no protection key was assigned to the specified range,
+or previously assigned key cleared.
+If some key was already applied to any part of the range, the call
+fails with the
+.Ev EBUSY
+error.
+.It Dv AMD64_PKRU_PERSIST
+Makes the assigned key persistent.
+It is automatically re-applied to any new mapping created in the range.
+.El
+.Pp
+Protection keys feature is optional and depends on CPU implementing it.
+Use the
+.Dv CPUID
+instruction to check its availability.
+.Pp
+The request is used to implement the
+.Xr x86_pkru_protect_range 3
+function.
+.It Dv AMD64_CLEAR_PKRU
+Clear any protection keys assigned to the specified region.
+.Pp
+The request takes the
+.Vt struct amd64_set_pkru
+structure pointed to by the
+.Fa args
+parameter.
+The
+.Va addr
+and
+.Va len
+members of the structure specify starting address and the length in bytes
+of the region.
+Other structure members are ignored.
+.Pp
+The request is used to implement the
+.Xr x86_pkru_unprotect_range 3
+function.
+.It Dv AMD64_GET_TLSBASE
+AMD64 only.
+.Pp
+Returns the current TLSBASE value for the calling thread.
+The
+.Fa args
+argument must point to the 64bit
+.Vt unsigned long
+variable where the value is written to.
+.It Dv AMD64_SET_TLSBASE
+Sets the TLSBASE and the fsbase register values for the calling thread.
+The
+.Fa args
+argument must point to the 64bit
+.Vt unsigned long
+variable where the value is taken from.
+.Pp
+The TLSBASE value is written into the
+.Dv fsbase
+register before a signal handler is invoked.
+The current fsbase value is saved, and then restored
+upon return from the signal handler.
+Use of TLSBASE makes it possible for programs that modify
+the fsbase register using WRFSBASE instruction to reliably access
+thread-local variables in signal handlers.
+.Pp
+TLSBASE is set up by the
+.Fx
+C runtime environment on thread startup.
+.It Dv AMD64_DISABLE_TLSBASE
+Disables loading the fsbase register from TLSBASE value on
+a signal handler invocation.
+The argument
+.Fa args
+is ignored.
+.Pp
+The call allows to undo the effect of the
+.Dv AMD64_SET_TLSBASE ,
+making signal handlers retain the value of fsbase from the
+interrupted context.
+By default, tlsbase is disabled after the
+.Xr execve 2
+syscall activated a new image.
+.El
+.Sh RETURN VALUES
+For all requests except
+.Dv I386_GET_LDT
+and
+.Dv I386_SET_LDT ,
+upon successful completion, the value 0 is returned; otherwise the
+value -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Pp
+The
+.Dv I386_SET_LDT
+request returns the starting index of the descriptors range it operated
+on, on success.
+In particular, the index of the automatically allocated descriptor is
+reported this way.
+Otherwise, -1 is returned and
+.Va errno
+is set.
+.Pp
+The
+.Dv I386_GET_LDT
+request returns 0 if the specified descriptors range is completely
+outside the allocated LDT.
+On any other error, -1 is returned and
+.Va errno
+is set.
+Otherwise the number of reported descriptors is returned as the syscall
+return value.
+.Sh SEE ALSO
+.Xr i386_get_ioperm 2 ,
+.Xr i386_get_ldt 2 ,
+.Xr i386_vm86 2 ,
+.Xr sysarch 2 ,
+.Xr pkru 3 ,
+.Xr arch 7
+.Sh HISTORY
+The manual page appeared in
+.Fx 16.0 .
+.Sh AUTHORS
+The manual page was written by
+.An Konstantin Belousov Aq Mt kib@FreeBSD.org .
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Sep 28, 12:32 AM (13 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39772210
Default Alt Text
D60047.id187761.diff (17 KB)
Attached To
Mode
D60047: sysarch.x86.2: manual page for the sysarch(2) functions on x86
Attached
Detach File
Event Timeline
Log In to Comment