riscv-non-isa/riscv-iommu

Clarification related to the reference model EXE/PRIV enforcements

Closed this issue · 8 comments

In the IOMMU specification,
3.2. Fault/Event-Queue (FQ)
If PV is 0, then PID and PRIV are 0.

This sentence can be interpreted as it implies the logic of PCIe PASID TLP prefix. When this TLP doesn't exist, fields inside of it, e.x., Privileged Mode Requested field shouldn't exist.

6.20 PASID TLP Prefix
image

However, the reference model enforces this implied PCIe logic inside of IOMMU implementation:

    // If a Translation Request has a PASID, the Untranslated Address Field is an address
    // within the process address space indicated by the PASID field.
    // If a Translation Request has a PASID with either the Privileged Mode Requested
    // or Execute Requested bit Set, these may be used in constructing the Translation
    // Completion Data Entry.  The PASID Extended Capability indicates whether a Function
    // supports and is enabled to send and receive TLPs with the PASID.
    is_exec = ( (is_read && req->exec_req &&
                (req->tr.at == ADDR_TYPE_UNTRANSLATED || req->pid_valid)) ) ? 1 : 0;
    priv = ( req->pid_valid && req->priv_req ) ? S_MODE : U_MODE;

One uses the reference model verifying the hardware implementation may falsely enforces this logic inside of the RISC-V IOMMU implementation.
Should this be clarified?

Could you please explain more about the clarification sought?

For example, adding words stating the following is an implication in the PCIe scenario:

If PV is 0, then PID and PRIV are 0.

And adds special condition in the reference model around the logic indicating it is only used for non-PCIe address translation.

if (req->tr.at != ADDR_TYPE_PCIE_ATS_TRANSLATION_REQUEST)

Emm, I couldn't see such enforcement in other IOMMU implementations:

    // If a Translation Request has a PASID, the Untranslated Address Field is an address
    // within the process address space indicated by the PASID field.
    // If a Translation Request has a PASID with either the Privileged Mode Requested
    // or Execute Requested bit Set, these may be used in constructing the Translation
    // Completion Data Entry.  The PASID Extended Capability indicates whether a Function
    // supports and is enabled to send and receive TLPs with the PASID.
    is_exec = ( (is_read && req->exec_req &&
                (req->tr.at == ADDR_TYPE_UNTRANSLATED || req->pid_valid)) ) ? 1 : 0;
    priv = ( req->pid_valid && req->priv_req ) ? S_MODE : U_MODE;

This looks a kind of DMA master side business rather than IOMMU internal.

For example, adding words stating the following is an implication in the PCIe scenario:
If PV is 0, then PID and PRIV are 0.

When process_id (PID) is not valid (PV) it is 0. This is not PCIe related. The IOMMU requires the validity to be indicated at input to the IOMMU (section 1.3) and requires PRIV to be 0 when process_id is not valid. When process_id is not valid only the G-stage page tables apply. In G-stage PTEs, when checking the U bit, the current privilege mode is always taken to be U-mode . This follows from RISC-V Priv. architecture (section 17.5.1 of Priv. spec) and is unrelated to PCIe.

And adds special condition in the reference model around the logic indicating it is only used for non-PCIe address translation.

The quoted code indicates that the transaction is not a PCIe ATS translation request but that does not imply it is only used for non-PCIE address translation. There are 10 types of transactions in the architecture - see TTYP encodings - of these TTYP=8 is specifically designating PCIe ATS Translation Request but the other 9 may be used by any other protocol - including PCIe.

For non-PCIe ATS translation requests, for example, a generic DMA master with ARM SMMU TBU remapping configured should be able to control PID and PRIV when PV = 0. It can choose to wire PID/PRIV to 0 when PV is 0.

The IOMMU requires the validity to be indicated at input to the IOMMU (section 1.3) and requires PRIV to be 0 when process_id is not valid. When process_id is not valid only the G-stage page tables apply. In G-stage PTEs, when checking the U bit, the current privilege mode is always taken to be U-mode .

"For requests without a process_id the privilege mode must be User." by IOMMU (section 1.3).

This follows from RISC-V Priv. architecture (section 17.5.1 of Priv. spec) and is unrelated to PCIe.

Unlike PCIe which is constrained by the PASID TLP Prefix, I wonder if there is any usage model that such DMA master can choose to let PID/PRIV as is when PV is 0, or wire PID to a default value other than 0, and PRIV to 1 when PV is 0?

I wonder if there is any usage model that such DMA master can choose to let PID/PRIV as is when PV is 0, or wire PID to a default value other than 0, and PRIV to 1 when PV is 0?

Use of PID (process ID), PV (process ID valid) and PRIV (privileged request) does not necessarily need PCIe/PASID. If a DMA master wants to drive a process ID (PID) input then it must indicate that the PID is valid by setting PV (process ID valid) to 1. PRIV can be 1 or 0 only when PID is valid. When PID is not valid PRIV must be 0. Only when process based isolation is used i.e. process ID is valid - there is a concept of user vs. supervisor - through the use of U bit in the PTEs since such page tables are associated with processes identified by process ID (PID).

IMO, PRIV should be driven by the DMA masters, given the reasons below:

  1. Both PV/PID/PRIV are output signals that need DMA master's driving;
  2. There must be driving source of these signals in the DMA masters' design;
  3. In case of PV=0, DMA master should also encounter an embarrassing situation that lacks the source of PID/PRIV.

Thus the above logic is implied in the DMA masters design, and might not be a part of IOMMU.
As such, the reference model may remove the following logic which is detected to report model comparison fault with some hardware implementation when a test bench contains only IOMMU IP w/o a DMA master and verified by the reference model:

    // If a Translation Request has a PASID, the Untranslated Address Field is an address
    // within the process address space indicated by the PASID field.
    // If a Translation Request has a PASID with either the Privileged Mode Requested
    // or Execute Requested bit Set, these may be used in constructing the Translation
    // Completion Data Entry.  The PASID Extended Capability indicates whether a Function
    // supports and is enabled to send and receive TLPs with the PASID.
    is_exec = ( (is_read && req->exec_req &&
                (req->tr.at == ADDR_TYPE_UNTRANSLATED || req->pid_valid)) ) ? 1 : 0;
    priv = ( req->pid_valid && req->priv_req ) ? S_MODE : U_MODE;

At least, this shouldn't be forced in IOMMU, but should be implementation dependent.

This can be extract out into a function that the implementation can provide. Updated in PR #306

Thanks for the clarification.