2021-09-14 01:01:53

by Sohil Mehta

[permalink] [raw]
Subject: [RFC PATCH 01/13] x86/uintr/man-page: Include man pages draft for reference

Included here in plain text format for reference and review.

<Will eventually send the man pages in groff format separately to the
man-pages repository.>

The formatting for the man pages still needs a little bit of work.

Signed-off-by: Sohil Mehta <[email protected]>
---
tools/uintr/manpages/0_overview.txt | 265 ++++++++++++++++++
tools/uintr/manpages/1_register_receiver.txt | 122 ++++++++
.../uintr/manpages/2_unregister_receiver.txt | 62 ++++
tools/uintr/manpages/3_create_fd.txt | 104 +++++++
tools/uintr/manpages/4_register_sender.txt | 121 ++++++++
tools/uintr/manpages/5_unregister_sender.txt | 79 ++++++
tools/uintr/manpages/6_wait.txt | 59 ++++
7 files changed, 812 insertions(+)
create mode 100644 tools/uintr/manpages/0_overview.txt
create mode 100644 tools/uintr/manpages/1_register_receiver.txt
create mode 100644 tools/uintr/manpages/2_unregister_receiver.txt
create mode 100644 tools/uintr/manpages/3_create_fd.txt
create mode 100644 tools/uintr/manpages/4_register_sender.txt
create mode 100644 tools/uintr/manpages/5_unregister_sender.txt
create mode 100644 tools/uintr/manpages/6_wait.txt

diff --git a/tools/uintr/manpages/0_overview.txt b/tools/uintr/manpages/0_overview.txt
new file mode 100644
index 000000000000..349538effb15
--- /dev/null
+++ b/tools/uintr/manpages/0_overview.txt
@@ -0,0 +1,265 @@
+UINTR(7) Miscellaneous Information Manual UINTR(7)
+
+
+
+NAME
+ Uintr - overview of User Interrupts
+
+DESCRIPTION
+ User Interrupts (Uintr) provides a low latency event delivery and inter
+ process communication mechanism. These events can be delivered directly
+ to userspace without a transition to the kernel.
+
+ In the User Interrupts hardware architecture, a receiver is always
+ expected to be a user space task. However, a user interrupt can be sent
+ by another user space task, kernel or an external source (like a
+ device). The feature that allows another userspace task to send an
+ interrupt is referred to as User IPI.
+
+ Uintr is a hardware dependent, opt-in feature. Application aren't
+ expected or able to send or receive interrupts unless they register
+ themselves with the kernel using the syscall interface described below.
+ It is recommended that applications wanting to use User Interrupts call
+ uintr_register_handler(2) and test whether the call succeeds.
+
+ Hardware support for User interrupts may be detected using other
+ mechanisms but they could be misleading and are generally not needed:
+ - Using the cpuid instruction (Refer the Intel Software Developers
+ Manual).
+ - Checking for the "uintr" string in /proc/cpuinfo under the "flags"
+ field.
+
+
+ Applications wanting to use Uintr should also be able to function
+ without it as well. Uintr support might be unavailable because of any
+ one of the following reasons:
+ - the kernel code does not contain support
+ - the kernel support has been disabled
+ - the hardware does not support it
+
+
+ Uintr syscall interface
+ Applications can use and manage Uintr using the system calls described
+ here. The Uintr system calls are available only if the kernel is
+ configured with the CONFIG_X86_USER_INTERRUPTS option.
+
+ 1) A user application registers an interrupt handler using
+ uintr_register_handler(2). The registered interrupt handler will be
+ invoked when a user interrupt is delivered to that thread. Only one
+ interrupt handler can be registered by a particular thread within a
+ process.
+
+ 2) Each thread that registered a handler has its own unique vector
+ space of 64 vectors. The thread can then use uintr_create_fd(2) to
+ register a vector and create a user interrupt file descriptor -
+ uintr_fd.
+
+ 3) The uintr_fd is only associated with only one Uintr vector. A new
+ uintr_fd must be created for each of the 64 vectors. uintr_fd is
+ automatically inherited by forked processes but the receiver can also
+ share the uintr_fd with potential senders using any of the existing FD
+ sharing mechanisms (like pidfd_getfd(2) or socket sendmsg(2)). Access
+ to uintr_fd allows a sender to generate an interrupt with the
+ associated vector. Upon interrupt delivery, the interrupt handler is
+ invoked with the vector number pushed onto the stack to identify the
+ source of the interrupt.
+
+ 4) Each thread has a local flag called User Interrupt flag (UIF). The
+ thread can set or clear this flag to enable or disable interrupts. The
+ default value of UIF is always 0 (Interrupts disabled). A receiver must
+ execute the _stui() intrinsic instruction at some point (before or
+ anytime after registration) to start receiving user interrupts. To
+ disable interrupts during critical sections the thread can call the
+ _clui() instruction to clear UIF.
+
+ 5a) For sending a user IPI, the sender task registers with the kernel
+ using uintr_register_sender(2). The kernel would setup the routing
+ tables to connect the sender and receiver. The syscall returns an index
+ that can be used with the 'SENDUIPI <index>' instruction to send a user
+ IPI. If the receiver is running, the interrupt is delivered directly
+ to the receiver without any kernel intervention.
+
+ 5b) If the sender is the kernel or an external source, the uintr_fd can
+ be passed onto the related kernel entity to allow them to connect and
+ generate the user interrupt. <The exact details of this API are still
+ being worked upon.>
+
+ 6) The receiver can block in the kernel while it is waiting for user
+ interrupts to get delivered using uintr_wait(2). If the receiver has
+ been context switched out due to other reasons the user interrupt will
+ be delivered when the receiver gets scheduled back in.
+
+ <The behavior when the receiver has made some other blocking system
+ call like sleep(2) or read(2) is still to be decided. We are evaluating
+ if a thread made another blocking syscall should be interrupted and
+ woken up when a user interrupt arrives for that thread. uintr_wait(2)
+ has been implemented as a placeholder in the meantime.>
+
+ 7) The sender and receiver are expected to coordinate and then call the
+ teardown syscalls to terminate the connection:
+ a. A sender unregisters with uintr_unregister_sender(2)
+ b. A vector is unregistered using close(uintr_fd)
+ c. A receiver unregisters with uintr_unregister_handler(2)
+
+ If the sender and receiver aren't able to coordinate, some shared
+ kernel resources between them would get freed later when the file
+ descriptors get released automatically on process exit.
+
+
+ Multi-threaded applications need to be careful when using Uintr since
+ it is a thread specific feature. Actions by one thread don't reflect on
+ other threads of the same application.
+
+
+ Toolchain support
+ Support has added to GCC(11.1) and Binutils(2.36.1) to enable user
+ interrupt intrinsic instructions and compiler flag (-muintr).
+
+ The "(interrupt)" attribute can be used to compile a function as a user
+ interrupt handler. In conjunction with the 'muintr' flag, the compiler
+ would:
+ - Generate the entry and exit sequences for the User interrupt
+ handler
+ - Handle the saving and restoring of registers
+ - Call uiret to return from a user interrupt handler
+
+ User Interrupts related compiler intrinsic instructions -
+ <x86gprintrin.h>:
+
+ _clui() - Disable user interrupts - clear UIF (User Interrupt Flag).
+
+ _stui() - enable user interrupts - set UIF.
+
+ _testui() - test current value of UIF.
+
+ _uiret() - return from a user interrupt handler.
+
+ _senduipi <uipi_index> - send a user IPI to a target task. The
+ uipi_index is obtained using uintr_register_sender(2).
+
+
+ Interrupt handler restrictions
+ There are restrictions on what can be done in a user interrupt handler.
+
+ For example, the handler and the functions called from the handler
+ should only use general purpose registers.
+
+ For details refer the Uintr compiler programming guide.
+ https://github.com/intel/uintr-compiler-guide/blob/uintr-
+ gcc-11.1/UINTR-compiler-guide.pdf
+
+
+CONFORMING TO
+ Uintr related system calls are Linux specific.
+
+EXAMPLES
+ Build
+ To compile this sample an updated toolchain is needed.
+ - Use GCC release 11 or higher &
+ - Use Binutils release 2.36 or higher
+
+ gcc -muintr -mgeneral-regs-only -minline-all-stringops uipi_sample.c -lpthread -o uipi_sample
+
+
+ Run
+ $./uipi_sample
+ Receiver enabled interrupts
+ Sending IPI from sender thread
+ -- User Interrupt handler --
+ Success
+
+
+ Program source
+ #define _GNU_SOURCE
+ #include <pthread.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <syscall.h>
+ #include <unistd.h>
+ #include <x86gprintrin.h>
+
+ #define __NR_uintr_register_handler 449
+ #define __NR_uintr_unregister_handler 450
+ #define __NR_uintr_create_fd 451
+ #define __NR_uintr_register_sender 452
+ #define __NR_uintr_unregister_sender 453
+
+ #define uintr_register_handler(handler, flags) syscall(__NR_uintr_register_handler, handler, flags)
+ #define uintr_unregister_handler(flags) syscall(__NR_uintr_unregister_handler, flags)
+ #define uintr_create_fd(vector, flags) syscall(__NR_uintr_create_fd, vector, flags)
+ #define uintr_register_sender(fd, flags) syscall(__NR_uintr_register_sender, fd, flags)
+ #define uintr_unregister_sender(fd, flags) syscall(__NR_uintr_unregister_sender, fd, flags)
+
+ unsigned int uintr_received;
+ unsigned int uintr_fd;
+
+ void __attribute__ ((interrupt)) uintr_handler(struct __uintr_frame *ui_frame,
+ unsigned long long vector)
+ {
+ static const char print[] = "\t-- User Interrupt handler --\n";
+
+ write(STDOUT_FILENO, print, sizeof(print) - 1);
+ uintr_received = 1;
+ }
+
+ void *sender_thread(void *arg)
+ {
+ int uipi_index;
+
+ uipi_index = uintr_register_sender(uintr_fd, 0);
+ if (uipi_index < 0) {
+ printf("Sender register error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Sending IPI from sender thread\n");
+ _senduipi(uipi_index);
+
+ uintr_unregister_sender(uintr_fd, 0);
+
+ return NULL;
+ }
+
+ int main(int argc, char *argv[])
+ {
+ pthread_t pt;
+
+ if (uintr_register_handler(uintr_handler, 0)) {
+ printf("Interrupt handler register error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ uintr_fd = uintr_create_fd(0, 0);
+ if (uintr_fd < 0) {
+ printf("Interrupt vector registration error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ _stui();
+ printf("Receiver enabled interrupts\n");
+
+ if (pthread_create(&pt, NULL, &sender_thread, NULL)) {
+ printf("Error creating sender thread\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Do some other work */
+ while (!uintr_received)
+ usleep(1);
+
+ pthread_join(pt, NULL);
+ close(uintr_fd);
+ uintr_unregister_handler(0);
+
+ printf("Success\n");
+ exit(EXIT_SUCCESS);
+ }
+
+
+NOTES
+ Currently, there is no glibc wrapper for the Uintr related system call;
+ call the system calls using syscall(2).
+
+
+
+ UINTR(7)
diff --git a/tools/uintr/manpages/1_register_receiver.txt b/tools/uintr/manpages/1_register_receiver.txt
new file mode 100644
index 000000000000..4b6652c94faa
--- /dev/null
+++ b/tools/uintr/manpages/1_register_receiver.txt
@@ -0,0 +1,122 @@
+uintr_register_handler(2) System Calls Manual uintr_register_handler(2)
+
+
+
+NAME
+ uintr_register_handler - register a user interrupt handler
+
+
+SYNOPSIS
+ int uintr_register_handler(u64 handler_address, unsigned int flags);
+
+
+DESCRIPTION
+ uintr_register_handler() registers a user interrupt handler for the
+ calling process. In case of multi-threaded processes the user interrupt
+ handler is only registered for the thread that makes this system call.
+
+ The handler_address is the function that would be invoked when the
+ process receives a user interrupt. The function should be defined as
+ below:
+
+ void __attribute__ ((interrupt)) ui_handler(struct __uintr_frame *frame,
+ unsigned long long vector)
+
+ For more details and an example for the handler definition refer
+ uintr(7).
+
+ Providing an invalid handler_address could lead to undefined behavior
+ for the process.
+
+ The flags argument is reserved for future use. Currently, it must be
+ specified as 0.
+
+ Each user thread can register only one interrupt handler. Each thread
+ that would like to be a receiver must register once. The registration
+ is not inherited across forks(2) or when additional threads are created
+ within the same process.
+
+ Each thread within a process gets its own interrupt vector space for 64
+ vectors. The vector number is pushed onto the stack when a user
+ interrupt is delivered. Since the vector space is per-thread, each
+ receiver can receive up to 64 unique interrupt events.
+
+ For information on creating uintr_fd to register and manage interrupt
+ vectors, refer uintr_create_fd(2) system call.
+
+ Once an interrupt handler is registered it cannot be changed before the
+ handler is unregistered via uintr_unregister_handler(2). Calling
+ uintr_unregister_handler(2) would however invalidate the current
+ interrupt resources registered with the kernel.
+
+ The interrupt handler gets invoked only while the process is running.
+ If the process is scheduled out or blocked in the kernel, interrupts
+ will be delivered when the process is scheduled again. <A mechanism to
+ unblock a process as soon as a user interrupt is posted is being worked
+ upon.>
+
+
+ Interrupt handler restrictions
+ There are restrictions on what can be done in a user interrupt handler.
+
+ For example, the handler and the functions called from the handler
+ should only use general purpose registers.
+
+ For details refer the Uintr compiler programming guide.
+ https://github.com/intel/uintr-compiler-guide/blob/uintr-
+ gcc-11.1/UINTR-compiler-guide.pdf
+
+
+ Security implications
+ A lot of security issues that are applicable to signal handlers, also
+ apply to user interrupt handlers.
+
+ The user interrupt handler by-itself need not be re-entrant since
+ interrupts are automatically disabled when the handler is invoked. But
+ this isn't valid if the handler is shared between multiple threads or
+ nested interrupts have been enabled.
+
+ Similar to signal handlers, the functions that are called from a user
+ interrupt should be async-signal-safe. Refer signal-safety(7) for a
+ discussion of async-signal-safe functions.
+
+ It is recommended to disable interrupts using _clui() instruction
+ before executing any privileged code. Doing so would prevent a user
+ interrupt handler from running at a higher privilege level.
+
+
+RETURN VALUE
+ On success, uintr_register_handler() returns 0. On error, -1 is
+ returned and errno is set to indicate the cause of the error.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for Uintr.
+
+ EINVAL flags is not 0.
+
+ EFAULT handler address is not valid.
+
+ ENOMEM The system is out of available memory.
+
+ EBUSY An interrupt handler has already been registered.
+
+
+VERSIONS
+ uintr_register_handler() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_register_handler() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_register_handler(2)
diff --git a/tools/uintr/manpages/2_unregister_receiver.txt b/tools/uintr/manpages/2_unregister_receiver.txt
new file mode 100644
index 000000000000..dd6981f33597
--- /dev/null
+++ b/tools/uintr/manpages/2_unregister_receiver.txt
@@ -0,0 +1,62 @@
+uintr_unregister_handler(2) System Calls Manual uintr_unregister_handler(2)
+
+
+
+NAME
+ uintr_unregister_handler - unregister a user interrupt handler
+
+
+SYNOPSIS
+ int uintr_unregister_handler(unsigned int flags);
+
+
+DESCRIPTION
+ uintr_unregister_handler() unregisters a previously registered user
+ interrupt handler. If no interrupt handler was registered by the
+ process uintr_unregister_handler() would return an error.
+
+ Since interrupt handler is local to a thread, only the thread that has
+ registered via uintr_register_handler(2) can call
+ uintr_unregister_handler().
+
+ The interrupt resources such as interrupt vectors and uintr_fd, that
+ have been allocated for this thread, would be deactivated. Other
+ senders posting interrupts to this thread will not be delivered.
+
+ The kernel does not automatically close the uintr_fds related to this
+ process/thread when uintr_unregister_handler() is called. The
+ application is expected to close the unused uintr_fds before or the
+ after the handler has been unregistered.
+
+
+RETURN VALUE
+ On success, uintr_unregister_handler() returns 0. On error, -1 is
+ returned and errno is set to indicate the cause of the error.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for Uintr.
+
+ EINVAL flags is not 0.
+
+ EINVAL No registered user interrupt handler.
+
+
+VERSIONS
+ uintr_unregister_handler() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_unregister_handler() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_unregister_handler(2)
diff --git a/tools/uintr/manpages/3_create_fd.txt b/tools/uintr/manpages/3_create_fd.txt
new file mode 100644
index 000000000000..e90b0dce2703
--- /dev/null
+++ b/tools/uintr/manpages/3_create_fd.txt
@@ -0,0 +1,104 @@
+uintr_create_fd(2) System Calls Manual uintr_create_fd(2)
+
+
+
+NAME
+ uintr_create_fd - Create a user interrupt file descriptor - uintr_fd
+
+
+SYNOPSIS
+ int uintr_create_fd(u64 vector, unsigned int flags);
+
+
+DESCRIPTION
+ uintr_create_fd() allocates a new user interrupt file descriptor
+ (uintr_fd) based on the vector registered by the calling process. The
+ uintr_fd can be shared with other processes and the kernel to allow
+ them to generate interrupts with the associated vector.
+
+ The caller must have registered a handler via uintr_register_handler(2)
+ before attempting to create uintr_fd. The interrupts generated based on
+ this uintr_fd will be delivered only to the thread that created this
+ file descriptor. A unique uintr_fd is generated for each vector
+ registered using uintr_create_fd().
+
+ Each thread has a private vector space of 64 vectors ranging from 0-63.
+ Vector number 63 has the highest priority while vector number 0 has the
+ lowest. If two or more interrupts are pending to be delivered then the
+ interrupt with the higher vector number will be delivered first
+ followed by the ones with lower vector numbers. Applications can choose
+ appropriate vector numbers to prioritize certain interrupts over
+ others.
+
+ Upon interrupt delivery, the handler is invoked with the vector number
+ pushed onto the stack to help identify the source of the interrupt.
+ Since the vector space is per-thread, each receiver can receive up to
+ 64 unique interrupt events.
+
+ A receiver can choose to share the same uintr_fd with multiple senders.
+ Since an interrupt with the same vector number would be delivered, the
+ receiver would need to use other mechanisms to identify the exact
+ source of the interrupt.
+
+ The flags argument is reserved for future use. Currently, it must be
+ specified as 0.
+
+ close(2)
+ When the file descriptor is no longer required it should be
+ closed. When all file descriptors associated with the same
+ uintr_fd object have been closed, the resources for object are
+ freed by the kernel.
+
+ fork(2)
+ A copy of the file descriptor created by uintr_create_fd() is
+ inherited by the child produced by fork(2). The duplicate file
+ descriptor is associated with the same uintr_fd object. The
+ close-on-exec flag (FD_CLOEXEC; see fcntl(2)) is set on the
+ file descriptor returned by uintr_create_fd().
+
+ For information on how to generate interrupts with uintr_fd refer
+ uintr_register_sender(2).
+
+
+RETURN VALUE
+ On success, uintr_create_fd() returns a new uintr_fd file descriptor.
+ On error, -1 is returned and errno is set to indicate the cause of the
+ error.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for Uintr.
+
+ EINVAL flags is not 0.
+
+ EFAULT handler address is not valid.
+
+ EMFILE The per-process limit on the number of open file
+ descriptors has been reached.
+
+ ENFILE The system-wide limit on the total number of open files
+ has been reached.
+
+ ENODEV Could not mount (internal) anonymous inode device.
+
+ ENOMEM The system is out of available memory to allocate uintr_fd.
+
+
+VERSIONS
+ uintr_create_fd() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_create_fd() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_create_fd(2)
diff --git a/tools/uintr/manpages/4_register_sender.txt b/tools/uintr/manpages/4_register_sender.txt
new file mode 100644
index 000000000000..1dc17f4c041f
--- /dev/null
+++ b/tools/uintr/manpages/4_register_sender.txt
@@ -0,0 +1,121 @@
+uintr_register_sender(2) System Calls Manual uintr_register_sender(2)
+
+
+
+NAME
+ uintr_register_sender - Register a user inter-process interrupt sender
+
+
+SYNOPSIS
+ int uintr_register_sender(int uintr_fd, unsigned int flags);
+
+
+DESCRIPTION
+ uintr_register_sender() allows a sender process to connect with a Uintr
+ receiver based on the uintr_fd. It returns a user IPI index
+ (uipi_index) that the sender process can use in conjunction with the
+ SENDUIPI instruction to generate a user IPI.
+
+ When a sender executes 'SENDUIPI <uipi_index>', a user IPI can be
+ delivered by the hardware to the receiver without any intervention from
+ the kernel. Upon IPI delivery, the handler is invoked with the vector
+ number, associated with uintr_fd, pushed onto the stack to help
+ identify the source of the interrupt.
+
+ If the receiver for the thread is running the hardware would directly
+ deliver the user IPI to the receiver. If the receiver is not running or
+ has disabled receiving interrupts using the STUI instruction, the
+ interrupt will be stored in memory and delivered when the receiver is
+ able to receive it.
+
+ If the sender tries to send multiple IPIs while the receiver is not
+ able to receive them then all the IPIs with the same vector would be
+ coalesced. Only a single IPI per vector would be delivered.
+
+ uintr_register_sender() can be used to connect with multiple uintr_fds.
+ uintr_register_sender() would return a unique uipi_index for each
+ uintr_fd the sender connects with.
+
+ In case of a multi-threaded process, the uipi_index is only valid for
+ the thread that registered itself. Other threads would need to register
+ themselves if they intend to be a user IPI sender. Executing SENDUIPI
+ on different threads can have varying results based on the connections
+ that have been setup.
+
+ <We are also considering an alternate approach where the same
+ uipi_index would be valid for all threads that are part of the same
+ process. All threads would see consistent SENDUIPI behaviour in that
+ case.>
+
+ If a process uses SENDUIPI without registering using
+ uintr_register_sender() it receives a SIGILL signal. If a process uses
+ an illegal uipi_index, it receives a SIGSEGV signal. See sigaction(2)
+ for details of the information available with that signal.
+
+ The flags argument is reserved for future use. Currently, it must be
+ specified as 0.
+
+ close(2)
+ When the file descriptor is no longer required it should be
+ closed. When all file descriptors associated with the same
+ uintr_fd object have been closed, the resources for object are
+ freed by the kernel. Freeing the uintr_fd object would also
+ result in the associated uipi_index to be freed.
+
+ fork(2)
+ A copy of uintr_fd is inherited by the child produced by
+ fork(2). However the uipi_index would not get inherited by the
+ child. If the child wants to send a user IPI it would have to
+ explicitly register itself using the uintr_register_sender()
+ system call.
+
+ For information on how to unregister a sender refer
+ uintr_unregister_sender(2).
+
+
+RETURN VALUE
+ On success, uintr_register_sender() returns a new user IPI index -
+ uipi_index. On error, -1 is returned and errno is set to indicate the
+ cause of the error.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for uintr(7).
+
+ EOPNOTSUPP uintr_fd does not refer to a Uintr instance.
+
+ EBADF The uintr_fd passed to the kernel is invalid.
+
+ EINVAL flags is not 0.
+
+ EISCONN A connection to this uintr_fd has already been established.
+
+ ECONNRESET The user interrupt receiver has disabled the connection.
+
+ ESHUTDOWN The user interrupt receiver has exited the connection.
+
+ ENOSPC No uipi_index can be allocated. The system has run out of
+ the available user IPI indexes.
+
+ ENOMEM The system is out of available memory to register a user
+ IPI sender.
+
+
+VERSIONS
+ uintr_register_sender() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_register_sender() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_register_sender(2)
diff --git a/tools/uintr/manpages/5_unregister_sender.txt b/tools/uintr/manpages/5_unregister_sender.txt
new file mode 100644
index 000000000000..31a8c574dc25
--- /dev/null
+++ b/tools/uintr/manpages/5_unregister_sender.txt
@@ -0,0 +1,79 @@
+uintr_unregister_sender(2) System Calls Manual uintr_unregister_sender(2)
+
+
+
+NAME
+ uintr_unregister_sender - Unregister a user inter-process interrupt
+ sender
+
+
+SYNOPSIS
+ int uintr_unregister_sender(int uintr_fd, unsigned int flags);
+
+
+DESCRIPTION
+ uintr_unregister_sender() unregisters a sender process from a uintr_fd
+ it had previously connected with. If no connection is present with this
+ uintr_fd the system call return an error.
+
+ The uipi_index that was allocated during uintr_register_sender(2) will
+ also be freed. If a process tries to use a uipi_index after it has been
+ freed it would receive a SIGSEGV signal.
+
+ In case of a multi-threaded process uintr_unregister_sender() will only
+ disconnect the thread that makes this call. Other threads can continue
+ to use their connection with the uintr_fd based on their uipi_index.
+
+ <We are considering an alternate approach where all threads in a
+ process see a consistent view of the uipi_index. In that case,
+ uintr_unregister_sender() would disconnect all threads from uintr_fd.>
+
+ The flags argument is reserved for future use. Currently, it must be
+ specified as 0.
+
+ close(2)
+ When the file descriptor is no longer required it should be
+ closed. When all file descriptors associated with the same
+ uintr_fd object have been closed, the resources for object are
+ freed by the kernel. Freeing the uintr_fd object would also
+ result in the associated uipi_index to be freed.
+
+ The behavior of uintr_unregister_sender() system call after uintr_fd
+ has been close is undefined.
+
+
+RETURN VALUE
+ On success, uintr_unregister_sender() returns 0. On error, -1 is
+ returned and errno is set to indicate the cause of the error.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for uintr(7).
+
+ EOPNOTSUPP uintr_fd does not refer to a Uintr instance.
+
+ EBADF The uintr_fd passed to the kernel is invalid.
+
+ EINVAL flags is not 0.
+
+ EINVAL No connection has been setup with this uintr_fd.
+
+
+VERSIONS
+ uintr_unregister_sender() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_unregister_sender() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_unregister_sender(2)
diff --git a/tools/uintr/manpages/6_wait.txt b/tools/uintr/manpages/6_wait.txt
new file mode 100644
index 000000000000..f281a6ce83aa
--- /dev/null
+++ b/tools/uintr/manpages/6_wait.txt
@@ -0,0 +1,59 @@
+uintr_wait(2) System Calls Manual uintr_wait(2)
+
+
+
+NAME
+ uintr_wait - wait for user interrupts
+
+
+SYNOPSIS
+ int uintr_wait(unsigned int flags);
+
+
+DESCRIPTION
+ uintr_wait() causes the calling process (or thread) to sleep until a
+ user interrupt is delivered.
+
+ uintr_wait() will block in the kernel only when a interrupt handler has
+ been registered using uintr_register_handler(2)
+
+ <uintr_wait() is a placeholder syscall while we decide on the behaviour
+ of blocking system calls like sleep(2) and read(2) being interrupted by
+ uintr(7).>
+
+
+RETURN VALUE
+ uintr_wait() returns only when a user interrupt is received and the
+ interrupt handler function returned. In this case, -1 is returned and
+ errno is set to EINTR.
+
+
+ERRORS
+ EOPNOTSUPP Underlying hardware doesn't have support for Uintr.
+
+ EOPNOTSUPP No interrupt handler registered.
+
+ EINVAL flags is not 0.
+
+ EINTR A user interrupt was received and the interrupt handler
+ returned.
+
+
+VERSIONS
+ uintr_wait() first appeared in Linux <tbd>.
+
+
+CONFORMING TO
+ uintr_wait() is Linux specific.
+
+
+NOTES
+ Currently, there is no glibc wrapper for this system call; call it
+ using syscall(2).
+
+ The user interrupt related system calls need hardware support to
+ generate and receive user interrupts. Refer uintr(7) for details.
+
+
+
+ uintr_wait(2)
--
2.33.0