mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
11 KiB
305 lines
11 KiB
.. SPDX-License-Identifier: GPL-2.0 |
|
.. _VAS-API: |
|
|
|
=================================================== |
|
Virtual Accelerator Switchboard (VAS) userspace API |
|
=================================================== |
|
|
|
Introduction |
|
============ |
|
|
|
Power9 processor introduced Virtual Accelerator Switchboard (VAS) which |
|
allows both userspace and kernel communicate to co-processor |
|
(hardware accelerator) referred to as the Nest Accelerator (NX). The NX |
|
unit comprises of one or more hardware engines or co-processor types |
|
such as 842 compression, GZIP compression and encryption. On power9, |
|
userspace applications will have access to only GZIP Compression engine |
|
which supports ZLIB and GZIP compression algorithms in the hardware. |
|
|
|
To communicate with NX, kernel has to establish a channel or window and |
|
then requests can be submitted directly without kernel involvement. |
|
Requests to the GZIP engine must be formatted as a co-processor Request |
|
Block (CRB) and these CRBs must be submitted to the NX using COPY/PASTE |
|
instructions to paste the CRB to hardware address that is associated with |
|
the engine's request queue. |
|
|
|
The GZIP engine provides two priority levels of requests: Normal and |
|
High. Only Normal requests are supported from userspace right now. |
|
|
|
This document explains userspace API that is used to interact with |
|
kernel to setup channel / window which can be used to send compression |
|
requests directly to NX accelerator. |
|
|
|
|
|
Overview |
|
======== |
|
|
|
Application access to the GZIP engine is provided through |
|
/dev/crypto/nx-gzip device node implemented by the VAS/NX device driver. |
|
An application must open the /dev/crypto/nx-gzip device to obtain a file |
|
descriptor (fd). Then should issue VAS_TX_WIN_OPEN ioctl with this fd to |
|
establish connection to the engine. It means send window is opened on GZIP |
|
engine for this process. Once a connection is established, the application |
|
should use the mmap() system call to map the hardware address of engine's |
|
request queue into the application's virtual address space. |
|
|
|
The application can then submit one or more requests to the engine by |
|
using copy/paste instructions and pasting the CRBs to the virtual address |
|
(aka paste_address) returned by mmap(). User space can close the |
|
established connection or send window by closing the file descriptior |
|
(close(fd)) or upon the process exit. |
|
|
|
Note that applications can send several requests with the same window or |
|
can establish multiple windows, but one window for each file descriptor. |
|
|
|
Following sections provide additional details and references about the |
|
individual steps. |
|
|
|
NX-GZIP Device Node |
|
=================== |
|
|
|
There is one /dev/crypto/nx-gzip node in the system and it provides |
|
access to all GZIP engines in the system. The only valid operations on |
|
/dev/crypto/nx-gzip are: |
|
|
|
* open() the device for read and write. |
|
* issue VAS_TX_WIN_OPEN ioctl |
|
* mmap() the engine's request queue into application's virtual |
|
address space (i.e. get a paste_address for the co-processor |
|
engine). |
|
* close the device node. |
|
|
|
Other file operations on this device node are undefined. |
|
|
|
Note that the copy and paste operations go directly to the hardware and |
|
do not go through this device. Refer COPY/PASTE document for more |
|
details. |
|
|
|
Although a system may have several instances of the NX co-processor |
|
engines (typically, one per P9 chip) there is just one |
|
/dev/crypto/nx-gzip device node in the system. When the nx-gzip device |
|
node is opened, Kernel opens send window on a suitable instance of NX |
|
accelerator. It finds CPU on which the user process is executing and |
|
determine the NX instance for the corresponding chip on which this CPU |
|
belongs. |
|
|
|
Applications may chose a specific instance of the NX co-processor using |
|
the vas_id field in the VAS_TX_WIN_OPEN ioctl as detailed below. |
|
|
|
A userspace library libnxz is available here but still in development: |
|
|
|
https://github.com/abalib/power-gzip |
|
|
|
Applications that use inflate / deflate calls can link with libnxz |
|
instead of libz and use NX GZIP compression without any modification. |
|
|
|
Open /dev/crypto/nx-gzip |
|
======================== |
|
|
|
The nx-gzip device should be opened for read and write. No special |
|
privileges are needed to open the device. Each window corresponds to one |
|
file descriptor. So if the userspace process needs multiple windows, |
|
several open calls have to be issued. |
|
|
|
See open(2) system call man pages for other details such as return values, |
|
error codes and restrictions. |
|
|
|
VAS_TX_WIN_OPEN ioctl |
|
===================== |
|
|
|
Applications should use the VAS_TX_WIN_OPEN ioctl as follows to establish |
|
a connection with NX co-processor engine: |
|
|
|
:: |
|
|
|
struct vas_tx_win_open_attr { |
|
__u32 version; |
|
__s16 vas_id; /* specific instance of vas or -1 |
|
for default */ |
|
__u16 reserved1; |
|
__u64 flags; /* For future use */ |
|
__u64 reserved2[6]; |
|
}; |
|
|
|
version: |
|
The version field must be currently set to 1. |
|
vas_id: |
|
If '-1' is passed, kernel will make a best-effort attempt |
|
to assign an optimal instance of NX for the process. To |
|
select the specific VAS instance, refer |
|
"Discovery of available VAS engines" section below. |
|
|
|
flags, reserved1 and reserved2[6] fields are for future extension |
|
and must be set to 0. |
|
|
|
The attributes attr for the VAS_TX_WIN_OPEN ioctl are defined as |
|
follows:: |
|
|
|
#define VAS_MAGIC 'v' |
|
#define VAS_TX_WIN_OPEN _IOW(VAS_MAGIC, 1, |
|
struct vas_tx_win_open_attr) |
|
|
|
struct vas_tx_win_open_attr attr; |
|
rc = ioctl(fd, VAS_TX_WIN_OPEN, &attr); |
|
|
|
The VAS_TX_WIN_OPEN ioctl returns 0 on success. On errors, it |
|
returns -1 and sets the errno variable to indicate the error. |
|
|
|
Error conditions: |
|
|
|
====== ================================================ |
|
EINVAL fd does not refer to a valid VAS device. |
|
EINVAL Invalid vas ID |
|
EINVAL version is not set with proper value |
|
EEXIST Window is already opened for the given fd |
|
ENOMEM Memory is not available to allocate window |
|
ENOSPC System has too many active windows (connections) |
|
opened |
|
EINVAL reserved fields are not set to 0. |
|
====== ================================================ |
|
|
|
See the ioctl(2) man page for more details, error codes and |
|
restrictions. |
|
|
|
mmap() NX-GZIP device |
|
===================== |
|
|
|
The mmap() system call for a NX-GZIP device fd returns a paste_address |
|
that the application can use to copy/paste its CRB to the hardware engines. |
|
|
|
:: |
|
|
|
paste_addr = mmap(addr, size, prot, flags, fd, offset); |
|
|
|
Only restrictions on mmap for a NX-GZIP device fd are: |
|
|
|
* size should be PAGE_SIZE |
|
* offset parameter should be 0ULL |
|
|
|
Refer to mmap(2) man page for additional details/restrictions. |
|
In addition to the error conditions listed on the mmap(2) man |
|
page, can also fail with one of the following error codes: |
|
|
|
====== ============================================= |
|
EINVAL fd is not associated with an open window |
|
(i.e mmap() does not follow a successful call |
|
to the VAS_TX_WIN_OPEN ioctl). |
|
EINVAL offset field is not 0ULL. |
|
====== ============================================= |
|
|
|
Discovery of available VAS engines |
|
================================== |
|
|
|
Each available VAS instance in the system will have a device tree node |
|
like /proc/device-tree/vas@* or /proc/device-tree/xscom@*/vas@*. |
|
Determine the chip or VAS instance and use the corresponding ibm,vas-id |
|
property value in this node to select specific VAS instance. |
|
|
|
Copy/Paste operations |
|
===================== |
|
|
|
Applications should use the copy and paste instructions to send CRB to NX. |
|
Refer section 4.4 in PowerISA for Copy/Paste instructions: |
|
https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0 |
|
|
|
CRB Specification and use NX |
|
============================ |
|
|
|
Applications should format requests to the co-processor using the |
|
co-processor Request Block (CRBs). Refer NX-GZIP user's manual for the format |
|
of CRB and use NX from userspace such as sending requests and checking |
|
request status. |
|
|
|
NX Fault handling |
|
================= |
|
|
|
Applications send requests to NX and wait for the status by polling on |
|
co-processor Status Block (CSB) flags. NX updates status in CSB after each |
|
request is processed. Refer NX-GZIP user's manual for the format of CSB and |
|
status flags. |
|
|
|
In case if NX encounters translation error (called NX page fault) on CSB |
|
address or any request buffer, raises an interrupt on the CPU to handle the |
|
fault. Page fault can happen if an application passes invalid addresses or |
|
request buffers are not in memory. The operating system handles the fault by |
|
updating CSB with the following data:: |
|
|
|
csb.flags = CSB_V; |
|
csb.cc = CSB_CC_FAULT_ADDRESS; |
|
csb.ce = CSB_CE_TERMINATION; |
|
csb.address = fault_address; |
|
|
|
When an application receives translation error, it can touch or access |
|
the page that has a fault address so that this page will be in memory. Then |
|
the application can resend this request to NX. |
|
|
|
If the OS can not update CSB due to invalid CSB address, sends SEGV signal |
|
to the process who opened the send window on which the original request was |
|
issued. This signal returns with the following siginfo struct:: |
|
|
|
siginfo.si_signo = SIGSEGV; |
|
siginfo.si_errno = EFAULT; |
|
siginfo.si_code = SEGV_MAPERR; |
|
siginfo.si_addr = CSB adress; |
|
|
|
In the case of multi-thread applications, NX send windows can be shared |
|
across all threads. For example, a child thread can open a send window, |
|
but other threads can send requests to NX using this window. These |
|
requests will be successful even in the case of OS handling faults as long |
|
as CSB address is valid. If the NX request contains an invalid CSB address, |
|
the signal will be sent to the child thread that opened the window. But if |
|
the thread is exited without closing the window and the request is issued |
|
using this window. the signal will be issued to the thread group leader |
|
(tgid). It is up to the application whether to ignore or handle these |
|
signals. |
|
|
|
NX-GZIP User's Manual: |
|
https://github.com/libnxz/power-gzip/blob/master/power_nx_gzip_um.pdf |
|
|
|
Simple example |
|
============== |
|
|
|
:: |
|
|
|
int use_nx_gzip() |
|
{ |
|
int rc, fd; |
|
void *addr; |
|
struct vas_setup_attr txattr; |
|
|
|
fd = open("/dev/crypto/nx-gzip", O_RDWR); |
|
if (fd < 0) { |
|
fprintf(stderr, "open nx-gzip failed\n"); |
|
return -1; |
|
} |
|
memset(&txattr, 0, sizeof(txattr)); |
|
txattr.version = 1; |
|
txattr.vas_id = -1 |
|
rc = ioctl(fd, VAS_TX_WIN_OPEN, |
|
(unsigned long)&txattr); |
|
if (rc < 0) { |
|
fprintf(stderr, "ioctl() n %d, error %d\n", |
|
rc, errno); |
|
return rc; |
|
} |
|
addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, |
|
MAP_SHARED, fd, 0ULL); |
|
if (addr == MAP_FAILED) { |
|
fprintf(stderr, "mmap() failed, errno %d\n", |
|
errno); |
|
return -errno; |
|
} |
|
do { |
|
//Format CRB request with compression or |
|
//uncompression |
|
// Refer tests for vas_copy/vas_paste |
|
vas_copy((&crb, 0, 1); |
|
vas_paste(addr, 0, 1); |
|
// Poll on csb.flags with timeout |
|
// csb address is listed in CRB |
|
} while (true) |
|
close(fd) or window can be closed upon process exit |
|
} |
|
|
|
Refer https://github.com/abalib/power-gzip for tests or more |
|
use cases.
|
|
|