Versal Secure Libraries Client-side Interface

The purpose of the page is to provide information to the developers regarding the usage of secure libraries using client-side interface running on A72/R5/PL Microblaze

Table of Contents

Communication Overview

The client-side libraries use mailbox library to send the command and receive response from PLM. The user should enable the mailbox library, when any of the client-side secure libraries are used.  The mailbox internally uses IPI driver to send the command to the PLM over IPI channel. The IPI communication channel is one-to-one communication between entities at both sides of the IPI channel. The user should select right IPI channel number as per the hardware design while configuring the mailbox. The below diagram shows the communication path from client-side API to server-side API. The client-side API sends request to the server-side API to perform the operation over cryptographic hardware.

Figure 1: Mailbox Communication mechanism

Note that if the same library is accessed from different places/processors, it’s the user application responsibility to handle the situation occurring due to multiple access to same resource. It is always recommended to set the ownership of one library to single application/processor and let others application/processor send request to the owner of the library to exercise the API. It’s highly recommended to use XPPU setting to restrict access to the IPI buffers and crypto hardware blocks to required modules only.

To get secure libraries to work, the data shared between the client-side APIs and the server-side APIs should be placed in memory that is accessible to both user application running on A72/R5/PL and PLM running on PMC. The IPI channel just provides 32 bytes and if anyone want to share beyond this, that should be passed through pointer and its responsibility of the user and individual client APIs to provide the data in shared memory that PMC can access. If there is need to send more than 32-byte data over IPI channel, the client-side library uses shared memory assigned to mailbox library by the user. It is user’s responsibility to configure proper shared memory for mailbox which both the client-side interface and PMC can access. When the user directly provides large data in form of pointer like data to be encrypted/decrypted/hashed etc, the user should make sure data is in the memory region that is accessible to PLM running on PMC. Table below provides the shared memory requirement of each client-side library for mailbox (IPI) communication.


Mailbox shared memory requirement


32 bytes


140 bytes


0 bytes

Table 1: Mailbox shared memory requirement for each library

If the application plan to use more than one client-side library, the mailbox can be shared, and user can allocate maximum shared memory required among those libraries.

PLM Customization

The PLM has only limited 384KB code memory, so it is impossible to include all features in one image. To manage the memory size, the PLMI library provides option for user to enable/disable optional features from PLM. This section provides details about how to customize it in each development flow. Following table gives details of available customization options and default value.

Option name


Default value


Enables (if enabled in hardware design too) or disables debug prints from UART (log to memory done irrespectively)



Selects the debug logs level



Selects between release and debug modes (PLM errors lead to SRST for former and system hang for latter)



Enables or disables boot time measurement



Enables (if enabled in hardware design too) or disables QSPI boot mode



Enables (if enabled in hardware design too) or disables SD boot mode



Enables (if enabled in hardware design too) or disables OSPI boot mode



Enables (if enabled in hardware design too) or disables SEM feature



Enables or disables secure features



Enables (if enabled in hardware design too) or disables USB boot mode



Enables or disables NVM handlers



Enables or disables PUF handlers



Enables or disables STL


Table 2: XilPlmi customization options

Vitis Flow

Following is the step-by-step guide for customizing PLM using Vitis flow.

  1. Click on plm.prj, it opens application project setting window. Click on “Navigate to BSP Settings” button top open board support package configuration window.

  2. Click on “Modify BSP Settings…”, button to customize BSP used for building the PLM.

  3. Click on “Modify BSP Settings…”, button to customize BSP used for building the PLM.

  4. Click on “xilplmi” as shown below. It shows list of options available for customization. Make sure you have enabled the server-side handler of the library that you plan to use in client mode. Also make sure to disable all features that are not required so that PLM fits in available memory.

  5. Click on value in “Value” column, which shows drop down box for making required selection.

  6. Click on OK and come out. Now build the PLM.


The below snippet shows steps involved in initially building the PLM with default configuration, then changing the debug level to debug info and regenerate BSP and rebuilding PLM, and then finally changing the debug level back to general (which is default), enabling the NVM library and regenerate BSP and rebuilding PLM. Refer above table for the different configuration options.

xsct% app create -name plm -template {versal PLM} -proc psv_pmc_0 -hw {vck190.xsa} -os standalone xsct% app build -name plm xsct% bsp config plm_dbg_lvl "info" xsct% platform clean xsct% platform generate xsct% app build -name plm xsct% bsp config plm_dbg_lvl "general" xsct% bsp config plm_nvm_en "true" xsct% platform clean xsct% platform generate xsct% app build -name plm

PetaLinux Flow

Below example shows how to enable NVM server-side interface in the PLM library (which is disabled by default). 

  1. Create a bbappend file for PLM and add below content

vim <plnx-proj-root>/project-spec/meta-user/recipes-bsp/embeddedsw/plm-firmware_%.bbappend

2. Update the configuration by adding the entries to bbappend file

#Add BSP flags for PLM. Here USB boot mode is enabled and debug level changed to level0 (minimal) #Alternatively, each of these two parameters can be configured separately YAML_BSP_CONFIG += "plm_usb_en plm_dbg_lvl plm_nvm_en" YAML_BSP_CONFIG[plm_dbg_lvl] = "set,level0" YAML_BSP_CONFIG[plm_nvm_en] = "set,true"

3. Remove the <plnx-proj-root>/components/plnx_workspace and clean you project workspace before rebuilding PLM component 

$ petalinux-build -x mrproper $ rm -rf <plnx-proj-root>/components/plnx_workspace $ petalinux-build

Writing an Application Using the Client-side APIs

Following is the procedure to setup and use the client-side library.

  1. Configure Mailbox

    1. Find the IPI channel to be used from hardware design.

    2. Find the canonical IPI channel number assigned to IPI channel found in step 1. Follow following procedure to find the canonical number to the physical IPI channel number.

      1. Open xparameters.h file of application BSP file.

      2. Search XPAR_XIPIPSU_NUM_INSTANCES macro. It tells number of IPI channels defined for target controller that application is going to run on. Value more than 1 indicates that hardware design defined IPI channel for target controller. Below this macro, user can find macros associated with IPI channels defined based on the hardware design.

      3. Under parameter definition of the physical IPI channel you will find the canonical Device ID associated with the channel. For example, the code snippet on next page device ID set for IPI physical channel 3 is 0U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_DEVICE_ID  0U

      4. Use above macro and find the canonical macro to be used while initializing the mailbox. For example, in the below code snippet, line 18 defines the short canonical macro (XPAR_XIPIPSU_0_DEVICE_ID) to be used in the code.


#define  XPAR_XIPIPSU_NUM_INSTANCES  2U   /* Parameter definitions for peripheral versal_cips_0_pspmc_0_psv_ipi_3 */ #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_DEVICE_ID  0U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_S_AXI_BASEADDR  0xFF360000U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_BIT_MASK  0x00000020U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_BUFFER_INDEX  0x5U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_INT_ID  65U   /* Parameter definitions for peripheral versal_cips_0_pspmc_0_psv_ipi_4 */ #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_DEVICE_ID  1U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_S_AXI_BASEADDR  0xFF370000U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_BIT_MASK  0x00000040U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_BUFFER_INDEX  0x6U #define  XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_INT_ID  66U   /* Canonical definitions for peripheral versal_cips_0_pspmc_0_psv_ipi_3 */ #define  XPAR_XIPIPSU_0_DEVICE_ID    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_DEVICE_ID #define  XPAR_XIPIPSU_0_BASE_ADDRESS    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_S_AXI_BASEADDR #define  XPAR_XIPIPSU_0_BIT_MASK    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_BIT_MASK #define  XPAR_XIPIPSU_0_BUFFER_INDEX    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_BUFFER_INDEX #define  XPAR_XIPIPSU_0_INT_ID    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_3_INT_ID   /* Canonical definitions for peripheral versal_cips_0_pspmc_0_psv_ipi_4 */ #define  XPAR_XIPIPSU_1_DEVICE_ID    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_DEVICE_ID #define  XPAR_XIPIPSU_1_BASE_ADDRESS    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_S_AXI_BASEADDR #define  XPAR_XIPIPSU_1_BIT_MASK    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_BIT_MASK #define  XPAR_XIPIPSU_1_BUFFER_INDEX    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_BUFFER_INDEX #define  XPAR_XIPIPSU_1_INT_ID    XPAR_VERSAL_CIPS_0_PSPMC_0_PSV_IPI_4_INT_ID

c. Initialize mailbox using above canonical IPI macro and shared memory that library can use for IPI communication. Make sure your hardware design allows access to the shared memory to both PMC and the processor on which application is running. Make sure enough shared memory is reserved for IPI communication as per Table 1.

2. Initialize and configure the client-side interface library using above mailbox instance.

3. Use the library.

4. Release the shared memory allocated for mailbox.

Related Links

© Copyright 2019 - 2022 Xilinx Inc. Privacy Policy