linux/Documentation/powerpc/vas-api.rst
<<
>>
Prefs
   1.. SPDX-License-Identifier: GPL-2.0
   2.. _VAS-API:
   3
   4===================================================
   5Virtual Accelerator Switchboard (VAS) userspace API
   6===================================================
   7
   8Introduction
   9============
  10
  11Power9 processor introduced Virtual Accelerator Switchboard (VAS) which
  12allows both userspace and kernel communicate to co-processor
  13(hardware accelerator) referred to as the Nest Accelerator (NX). The NX
  14unit comprises of one or more hardware engines or co-processor types
  15such as 842 compression, GZIP compression and encryption. On power9,
  16userspace applications will have access to only GZIP Compression engine
  17which supports ZLIB and GZIP compression algorithms in the hardware.
  18
  19To communicate with NX, kernel has to establish a channel or window and
  20then requests can be submitted directly without kernel involvement.
  21Requests to the GZIP engine must be formatted as a co-processor Request
  22Block (CRB) and these CRBs must be submitted to the NX using COPY/PASTE
  23instructions to paste the CRB to hardware address that is associated with
  24the engine's request queue.
  25
  26The GZIP engine provides two priority levels of requests: Normal and
  27High. Only Normal requests are supported from userspace right now.
  28
  29This document explains userspace API that is used to interact with
  30kernel to setup channel / window which can be used to send compression
  31requests directly to NX accelerator.
  32
  33
  34Overview
  35========
  36
  37Application access to the GZIP engine is provided through
  38/dev/crypto/nx-gzip device node implemented by the VAS/NX device driver.
  39An application must open the /dev/crypto/nx-gzip device to obtain a file
  40descriptor (fd). Then should issue VAS_TX_WIN_OPEN ioctl with this fd to
  41establish connection to the engine. It means send window is opened on GZIP
  42engine for this process. Once a connection is established, the application
  43should use the mmap() system call to map the hardware address of engine's
  44request queue into the application's virtual address space.
  45
  46The application can then submit one or more requests to the engine by
  47using copy/paste instructions and pasting the CRBs to the virtual address
  48(aka paste_address) returned by mmap(). User space can close the
  49established connection or send window by closing the file descriptior
  50(close(fd)) or upon the process exit.
  51
  52Note that applications can send several requests with the same window or
  53can establish multiple windows, but one window for each file descriptor.
  54
  55Following sections provide additional details and references about the
  56individual steps.
  57
  58NX-GZIP Device Node
  59===================
  60
  61There is one /dev/crypto/nx-gzip node in the system and it provides
  62access to all GZIP engines in the system. The only valid operations on
  63/dev/crypto/nx-gzip are:
  64
  65        * open() the device for read and write.
  66        * issue VAS_TX_WIN_OPEN ioctl
  67        * mmap() the engine's request queue into application's virtual
  68          address space (i.e. get a paste_address for the co-processor
  69          engine).
  70        * close the device node.
  71
  72Other file operations on this device node are undefined.
  73
  74Note that the copy and paste operations go directly to the hardware and
  75do not go through this device. Refer COPY/PASTE document for more
  76details.
  77
  78Although a system may have several instances of the NX co-processor
  79engines (typically, one per P9 chip) there is just one
  80/dev/crypto/nx-gzip device node in the system. When the nx-gzip device
  81node is opened, Kernel opens send window on a suitable instance of NX
  82accelerator. It finds CPU on which the user process is executing and
  83determine the NX instance for the corresponding chip on which this CPU
  84belongs.
  85
  86Applications may chose a specific instance of the NX co-processor using
  87the vas_id field in the VAS_TX_WIN_OPEN ioctl as detailed below.
  88
  89A userspace library libnxz is available here but still in development:
  90
  91         https://github.com/abalib/power-gzip
  92
  93Applications that use inflate / deflate calls can link with libnxz
  94instead of libz and use NX GZIP compression without any modification.
  95
  96Open /dev/crypto/nx-gzip
  97========================
  98
  99The nx-gzip device should be opened for read and write. No special
 100privileges are needed to open the device. Each window corresponds to one
 101file descriptor. So if the userspace process needs multiple windows,
 102several open calls have to be issued.
 103
 104See open(2) system call man pages for other details such as return values,
 105error codes and restrictions.
 106
 107VAS_TX_WIN_OPEN ioctl
 108=====================
 109
 110Applications should use the VAS_TX_WIN_OPEN ioctl as follows to establish
 111a connection with NX co-processor engine:
 112
 113        ::
 114
 115                struct vas_tx_win_open_attr {
 116                        __u32   version;
 117                        __s16   vas_id; /* specific instance of vas or -1
 118                                                for default */
 119                        __u16   reserved1;
 120                        __u64   flags;  /* For future use */
 121                        __u64   reserved2[6];
 122                };
 123
 124        version:
 125                The version field must be currently set to 1.
 126        vas_id:
 127                If '-1' is passed, kernel will make a best-effort attempt
 128                to assign an optimal instance of NX for the process. To
 129                select the specific VAS instance, refer
 130                "Discovery of available VAS engines" section below.
 131
 132        flags, reserved1 and reserved2[6] fields are for future extension
 133        and must be set to 0.
 134
 135        The attributes attr for the VAS_TX_WIN_OPEN ioctl are defined as
 136        follows::
 137
 138                #define VAS_MAGIC 'v'
 139                #define VAS_TX_WIN_OPEN _IOW(VAS_MAGIC, 1,
 140                                                struct vas_tx_win_open_attr)
 141
 142                struct vas_tx_win_open_attr attr;
 143                rc = ioctl(fd, VAS_TX_WIN_OPEN, &attr);
 144
 145        The VAS_TX_WIN_OPEN ioctl returns 0 on success. On errors, it
 146        returns -1 and sets the errno variable to indicate the error.
 147
 148        Error conditions:
 149
 150                ======  ================================================
 151                EINVAL  fd does not refer to a valid VAS device.
 152                EINVAL  Invalid vas ID
 153                EINVAL  version is not set with proper value
 154                EEXIST  Window is already opened for the given fd
 155                ENOMEM  Memory is not available to allocate window
 156                ENOSPC  System has too many active windows (connections)
 157                        opened
 158                EINVAL  reserved fields are not set to 0.
 159                ======  ================================================
 160
 161        See the ioctl(2) man page for more details, error codes and
 162        restrictions.
 163
 164mmap() NX-GZIP device
 165=====================
 166
 167The mmap() system call for a NX-GZIP device fd returns a paste_address
 168that the application can use to copy/paste its CRB to the hardware engines.
 169
 170        ::
 171
 172                paste_addr = mmap(addr, size, prot, flags, fd, offset);
 173
 174        Only restrictions on mmap for a NX-GZIP device fd are:
 175
 176                * size should be PAGE_SIZE
 177                * offset parameter should be 0ULL
 178
 179        Refer to mmap(2) man page for additional details/restrictions.
 180        In addition to the error conditions listed on the mmap(2) man
 181        page, can also fail with one of the following error codes:
 182
 183                ======  =============================================
 184                EINVAL  fd is not associated with an open window
 185                        (i.e mmap() does not follow a successful call
 186                        to the VAS_TX_WIN_OPEN ioctl).
 187                EINVAL  offset field is not 0ULL.
 188                ======  =============================================
 189
 190Discovery of available VAS engines
 191==================================
 192
 193Each available VAS instance in the system will have a device tree node
 194like /proc/device-tree/vas@* or /proc/device-tree/xscom@*/vas@*.
 195Determine the chip or VAS instance and use the corresponding ibm,vas-id
 196property value in this node to select specific VAS instance.
 197
 198Copy/Paste operations
 199=====================
 200
 201Applications should use the copy and paste instructions to send CRB to NX.
 202Refer section 4.4 in PowerISA for Copy/Paste instructions:
 203https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0
 204
 205CRB Specification and use NX
 206============================
 207
 208Applications should format requests to the co-processor using the
 209co-processor Request Block (CRBs). Refer NX-GZIP user's manual for the format
 210of CRB and use NX from userspace such as sending requests and checking
 211request status.
 212
 213NX Fault handling
 214=================
 215
 216Applications send requests to NX and wait for the status by polling on
 217co-processor Status Block (CSB) flags. NX updates status in CSB after each
 218request is processed. Refer NX-GZIP user's manual for the format of CSB and
 219status flags.
 220
 221In case if NX encounters translation error (called NX page fault) on CSB
 222address or any request buffer, raises an interrupt on the CPU to handle the
 223fault. Page fault can happen if an application passes invalid addresses or
 224request buffers are not in memory. The operating system handles the fault by
 225updating CSB with the following data::
 226
 227        csb.flags = CSB_V;
 228        csb.cc = CSB_CC_FAULT_ADDRESS;
 229        csb.ce = CSB_CE_TERMINATION;
 230        csb.address = fault_address;
 231
 232When an application receives translation error, it can touch or access
 233the page that has a fault address so that this page will be in memory. Then
 234the application can resend this request to NX.
 235
 236If the OS can not update CSB due to invalid CSB address, sends SEGV signal
 237to the process who opened the send window on which the original request was
 238issued. This signal returns with the following siginfo struct::
 239
 240        siginfo.si_signo = SIGSEGV;
 241        siginfo.si_errno = EFAULT;
 242        siginfo.si_code = SEGV_MAPERR;
 243        siginfo.si_addr = CSB adress;
 244
 245In the case of multi-thread applications, NX send windows can be shared
 246across all threads. For example, a child thread can open a send window,
 247but other threads can send requests to NX using this window. These
 248requests will be successful even in the case of OS handling faults as long
 249as CSB address is valid. If the NX request contains an invalid CSB address,
 250the signal will be sent to the child thread that opened the window. But if
 251the thread is exited without closing the window and the request is issued
 252using this window. the signal will be issued to the thread group leader
 253(tgid). It is up to the application whether to ignore or handle these
 254signals.
 255
 256NX-GZIP User's Manual:
 257https://github.com/libnxz/power-gzip/blob/master/doc/power_nx_gzip_um.pdf
 258
 259Simple example
 260==============
 261
 262        ::
 263
 264                int use_nx_gzip()
 265                {
 266                        int rc, fd;
 267                        void *addr;
 268                        struct vas_setup_attr txattr;
 269
 270                        fd = open("/dev/crypto/nx-gzip", O_RDWR);
 271                        if (fd < 0) {
 272                                fprintf(stderr, "open nx-gzip failed\n");
 273                                return -1;
 274                        }
 275                        memset(&txattr, 0, sizeof(txattr));
 276                        txattr.version = 1;
 277                        txattr.vas_id = -1
 278                        rc = ioctl(fd, VAS_TX_WIN_OPEN,
 279                                        (unsigned long)&txattr);
 280                        if (rc < 0) {
 281                                fprintf(stderr, "ioctl() n %d, error %d\n",
 282                                                rc, errno);
 283                                return rc;
 284                        }
 285                        addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE,
 286                                        MAP_SHARED, fd, 0ULL);
 287                        if (addr == MAP_FAILED) {
 288                                fprintf(stderr, "mmap() failed, errno %d\n",
 289                                                errno);
 290                                return -errno;
 291                        }
 292                        do {
 293                                //Format CRB request with compression or
 294                                //uncompression
 295                                // Refer tests for vas_copy/vas_paste
 296                                vas_copy((&crb, 0, 1);
 297                                vas_paste(addr, 0, 1);
 298                                // Poll on csb.flags with timeout
 299                                // csb address is listed in CRB
 300                        } while (true)
 301                        close(fd) or window can be closed upon process exit
 302                }
 303
 304        Refer https://github.com/libnxz/power-gzip for tests or more
 305        use cases.
 306