Versal Secure Register Access with IOCTL - 2023.1 English

Versal Adaptive SoC System Software Developers Guide (UG1304)

Document ID
Release Date
2023.1 English

For most secure usecases, enforces XPPU and XMPU protection scheme allows only a set of "firmware masters" to access system resources directly. Protections are enforced in the hardware by configuring the XPPUs/XMPUs appropriately. If a non-firmware master requires an access to such protected address space, then it should request PLM to perform the access on behalf of it. A direct access from any non-firmware master to this protected address space will be blocked by hardware. Such non-firmware masters can use EEMI IOCTL APIs (IOCTL_READ_REG and IOCTL_MASK_WRITE_REG) to perform desired accesses which ensures that only firmware is directly accessing these resources and access is kept "secure". To use this feature, define an access policy for one or more apertures per resource through SET_NODE_ACCESS command in the PMC data CDO.

To read the secure/protected registers via IOCTL (for example, SYSMON registers), set the Node Access, add this as part of PMC CDO:

This command allows you to define address apertures accessible using EEMI IOCTL command. This unit describes one or more apertures associated with a node and defines different “access permissions” for each such aperture. This information is used by the firmware to build a "Node Access Table" which is used to evaluate client read/write access requests. A "Node Access Table" will contain several entries, where each entry will contain:

  • Node ID
  • Base Address
  • Total Size
  • List of:
    • <offset1, size1, access-permission1>,
    • <offset2, size2, access-permission2>,
Table 1.
Command: Set Node Access
Reserved[31:24] Length[23:16] XILPM = 2 CMD_PM_SET_NODE_ACCESS
NodeID #tqj1678210907764/li_prn_tnt_swb
size1[31:24]2 reserved[23:20] offset1[19:0]
reserved[31:4] access1[3:0]
size2[31:24] #tqj1678210907764/li_ktb_znt_swb reserved[23:20] offset2[19:0]
reserved[31:4] access2[3:0]
  • RNodeID can be of two types:
    • Device ID: These are PLM aware devices and have unique node IDs - defined in xpm_nodeid.h.
    • RegNode ID: These are non-PLM aware nodes and Node IDs must be created for these. Each SET_NODE_ACCESS is accompanied by a PM_ADD_NODE command for adding the given RegNode to PM database.
  • Size is 1-based and not 0-based. (i.e. Min size: 1)
    • Offset[19:0]: Defines permitted aperture's start address as offset from the base address of the node
    • Size[31:24] (in 32-bit words - MAX 255 words): defines size of the permitted aperture (chunk of address space starting from offset)
    • Access[0:3]: defines access permission for masters issuing the IOCTL command
  • If access is set to 5, 6, 7 or 8, the node must be assigned to a subsystem using PM_ADD_REQ command. Mere presence of the requirement for call subsystem is enough, no need for device policy checking. In that case, even though add requirement is used, the XPPU / FPD_XMPU setting still only allow access by firmware.

0x18224055 is the NodeID of PMC_SYSMON resource (taken from xpm_nodeid.h in PLM sources).

# Add default subsystem
# subsystem_default
pm_add_subsystem 0x1c000000
# Define node access permissions for PMC SYSMON Block Chunks
# Allow Sysmon access for any sec/non-secure masters for following ranges:
# 0xf1270000 - 0xf12703fb (0xff: 255 32-bit words)
# 0xf12703fc - 0xf12707f7 (0xff: 255 32-bit words)
# 0xf12707f8 - 0xf1270bf3 (0xff: 255 32-bit words)
# 0xf1270bf4 - 0xf1270fef (0xff: 255 32-bit words)
# 0xf1270ff0 - 0xf12713eb (0xff: 255 32-bit words)
# 0xf12713ec - 0xf12717e7 (0xff: 255 32-bit words)
# 0xf12717e8 - 0xf1271be3 (0xff: 255 32-bit words)
# 0xf1271be4 - 0xf1271fdf (0xff: 255 32-bit words)
# 0xf1271fe0 - 0xf12723db (0xff: 255 32-bit words)
# 0xf12723dc - 0xf12727d7 (0xff: 255 32-bit words)
# 0xf12727d8 - 0xf1272bd3 (0xff: 255 32-bit words)
# 0xf1272bd4 - 0xf1272fcf (0xff: 255 32-bit words)
# 0xf1272fd0 - 0xf12733cb (0xff: 255 32-bit words)
# 0xf12733cc - 0xf12737c7 (0xff: 255 32-bit words)
# 0xf12737c8 - 0xf1273bc3 (0xff: 255 32-bit words)
# 0xf1273bc4 - 0xf1273fbf (0xff: 255 32-bit words)
# 0xf1273fc0 - 0xf1274003 (0x11: 17 32-bit words)
pm_set_node_access 0x18224055 0xff000000 0x2 0xff0003fc 0x2 0xff0007f8 0x2 0xff000bf4 0x2 0xff000ff0 0x2 0xff0013ec 0x2 0xff0017e8 0x2 0xff001be4 0x2 0xff001fe0 0x2 0xff0023dc 0x2 0xff0027d8 0x2 0xff002bd4 0x2 0xff002fd0 0x2 0xff0033cc 0x2 0xff0037c8 0x2 0xff003bc4 0x2 0x11003fc0 0x2

An example to read SYSMON registers from Linux OS:

root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ echo pm_ioctl 0x18224055 0x1c 0x0 > /sys/kernel/debug/zynqmp-firmware/pm
root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ cat /sys/kernel/debug/zynqmp-firmware/pm
root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ echo pm_ioctl 0x18224055 0x1c 0x4 > /sys/kernel/debug/zynqmp-firmware/pm
root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ cat /sys/kernel/debug/zynqmp-firmware/pm
root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ echo pm_ioctl 0x18224055 0x1c 0x1fc > /sys/kernel/debug/zynqmp-firmware/pm
root@xilinx-vc-p-a2197-00-reva-x-prc-01-reva-2021_2:~$ cat /sys/kernel/debug/zynqmp-firmware/pm