Skip to content

Commit

Permalink
Document stack high water mark.
Browse files Browse the repository at this point in the history
Make it explicitly 16-byte aligned and point out the unaligned write spanning mshwmb corner case, which we do not require hardware to handle.

Fixes #15.
  • Loading branch information
ronorton committed Apr 4, 2024
1 parent 1e24f42 commit eda7e45
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 4 deletions.
2 changes: 2 additions & 0 deletions archdoc/chap-changes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ \chapter{Version history}
even if none were ever explicitly constructed.
\end{description}
\end{description}
\item[\ghissue{15}, \ghpr{49}] Document stack high water mark.
Make it explicitly 16-byte aligned and point out the unaligned write spanning \mshwmb{} corner case, which we do not require hardware to handle.
\end{description}
23 changes: 23 additions & 0 deletions archdoc/chap-cheri-riscv.tex
Original file line number Diff line number Diff line change
Expand Up @@ -712,3 +712,26 @@ \section{Instruction compression}
The \cherimcuisa{} introduces changes to mappings between certain compressed and uncompressed instructions, but no changes to the encodings of compressed instructions themselves.
This translates to minimum logic modifications when adding \cherimcuisa{} support to an existing RISC-V CPU.
However, experiments in \cref{chap:c-changes} show that further code size reduction can be achieved by introducing changes in the encoding themselves, to accommodate RV32E and CHERI instructions.

\section{Stack high water mark}
\label{sec:shwm}

The stack high water mark is a simple mechanism in \cherimcu{} to track stack use so that the RTOS switcher implementation can minimise the amount of stack zeroing during compartment calls.
The mechanism uses two new integer CSRs: the stack high water mark, \mshwm{} (\asm{0xBC1}), and the stack high water mark base, \mshwmb{} (\asm{0xBC2}).
These may be read and written using the \asm{CSRRW} instruction only if \PCC{} has \cappermASR{}, otherwise an attempt to do so will result in a Reserved Instruction exception.
The four least significant bits of both registers are hardwired to zeros, making them 16-byte aligned.
Any write with these bits set is legalised by rounding down.

On every memory write the address of the write (the lowest byte written) is compared to \mshwm{} and \mshwmb{}.
If the address is greater than or equal to \mshwmb{} and less than \mshwm{} then \mshwm{} is updated with the address of the write (rounded down to 16-byte alignment).
Thus, if \mshwmb{} is set to the stack base (the lowest stack address) and \mshwm{} is initialised to the top of the stack, then \mshwm{} will track the lowest stack address written during execution.
Since stacks grow downwards this indicates the maximum stack usage.
The RTOS uses this to optimise stack zeroing by maintaining an invariant that the stack between \mshwmb{} and \mshwm{} for each thread is always zeroed.
The stack high water mark CSRs are saved and restored during context switches along with other thread state.

Note that only the address of the store is accounted for, not the width.
This means that it is possible for an unaligned store with an address below \mshwmb{} to write bytes above \mshwmb{} without updating \mshwm{}.
For example, a 4-byte store to \mshwmb{}$ - 1$ would write the bytes at \mshwmb{}$\dots{}$\mshwmb$+ 2$ but leave \mshwm{} unchanged, potentially breaking the RTOS's invariant.
In practice this is not a problem as the RTOS will never issue a capability to untrusted code that crosses the stack base and would therefore premit such a write.%
\footnote{In fact, no such capabilities should exist after the loader has run and initialised the thread data structures.}
Given this, we choose not to unnecessarily complicate the hardware by requiring it to handle this corner case.
2 changes: 2 additions & 0 deletions archdoc/preamble.tex
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@
\newcommand{\mccsr}{\texttt{mccsr}}
\newcommand{\sccsr}{\texttt{sccsr}}
\newcommand{\uccsr}{\texttt{uccsr}}
\newcommand{\mshwm}{\texttt{mshwm}}
\newcommand{\mshwmb}{\texttt{mshwmb}}
% RISC-V existing registers
\newcommand{\xtval}{\texttt{{\it x}tval}}
\newcommand{\xtvec}{\texttt{{\it x}tvec}}
Expand Down
6 changes: 4 additions & 2 deletions src/cheri_addr_checks.sail
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,11 @@ function ext_check_phys_mem_read (access_type, paddr, size, aquire, release, res

function ext_check_phys_mem_write(write_kind, paddr, size, data, metadata) = {
if ((paddr >=_u MSHWMB) & (paddr <_u MSHWM)) then {
/* align down MSHWM to 16 bytes */
paddr16 = legalize_mshwm(paddr);
if get_config_print_reg()
then print_reg("MSHWM <- " ^ BitStr(paddr));
MSHWM = paddr;
then print_reg("MSHWM <- " ^ BitStr(paddr16));
MSHWM = paddr16;
};
Ext_PhysAddr_OK()
}
Expand Down
12 changes: 10 additions & 2 deletions src/cheri_sys_regs.sail
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ function legalize_ccsr(c : ccsr, v : xlenbits) -> ccsr = {
c
}

/*!
* Legalize stack high water mark by rounding
* down to 16-byte aligned value.
*/
function legalize_mshwm(v : xlenbits) -> xlenbits = {
[v with 3..0=0x0]
}

// XXX these are currently disabled due to sail bug when compiling C
//mapping clause csr_name_map = 0x8c0 <-> "uccsr"
//mapping clause csr_name_map = 0x9c0 <-> "sccsr"
Expand All @@ -107,8 +115,8 @@ function clause ext_write_CSR (0x8C0, value) = { uccsr = legalize_ccsr(uccsr, va
function clause ext_write_CSR (0x9C0, value) = { sccsr = legalize_ccsr(sccsr, value); Some(sccsr.bits()) }
function clause ext_write_CSR (0xBC0, value) = { mccsr = legalize_ccsr(mccsr, value); Some(mccsr.bits()) }

function clause ext_write_CSR (0xBC1, value) = { MSHWM = value; Some(value) }
function clause ext_write_CSR (0xBC2, value) = { MSHWMB = value; Some(value) }
function clause ext_write_CSR (0xBC1, value) = { MSHWM = legalize_mshwm(value); Some(MSHWM) }
function clause ext_write_CSR (0xBC2, value) = { MSHWMB = legalize_mshwm(value); Some(MSHWMB) }

function clause ext_is_CSR_defined (0x8C0, p) = haveUsrMode() // uccsr
function clause ext_is_CSR_defined (0x9C0, p) = haveSupMode() & (p == Machine | p == Supervisor) // sccsr
Expand Down

0 comments on commit eda7e45

Please sign in to comment.