For most secure usecases, AMD 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 is blocked by
the 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.
There are two types of Reg nodes:
- User-defined
- Pre-defined nodes.
Pre-defined nodes are made available at https://embeddedsw/lib/sw_services/xilpm/src/versal_common/common/xpm_nodeid.h. Then, you can directly access it by the IOCTL commands to read or write the registers.
For the user-defined node, follow the below steps.
- Create node
ID
Introduce New Node ID class/Subclass/Type for RegNodes: CLASS: XPM_NODECLASS_REGNODE=0xC SUBCLASS: XPM_NODESUBCL_REGNODE_USERDEF=0x1 TYPE: XPM_NODETYPE_REGNODE_GENERIC=0x0 INDEX: Min: 0x0, Max: 0x1F (31)
- Use the add node command to add the node:
Command: PM_ADD_NODE Reserved [31:24] Length [23:16] XILPM=2 CMD_PM_ADD_NODE Node Id (Node ID includes class, subclass, type and node index) Base Address Power ID (Domain/Island RegNode belongs to) Provide the permission by using the set node access command.
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" contains several entries, where each entry contains:
- Node ID
- Base Address
- Total Size
- List of:
- <offset1, size1, access-permission1>,
- <offset2, size2, access-permission2>,
Command: Set Node Access | |||
---|---|---|---|
Reserved[31:24] | Length[23:16] | XILPM = 2 | CMD_PM_SET_NODE_ACCESS |
NodeID 1 | |||
size1[31:24]2 | reserved[23:20] | offset1[19:0] | |
reserved[31:4] | access1[3:0] | ||
size2[31:24] 2 | reserved[23:20] | offset2[19:0] | |
reserved[31:4] | access2[3:0] | ||
... | |||
... | |||
|
0x18224055 is the NodeID of PMC_SYSMON resource (taken from xpm_nodeid.h in PLM sources).
marker 0x64 "SUBSYSTEM_DEFINITION"
# 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
marker 0x65 "SUBSYSTEM_DEFINITION"
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