Skip to content

Commit

Permalink
Merge pull request #37 from tyshyu/main
Browse files Browse the repository at this point in the history
Update Chapter 2, 4 and 5
  • Loading branch information
paul-andes authored Jan 4, 2025
2 parents 8b40bab + d051338 commit 63a8a99
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 60 deletions.
61 changes: 29 additions & 32 deletions chapter2.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

This document refers to the term “secure monitor” as the software responsible for managing security-related tasks, including the programming of IOPMPs. The secure monitor is not restricted to operating on a single CPU or hart; instead, it has the flexibility to be distributed across multiple CPUs.

{set:cellbgcolor:#0000}
.Glossary and Acronyms
[cols="<1,<3",stripes=even]
|===
2+h|Glossary/ Acronyms{set:cellbgcolor:#D3D3D3}
h|Term h|Description
|{set:cellbgcolor:#FFFFFF}DC| don't care
|IMP|implementation-dependent
Expand Down Expand Up @@ -68,11 +67,11 @@ IOPMP entries exhibit partial prioritization. Entries with indices smaller than

NOTE: The specification incorporates both priority and non-priority entries due to considerations of security, latency, and area. Priority entries, which are locked, safeguard the most sensitive data, even in the event of secure software being compromised. However, implementing a large number of these priority entries results in higher latency and increased area usage. On the other hand, non-priority entries are treated equally and can be cached in smaller numbers. This approach reduces the amortized latency, power consumption, and area when the locality is sufficiently high. Thus, the mix of entry types in the specification allows for a balance between security and performance.

The entry with the highest priority that (1) matches any byte of the incoming transaction and (2) is associated with the RRID carried by the transaction determines whether the transaction is legal. If the matching entry is priority entry, the matching entry must match all bytes of a transaction, or the transaction is illegal with error type = "partial hit on a priority rule" (0x04), irrespective of its permission. If a priority entry is matched but doesn't grant a transaction permission to operate, the transaction is illegal with error type = "illegal read access" (0x01), "illegal write access" (0x02) or "illegal instruction fetch" (0x03), depending on its transaction type.
The entry with the highest priority that (1) matches any byte of the incoming transaction and (2) is associated with the RRID carried by the transaction determines whether the transaction is legal. If the matching entry is priority entry, the matching entry must match all bytes of a transaction, or the transaction is illegal with error type = "partial hit on a priority rule" (0x04), irrespective of its permission. An entry has own permission and permission from Memory Domain to grant a transaction permission. If a priority entry is matched but doesn't grant transaction permission to operate, the transaction is illegal with error type = "illegal read access" (0x01) for read access transaction, "illegal write access" (0x02) for write access transaction, or "illegal instruction fetch" (0x03) for instruction fetch transaction.

Let's consider a non-priority entry matching all bytes of a transaction. It is legal if the entry grants the transaction permission to operate. When multiple non-priority entries match all bytes of a transaction and one of them allows the transaction, the transaction is legal. If none of them allows, the transaction is illegal with error code = "not hit any rule" (0x05).
Let's consider a non-priority entry matching all bytes of a transaction. It is legal if the entry grants the transaction permission to operate. When multiple non-priority entries match all bytes of a transaction and one of them allows the transaction, the transaction is legal. If none of them allows, the transaction is illegal with error type = "illegal read access" (0x01) for read access transaction, "illegal write access" (0x02) for write access transaction, or "illegal instruction fetch" (0x03) for instruction fetch transaction.

Finally, if no such above entry exists, the transaction is illegal with error code = "not hit any rule" (0x05).
Finally, if no such above entry exists, the transaction is illegal with error type = "not hit any rule" (0x05).


[caption="Figure {counter:image}: ", reftext="Figure {image}"]
Expand All @@ -91,55 +90,58 @@ Upon detecting an illegal transaction, the IOPMP could initiate three of the fol

The interrupt enabling on an IOPMP violation can be configured globally via *ERR_CFG* register or optionally locally through the *ENTRY_CFG* register for each entry. The *ERR_CFG.ie* bit serves as the global interrupt enable configure bit. *HWCFG0.peis* is 1 if an implementation supports *sire*, *siwe*, or *sixe*. Every entry _i_ has three optional interrupt suppressing bits in register *ENTRY_CFG(_i_)*, *sire*, *siwe*, and *sixe* to suppress interrupt triggering due to illegal reads, illegal writes and illegal instruction fetches on the corresponding entry, respectively. Such local interrupt control mechanism can be beneficial in scenarios such as configuring guard regions for speculative access handling. The interrupt pending indication is equivalent to the error valid indication, both are flagged through the *ERR_INFO.v* bit. An IOPMP interrupt will be triggered when a transaction is illegal and the interrupt is not suppressed. An IOPMP triggers interrupt by global interrupt enable configure bit *ie* and suppressing bits (*sire*, *siwe*, or *sixe*) in entries if a transaction only violates permissions on entries and *peis* is 1. On the other hand, if a transaction doesn't only violate permissions on entries, an IOPMP triggers interrupt only by global interrupt enable configure bit *ie*. The permissions include permission bits in entries (*ENTRY_CFG(_i_).r/w/x*) and permission bits from SRCMD table (please refer <<#SECTION_3_2, SRCMD Table Formats>> for the details) to corresponding entries. The relation of interrupt control with interrupt suppression bits for an illegal transaction can be more precisely described as follows:

An entry indexed by _i_ has the highest priority and matches all bytes of the illegal transaction, and the illegal transaction is:
An entry indexed by _i_ has the highest priority and matches all bytes of the illegal transaction, and error type of the illegal transaction is:

* Read access transaction: +
* Illegal read access (0x01): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).sire*
* Write access transaction: +
* Illegal write access (0x02): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).siwe*
* Instruction fetch transaction: +
* Illegal instruction fetch (0x03): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).sixe*

For some cases with multiple matched non-priority entries, the more detailed relation is:

Entries indexed by _i_~0~, _i_~1~, …​, _i~N~_ match all bytes of the illegal transaction, and the illegal transaction is:
Entries indexed by _i_~0~, _i_~1~, …​, _i~N~_ match all bytes of the illegal transaction, and error type of the illegal transaction is:

* Read access transaction: +
* Illegal read access (0x01): +
*ERR_CFG.ie* && ( !*ENTRY_CFG(_i_~0~).sire* || !*ENTRY_CFG(_i_~1~).sire* || ... || !*ENTRY_CFG(_i~N~_).sire* )
* Write access transaction: +
* Illegal write access (0x02): +
*ERR_CFG.ie* && ( !*ENTRY_CFG(_i_~0~).siwe* || !*ENTRY_CFG(_i_~1~).siwe* || ... || !*ENTRY_CFG(_i~N~_).siwe* )
* Instruction fetch transaction: +
* Instruction fetch transaction (0x03): +
*ERR_CFG.ie* && ( !*ENTRY_CFG(_i_~0~).sixe* || !*ENTRY_CFG(_i_~1~).sixe* || ... || !*ENTRY_CFG(_i~N~_).sixe* )


Transactions that violates the IOPMP rule will by default yield a bus error. Additionally, the bus error response behavior on an IOPMP violation can be optionally configured globally via *ERR_CFG* register or locally through each *ENTRY_CFG* register. The IOPMP will signal the bus to the presence of a violation but will suppress the bus error if *ERR_CFG.rs* is implemented and set to 1 on a violation. User-defined suppression behavior allows, for example, a read response of 0x0. Likewise, the bus error response on an illegal write or instruction fetch.

In the same way, the bus error response behavior can be set up globally and individually for each IOPMP entry. *ERR_CFG.rs* globally suppresses returning a bus error on illegal access. When global suppression is disabled, individual per-entry suppression is possible using *sere*, *sewe*, and *sexe* for illegal read, illegal write, and illegal instruction fetch, respectively. *HWCFG0.pees* is 1 if an IOPMP implements *sere*, *sewe*, and *sexe*. An IOPMP will respond with a bus error when a transaction is illegal and the bus error is not suppressed. Bus error response behavior of an IOPMP is controlled by global interrupt enable configure bit *rs* and suppressing bits (*sere*, *sewe*, or *sexe*) in entries if a transaction only violates permissions on entries and *pees* is 1. On the other hand, if a transaction doesn't only violate permissions on entries, bus error response behavior of an IOPMP is controlled only by global interrupt enable configure bit *ie*. The permissions include permission bits in entries (*ENTRY_CFG(_i_).r/w/x*) and permission bits from SRCMD table (please refer <<#SECTION_3_2, SRCMD Table Formats>> for the details) to corresponding entries. The relation of bus error response suppression control with supression bits in entries for an illegal transaction can be more precisely described as follows:

An entry indexed by _i_ has the highest priority and matches all bytes of the illegal transaction, and the illegal transaction is:
An entry indexed by _i_ has the highest priority and matches all bytes of the illegal transaction, and error type of the illegal transaction is:

* Read access transaction: +
* Illegal read access (0x01): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).sere*
* Write access transaction: +
* Illegal write access (0x02): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).sewe*
* Instruction fetch transaction: +
* Illegal instruction fetch (0x03): +
*ERR_CFG.ie* && !*ENTRY_CFG(_i_).sexe*

For some cases with multiple matched non-priority entries, the more detailed relation is:

Entries indexed by _i_~0~, _i_~1~, …​, _i~N~_ match all bytes of the illegal transaction, and the illegal transaction is:
Entries indexed by _i_~0~, _i_~1~, …​, _i~N~_ match all bytes of the illegal transaction, and error type of the illegal transaction is:

* Read access transaction: +
* Illegal read access (0x01): +
!*ERR_CFG.rs* && ( !*ENTRY_CFG(_i_~0~).sere* || !*ENTRY_CFG(_i_~1~).sere* || ... || !*ENTRY_CFG(_i~N~_).sere* )
* Write access transaction: +
* Illegal write access (0x02): +
!*ERR_CFG.rs* && ( !*ENTRY_CFG(_i_~0~).sewe* || !*ENTRY_CFG(_i_~1~).sewe* || ... || !*ENTRY_CFG(_i~N~_).sewe* )
* Instruction fetch transaction: +
* Illegal instruction fetch (0x03): +
!*ERR_CFG.rs* && ( !*ENTRY_CFG(_i_~0~).sexe* || !*ENTRY_CFG(_i_~1~).sexe* || ... || !*ENTRY_CFG(_i~N~_).sexe* )

The error capture record maintains the specifics of the first illegal access detected, except if the following two conditions are held: (1) any interrupt-suppress bit regarding the access is set, and (2) no bus error is returned. New error capture only occurs when there is no currently pending error, namely *ERR_INFO.v* is ‘0’. If a pending error exists (*v* is ‘1’), the record will not be updated, even if a new illegal access is detected. In other words, *v* indicates whether the content of the capture record is valid and should be intentionally cleared in order to capture subsequent illegal accesses. One can write 1 to the bit to clear it. The error capture record is optional. If it is not implemented, *v* should be wired to zero. One can implement the error capture record but not *ERR_REQID.eid*. In this case, *ERR_REQID.eid* should be wired to 0xffff.
The error capture record maintains the specifics of the first illegal access detected, except if the following two conditions are held: (1) any interrupt-suppress bit regarding the access is set, and (2) no bus error is returned. New error capture only occurs when there is no currently pending error, namely *ERR_INFO.v* is ‘0’. If a pending error exists (*v* is ‘1’), the record will not be updated, even if a new illegal access is detected. In other words, *v* indicates whether the content of the capture record is valid and should be intentionally cleared in order to capture subsequent illegal accesses. One can write 1 to the bit to clear it. The error capture record is optional. If it is not implemented, *v* should be wired to zero. One can implement the error capture record but not *ERR_REQID.eid*. In this case, *eid* should be wired to 0xffff.

If a transaction violates IOPMP rules on multiple non-priority entries which don't suppress interrupt or bus error response, the *ERR_REQID.eid* should be one of the entries.

The following table shows (1) the error types, and (2) related control bits about interrupt triggering and bus error response if the IOPMP supports local control bits (*HWCFG0.peis* is 1 and/or *HWCFG0.pees* is 1):

.Error types and corresponding control bits
[cols="<1,<2,<5,<3"]
|===
3+h| Error type h| Control bits
Expand All @@ -148,21 +150,16 @@ The following table shows (1) the error types, and (2) related control bits abou
|0x02 2+| Illegal write access | Global and local
|0x03 2+| Illegal instruction fetch | Global and local
|0x04 2+| Partial hit on a priority rule | Global
.2+|0x05 .2+| Not hit any rule
| A transaction violates permissions on non-priority rules | Global and local
a| Other cases:

* No entry matches all bytes of a transaction
|0x05 | Not hit any rule
a|* No entry matches all bytes of a transaction
* Receives a write access transaction when *HWCFG0.no_w* is 1
* Receives an instruction fetch transaction when *HWCFG0.no_x* is 1
| Global
|0x06 2+| Unknown RRID | Global
|0x07 2+| Error due to stalled transactions.

Available if *ERR_CFG.stall_violation_en* is 1.
|0x07 2+| Error due to stalled transactions. Please refer <<#SECTION_4_2_1, Faulting stalled transactions>>.
| Global
|0x08 ~ 0x0B 2+| N/A, reserved for future | N/A
|0x0C ~ 0x0F 2+| User-defined error | Implementation-dependent
|0x08 ~ 0x0D 2+| N/A, reserved for future | N/A
|0x0E ~ 0x0F 2+| User-defined error | Implementation-dependent
|===

^1.^ Bit *ie* or *rs* in *ERR_CFG*. It depends on which reaction (i.e., interrupt or bus error response).
Expand Down
Loading

0 comments on commit 63a8a99

Please sign in to comment.