Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp238369pxb; Mon, 13 Sep 2021 18:01:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyZF8FkCmZHkEm71FCtifbd5TX0IMQZgFuG5sK7bJL1fMjeVjH8Fau4rjvAwLEIDaQW8lCQ X-Received: by 2002:a92:cd81:: with SMTP id r1mr9981828ilb.279.1631581312914; Mon, 13 Sep 2021 18:01:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631581312; cv=none; d=google.com; s=arc-20160816; b=UvIArrnfwEVmwYm5RWs36eBA3BxzKOTpPvU5ZBevylYGTwxbBoRDHmfn3tPeuDta5d DqTgiTzL//iFBcOYvwHERBBamkwA7eC8ZKLIVBaJiw6UDhW9j2a9wRoV/DL1BsBd0TtF XXTpltcSdwbDpBlvIMAbuK/vEFJqYLaWhdh8X81tQCe2L6kZvp/to1io/Wev21yrsYUO gv36v7geYOVJmKvqkacMp2mJ+ryz/yicfLXI+MiGQ/qoxCFOAIQs0tWReNOkPZzrblri l3HdKOW4rMv53O88fx1DTjrZ9olXhSBC5R+BZ5nnyTRkoUyJH8L4PkAfRooMbHZg9wWW o/RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=0MUfRrjcvnoyL94SU/yl97HdeAv0vbLZpx5LbOnr4gA=; b=STZWshoNQg3VIxvCUsHwpQVR/BRc/1XN0UyaZq3xk+0q+Jte0nTSxlzy+Ztwz4aohE ZabcYZWqqYNgi6Dj3NnMUFVwtt1pfmqa1GZ4Yd+w3eZdXjWonLrkYOUhdFFJ3ktRbbzX gl7HU6lal2wtFxtdaWw3km2abiOuTFLfpWn2rmOBmWMd1BVVL8LXocM7eBpMIDH+UjBj nAekfSkKeNHgEIdsryy3p1owKfwV/aDAR+8MmxznOnTyE1YnLvWnAVD6AHFIf0PYbkh8 f4ysipTGDV+kpbCLrMPdyvmMjp0pHZds95DMMJBODvijUARuLWYYQ1sFSIBljdB5EGjW wmxQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e16si8749634ilm.91.2021.09.13.18.01.41; Mon, 13 Sep 2021 18:01:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347838AbhIMUFv (ORCPT + 99 others); Mon, 13 Sep 2021 16:05:51 -0400 Received: from mga05.intel.com ([192.55.52.43]:38689 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241346AbhIMUFq (ORCPT ); Mon, 13 Sep 2021 16:05:46 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10106"; a="307336355" X-IronPort-AV: E=Sophos;i="5.85,290,1624345200"; d="scan'208";a="307336355" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Sep 2021 13:04:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.85,290,1624345200"; d="scan'208";a="469643902" Received: from sohilbuildbox.sc.intel.com (HELO localhost.localdomain) ([172.25.110.4]) by fmsmga007.fm.intel.com with ESMTP; 13 Sep 2021 13:04:29 -0700 From: Sohil Mehta To: x86@kernel.org Cc: Sohil Mehta , Tony Luck , Dave Hansen , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H . Peter Anvin" , Andy Lutomirski , Jens Axboe , Christian Brauner , Peter Zijlstra , Shuah Khan , Arnd Bergmann , Jonathan Corbet , Ashok Raj , Jacob Pan , Gayatri Kammela , Zeng Guang , Dan Williams , Randy E Witt , Ravi V Shankar , Ramesh Thomas , linux-api@vger.kernel.org, linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC PATCH 01/13] x86/uintr/man-page: Include man pages draft for reference Date: Mon, 13 Sep 2021 13:01:20 -0700 Message-Id: <20210913200132.3396598-2-sohil.mehta@intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210913200132.3396598-1-sohil.mehta@intel.com> References: <20210913200132.3396598-1-sohil.mehta@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Included here in plain text format for reference and review. The formatting for the man pages still needs a little bit of work. Signed-off-by: Sohil Mehta --- 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 ' 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. + + 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. + + + + 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 - + : + + _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 - 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 + #include + #include + #include + #include + #include + + #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. + + + 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 . + + +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 . + + +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 . + + +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 ', 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. + + + + 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 . + + +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. + + + + 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 . + + +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) + + + + +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 . + + +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