虛擬加速器交換板 (VAS) 使用者空間 API

介紹

Power9 處理器引入了虛擬加速器交換板 (VAS),允許使用者空間和核心與協處理器(硬體加速器)進行通訊,該協處理器被稱為巢狀加速器 (NX)。 NX 單元由一個或多個硬體引擎或協處理器型別組成,例如 842 壓縮、GZIP 壓縮和加密。 在 Power9 上,使用者空間應用程式只能訪問 GZIP 壓縮引擎,該引擎支援硬體中的 ZLIB 和 GZIP 壓縮演算法。

為了與 NX 通訊,核心必須建立一個通道或視窗,然後可以直接提交請求,而無需核心參與。 傳送到 GZIP 引擎的請求必須格式化為協處理器請求塊 (CRB),並且必須使用 COPY/PASTE 指令將這些 CRB 貼上到與引擎請求佇列關聯的硬體地址。

GZIP 引擎提供兩個優先順序級別的請求:普通和高。 目前,使用者空間僅支援普通請求。

本文件介紹了用於與核心互動以設定通道/視窗的使用者空間 API,該通道/視窗可用於直接將壓縮請求傳送到 NX 加速器。

概述

透過 VAS/NX 裝置驅動程式實現的 /dev/crypto/nx-gzip 裝置節點提供對 GZIP 引擎的應用程式訪問。 應用程式必須開啟 /dev/crypto/nx-gzip 裝置才能獲取檔案描述符 (fd)。 然後應使用此 fd 發出 VAS_TX_WIN_OPEN ioctl 以建立與引擎的連線。 這意味著在此程序的 GZIP 引擎上打開了傳送視窗。 建立連線後,應用程式應使用 mmap() 系統呼叫將引擎請求佇列的硬體地址對映到應用程式的虛擬地址空間中。

然後,應用程式可以透過使用複製/貼上指令並將 CRB 貼上到 mmap() 返回的虛擬地址(又名 paste_address)來向引擎提交一個或多個請求。 使用者空間可以透過關閉檔案描述符 (close(fd)) 或在程序退出時關閉已建立的連線或傳送視窗。

請注意,應用程式可以使用同一視窗傳送多個請求,或者可以建立多個視窗,但每個檔案描述符一個視窗。

以下部分提供了有關各個步驟的更多詳細資訊和參考。

NX-GZIP 裝置節點

系統中有且只有一個 /dev/crypto/nx-gzip 節點,它提供對系統中所有 GZIP 引擎的訪問。 /dev/crypto/nx-gzip 上的唯一有效操作是

  • open() 開啟裝置以進行讀取和寫入。

  • 發出 VAS_TX_WIN_OPEN ioctl

  • mmap() 將引擎的請求佇列對映到應用程式的虛擬地址空間中(即,獲取協處理器引擎的 paste_address)。

  • 關閉裝置節點。

此裝置節點上的其他檔案操作未定義。

請注意,複製和貼上操作直接進入硬體,而不會透過此裝置。 有關更多詳細資訊,請參閱 COPY/PASTE 文件。

雖然一個系統可能具有 NX 協處理器引擎的多個例項(通常,每個 P9 晶片一個),但在系統中只有一個 /dev/crypto/nx-gzip 裝置節點。 開啟 nx-gzip 裝置節點時,核心會在 NX 加速器的合適例項上打開發送視窗。 它找到使用者程序正在執行的 CPU,並確定此 CPU 所屬晶片上的相應 NX 例項。

應用程式可以使用 VAS_TX_WIN_OPEN ioctl 中的 vas_id 欄位選擇 NX 協處理器的特定例項,如下所述。

這裡有一個使用者空間庫 libnxz 可用,但仍在開發中

使用 inflate/deflate 呼叫的應用程式可以連結 libnxz 而不是 libz,並在沒有任何修改的情況下使用 NX GZIP 壓縮。

開啟 /dev/crypto/nx-gzip

應該開啟 nx-gzip 裝置以進行讀取和寫入。 開啟裝置不需要特殊許可權。 每個視窗對應一個檔案描述符。 因此,如果使用者空間程序需要多個視窗,則必須發出多個開啟呼叫。

有關其他詳細資訊(如返回值、錯誤程式碼和限制),請參閱 open(2) 系統呼叫手冊頁。

VAS_TX_WIN_OPEN ioctl

應用程式應使用 VAS_TX_WIN_OPEN ioctl 如下所示,以建立與 NX 協處理器引擎的連線

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];
};
版本

版本欄位當前必須設定為 1。

vas_id

如果傳遞 '-1',核心將盡最大努力為程序分配 NX 的最佳例項。 要選擇特定的 VAS 例項,請參閱下面的“發現可用的 VAS 引擎”部分。

flags、reserved1 和 reserved2[6] 欄位用於將來的擴充套件,必須設定為 0。

VAS_TX_WIN_OPEN ioctl 的屬性 attr 定義如下

#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);

VAS_TX_WIN_OPEN ioctl 成功時返回 0。 如果出錯,它返回 -1 並設定 errno 變數以指示錯誤。

錯誤情況

EINVAL

fd 不引用有效的 VAS 裝置。

EINVAL

無效的 vas ID

EINVAL

版本未設定為正確的值

EEXIST

已為給定的 fd 開啟視窗

ENOMEM

沒有可用的記憶體來分配視窗

ENOSPC

系統開啟的活動視窗(連線)太多

EINVAL

保留欄位未設定為 0。

有關更多詳細資訊、錯誤程式碼和限制,請參閱 ioctl(2) 手冊頁。

mmap() NX-GZIP 裝置

NX-GZIP 裝置 fd 的 mmap() 系統呼叫返回一個 paste_address,應用程式可以使用該地址將其 CRB 複製/貼上到硬體引擎。

paste_addr = mmap(addr, size, prot, flags, fd, offset);

NX-GZIP 裝置 fd 的 mmap 的唯一限制是

  • 大小應為 PAGE_SIZE

  • offset 引數應為 0ULL

有關其他詳細資訊/限制,請參閱 mmap(2) 手冊頁。 除了 mmap(2) 手冊頁上列出的錯誤情況之外,還可能因以下錯誤程式碼之一而失敗

EINVAL

fd 未與開啟的視窗關聯(即,mmap() 沒有遵循對 VAS_TX_WIN_OPEN ioctl 的成功呼叫)。

EINVAL

offset 欄位不是 0ULL。

發現可用的 VAS 引擎

系統中每個可用的 VAS 例項都將具有一個裝置樹節點,例如 /proc/device-tree/vas@* 或 /proc/device-tree/xscom@*/vas@*。 確定晶片或 VAS 例項,並使用此節點中相應的 ibm,vas-id 屬性值來選擇特定的 VAS 例項。

複製/貼上操作

應用程式應使用複製和貼上指令將 CRB 傳送到 NX。 有關複製/貼上指令,請參閱 PowerISA 中的第 4.4 節:https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0

CRB 規範和使用 NX

應用程式應使用協處理器請求塊 (CRB) 格式化對協處理器的請求。 有關 CRB 的格式以及從使用者空間使用 NX(例如傳送請求和檢查請求狀態)的資訊,請參閱 NX-GZIP 使用者手冊。

NX 故障處理

應用程式將請求傳送到 NX,並透過輪詢協處理器狀態塊 (CSB) 標誌來等待狀態。 NX 在處理每個請求後更新 CSB 中的狀態。 有關 CSB 的格式和狀態標誌,請參閱 NX-GZIP 使用者手冊。

如果 NX 在 CSB 地址或任何請求緩衝區上遇到轉換錯誤(稱為 NX 頁面錯誤),則會在 CPU 上引發中斷以處理該故障。 如果應用程式傳遞了無效地址或請求緩衝區不在記憶體中,則可能會發生頁面錯誤。 作業系統透過使用以下資料更新 CSB 來處理故障

csb.flags = CSB_V;
csb.cc = CSB_CC_FAULT_ADDRESS;
csb.ce = CSB_CE_TERMINATION;
csb.address = fault_address;

當應用程式收到轉換錯誤時,它可以觸控或訪問具有錯誤地址的頁面,以便該頁面位於記憶體中。 然後,應用程式可以重新將此請求傳送到 NX。

如果由於 CSB 地址無效而導致作業系統無法更新 CSB,則會將 SEGV 訊號傳送到在發出原始請求的傳送視窗上開啟該視窗的程序。 此訊號返回以下 siginfo 結構

siginfo.si_signo = SIGSEGV;
siginfo.si_errno = EFAULT;
siginfo.si_code = SEGV_MAPERR;
siginfo.si_addr = CSB address;

在多執行緒應用程式的情況下,NX 傳送視窗可以在所有執行緒之間共享。 例如,子執行緒可以開啟一個傳送視窗,但其他執行緒可以使用此視窗將請求傳送到 NX。 即使在作業系統處理故障的情況下,只要 CSB 地址有效,這些請求也會成功。 如果 NX 請求包含無效的 CSB 地址,則會將訊號傳送到開啟該視窗的子執行緒。 但是,如果在沒有關閉視窗的情況下退出該執行緒,並且使用此視窗發出請求,則會將訊號傳送到執行緒組負責人 (tgid)。 是否忽略或處理這些訊號取決於應用程式。

NX-GZIP 使用者手冊:https://github.com/libnxz/power-gzip/blob/master/doc/power_nx_gzip_um.pdf

簡單示例

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
}

有關測試或更多用例,請參閱 https://github.com/libnxz/power-gzip