Date
1 - 20 of 59
proposal for stateen CSRs
John Hauser
Hello tech-privileged,
The proposal below has been discussed by some of the principle RISC-V
architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and
the RISC-V Advanced Interrupt Architecture, which are other extensions
being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged
Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the
potential to open covert channels between separate user threads, or
between separate guest OSes running under a hypervisor. The problem
occurs when an extension adds processor state---usually explicit
registers, but possibly other forms of state---that the main OS or
hypervisor is unaware of (and hence won't context-switch) but that
can be modified/written by one user thread or guest OS and perceived/
examined/read by another.
Consider, for example, that the N extension is someday ratified by
the RISC-V Association, and a hart implements both S mode and the
N extension, with misa.N hardwired = 1. The OS in use on this hart
might be oblivious to the N extension and hence might not test for the
extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that
case, most of these CSRs provide an obvious covert channel between
user threads. Although traditional practices might consider such a
communication channel harmless, the intense focus on security today
argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the
V registers of the vector extension would also be potential covert
channels, except for the existence of the FS and VS fields in the
sstatus register. An OS that is unaware of, say, the vector extension
and its V registers will unwittingly prevent access to those registers
by initializing unknown fields of sstatus to zeros, which in this case
will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as
a covert channel would be to add to sstatus an "NS" field for the
N extension, paralleling the V extension's VS field. However, this is
not considered a general solution to the problem due to the number of
potential future extensions that may add small amounts of state. Even
with a 64-bit sstatus (necessitating adding sstatush for RV32), it is
not certain there are enough remaining bits in sstatus to accommodate
all future extensions. In any event, there is no need to strain
sstatus (and add sstatush) for this purpose. The "enable" flags
that are needed to plug covert channels are not generally expected to
require swapping on context switches of user threads, making them a
less-than-compelling candidate for inclusion in sstatus. Hence, a new
place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may
optionally implement four new 64-bit CSRs at machine level, listed with
their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined
at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for
the respective modes. For RV32, the registers listed above are 32-bit,
and for the machine-level and hypervisor CSRs there is a corresponding
set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time
because it is expected the upper 32 bits of these registers will always
be zeros, as explained later below.
The number of registers provided at each level is four because it is
believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years
to come, perhaps for as long as the RISC-V ISA is in use. The exact
number four is an attempted compromise between providing too few bits
on the one hand and going overboard with CSRs that will never be used
on the other. A possible future doubling of the number of stateen CSRs
is discussed later.
The registers at each level control access to state at all lower
privilege levels, but not at its own level. This is analogous to the
function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or
VU mode) to an extension's state, for an extension that was not deemed
"worthy" of a full XS field in sstatus like the FS and VS fields
for the F and V extensions. The intention is to allocate the bits of
sstateen CSRs starting at the least-significant end, bit 0, through to
bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit
is defined in the matching mstateen CSR to control access below machine
level to the same state. The upper 32 bits of an mstateen CSR (or for
RV32, the corresponding high-half CSR) control access to state that is
inherently inaccessible to user level, so no corresponding enable bits
in the supervisor-level sstateen CSR are applicable. The intention is
to allocate bits for this purpose starting at the most-significant end,
bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant
end for sstateen CSRs is sufficiently low, allocation from the most-
significant end of mstateen CSRs may be allowed to encroach on the
lower 32 bits before jumping to the next-higher mstateen CSR. In
that case, the bit positions of "encroaching" bits will remain forever
read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical
encoding to the mstateen CSRs, except controlling accesses for a
virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart
doesn't implement are read-only zeros for that hart. Likewise, all
reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero
or set to zero), the same bit appears as read-only zero in the matching
hstateen and sstateen CSRs. For every bit in an hstateen CSR that is
zero (whether read-only zero or set to zero), the same bit appears as
read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for
initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs
to indicate the state it is prepared to allow lower-privilege software
to access. For OSes and hypervisors, this usually means the state that
the OS or hypervisor is prepared to swap on a context switch, or to
manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform
standards can always make them mandatory). When the stateen CSRs
are not implemented, all state added by an extension is accessible as
defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control
access to the matching supervisor-level sstateen CSR. That is,
bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63
of mstateen1 and hstateen1 controls access to sstateen1; etc. A
hypervisor may need this control over accesses to the sstateen CSRs
if it ever must emulate for a virtual machine an extension that is
supposed to be affected by a bit in an sstateen CSR. (Even if such
emulation is uncommon, it shouldn't be excluded.) Machine-level
software needs identical control to be able to emulate the hypervisor
extension. (That is, machine level needs control over accesses to the
supervisor-level sstaten CSRs in order to emulate the hstateen CSRs,
which have such control.)
If the hypervisor extension is not implemented and a supervisor-level
sstateen CSR is all read-only zeros, an implementation may make bit 63
of the matching mstateen read-only zero. In that case, machine-level
software should preferably emulate attempts to access the affected
sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0,
mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information
returned by the optional QUERY instruction, even though this cannot act
as a covert channel between user threads or guest OSes. For more, see
the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions
operate on X registers instead of F registers. Whenever misa.F = 1,
bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs
are implemented and misa.F = 0, then if bit 1 of a relevant stateen0
CSR is zero, _all_ floating-point instructions cause an illegal
instruction trap (or possibly a virtual instruction trap, if executed
in a virtual machine), as though they all touch fcsr, regardless of
whether they really do.
In addition to the bits listed above for user-accessible state, the
following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros
on reset, machine-level software can set bits in these registers to
enable lower-privilege access to the controlled state. This may be
either because machine-level software knows how to swap the state or,
more likely, because machine-level software isn't swapping supervisor-
level environments. (Recall that the main reason the mstateen CSRs
must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is
likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize
the matching hstateen CSRs to zeros if the hypervisor extension
is implemented. And if any mstateen bits that are set to one have
matching bits in the sstateen CSRs, machine-level software must
initialize those sstateen CSRs to zeros. Ordinarily, machine-level
software will want to set bit 63 of each mstateen CSR, necessitating
that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to
zeros when the OS starts. It can set bits in these registers to enable
user-level access to the controlled state, presumably because the OS
knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for
a guest OS. When it starts a new guest OS, it must ensure the sstaten
CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual
purpose as enables for the ISA extensions that introduce the controlled
state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future
be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal
because it is unclear whether they will ever be needed, and it is
believed the rate of consumption of bits in the first group, numbers
0-3, will be slow enough that any looming shortage will be perceptible
many years in advance. At the moment, it is not known even how many
years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
The proposal below has been discussed by some of the principle RISC-V
architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and
the RISC-V Advanced Interrupt Architecture, which are other extensions
being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged
Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the
potential to open covert channels between separate user threads, or
between separate guest OSes running under a hypervisor. The problem
occurs when an extension adds processor state---usually explicit
registers, but possibly other forms of state---that the main OS or
hypervisor is unaware of (and hence won't context-switch) but that
can be modified/written by one user thread or guest OS and perceived/
examined/read by another.
Consider, for example, that the N extension is someday ratified by
the RISC-V Association, and a hart implements both S mode and the
N extension, with misa.N hardwired = 1. The OS in use on this hart
might be oblivious to the N extension and hence might not test for the
extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that
case, most of these CSRs provide an obvious covert channel between
user threads. Although traditional practices might consider such a
communication channel harmless, the intense focus on security today
argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the
V registers of the vector extension would also be potential covert
channels, except for the existence of the FS and VS fields in the
sstatus register. An OS that is unaware of, say, the vector extension
and its V registers will unwittingly prevent access to those registers
by initializing unknown fields of sstatus to zeros, which in this case
will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as
a covert channel would be to add to sstatus an "NS" field for the
N extension, paralleling the V extension's VS field. However, this is
not considered a general solution to the problem due to the number of
potential future extensions that may add small amounts of state. Even
with a 64-bit sstatus (necessitating adding sstatush for RV32), it is
not certain there are enough remaining bits in sstatus to accommodate
all future extensions. In any event, there is no need to strain
sstatus (and add sstatush) for this purpose. The "enable" flags
that are needed to plug covert channels are not generally expected to
require swapping on context switches of user threads, making them a
less-than-compelling candidate for inclusion in sstatus. Hence, a new
place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may
optionally implement four new 64-bit CSRs at machine level, listed with
their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined
at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for
the respective modes. For RV32, the registers listed above are 32-bit,
and for the machine-level and hypervisor CSRs there is a corresponding
set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time
because it is expected the upper 32 bits of these registers will always
be zeros, as explained later below.
The number of registers provided at each level is four because it is
believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years
to come, perhaps for as long as the RISC-V ISA is in use. The exact
number four is an attempted compromise between providing too few bits
on the one hand and going overboard with CSRs that will never be used
on the other. A possible future doubling of the number of stateen CSRs
is discussed later.
The registers at each level control access to state at all lower
privilege levels, but not at its own level. This is analogous to the
function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or
VU mode) to an extension's state, for an extension that was not deemed
"worthy" of a full XS field in sstatus like the FS and VS fields
for the F and V extensions. The intention is to allocate the bits of
sstateen CSRs starting at the least-significant end, bit 0, through to
bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit
is defined in the matching mstateen CSR to control access below machine
level to the same state. The upper 32 bits of an mstateen CSR (or for
RV32, the corresponding high-half CSR) control access to state that is
inherently inaccessible to user level, so no corresponding enable bits
in the supervisor-level sstateen CSR are applicable. The intention is
to allocate bits for this purpose starting at the most-significant end,
bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant
end for sstateen CSRs is sufficiently low, allocation from the most-
significant end of mstateen CSRs may be allowed to encroach on the
lower 32 bits before jumping to the next-higher mstateen CSR. In
that case, the bit positions of "encroaching" bits will remain forever
read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical
encoding to the mstateen CSRs, except controlling accesses for a
virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart
doesn't implement are read-only zeros for that hart. Likewise, all
reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero
or set to zero), the same bit appears as read-only zero in the matching
hstateen and sstateen CSRs. For every bit in an hstateen CSR that is
zero (whether read-only zero or set to zero), the same bit appears as
read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for
initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs
to indicate the state it is prepared to allow lower-privilege software
to access. For OSes and hypervisors, this usually means the state that
the OS or hypervisor is prepared to swap on a context switch, or to
manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform
standards can always make them mandatory). When the stateen CSRs
are not implemented, all state added by an extension is accessible as
defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control
access to the matching supervisor-level sstateen CSR. That is,
bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63
of mstateen1 and hstateen1 controls access to sstateen1; etc. A
hypervisor may need this control over accesses to the sstateen CSRs
if it ever must emulate for a virtual machine an extension that is
supposed to be affected by a bit in an sstateen CSR. (Even if such
emulation is uncommon, it shouldn't be excluded.) Machine-level
software needs identical control to be able to emulate the hypervisor
extension. (That is, machine level needs control over accesses to the
supervisor-level sstaten CSRs in order to emulate the hstateen CSRs,
which have such control.)
If the hypervisor extension is not implemented and a supervisor-level
sstateen CSR is all read-only zeros, an implementation may make bit 63
of the matching mstateen read-only zero. In that case, machine-level
software should preferably emulate attempts to access the affected
sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0,
mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information
returned by the optional QUERY instruction, even though this cannot act
as a covert channel between user threads or guest OSes. For more, see
the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions
operate on X registers instead of F registers. Whenever misa.F = 1,
bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs
are implemented and misa.F = 0, then if bit 1 of a relevant stateen0
CSR is zero, _all_ floating-point instructions cause an illegal
instruction trap (or possibly a virtual instruction trap, if executed
in a virtual machine), as though they all touch fcsr, regardless of
whether they really do.
In addition to the bits listed above for user-accessible state, the
following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros
on reset, machine-level software can set bits in these registers to
enable lower-privilege access to the controlled state. This may be
either because machine-level software knows how to swap the state or,
more likely, because machine-level software isn't swapping supervisor-
level environments. (Recall that the main reason the mstateen CSRs
must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is
likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize
the matching hstateen CSRs to zeros if the hypervisor extension
is implemented. And if any mstateen bits that are set to one have
matching bits in the sstateen CSRs, machine-level software must
initialize those sstateen CSRs to zeros. Ordinarily, machine-level
software will want to set bit 63 of each mstateen CSR, necessitating
that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to
zeros when the OS starts. It can set bits in these registers to enable
user-level access to the controlled state, presumably because the OS
knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for
a guest OS. When it starts a new guest OS, it must ensure the sstaten
CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual
purpose as enables for the ISA extensions that introduce the controlled
state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future
be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal
because it is unclear whether they will ever be needed, and it is
believed the rate of consumption of bits in the first group, numbers
0-3, will be slow enough that any looming shortage will be perceptible
many years in advance. At the moment, it is not known even how many
years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
Bill Huffman
Hello John,
Are some of the bits in xstateen allocated for custom use?
Bill
toggle quoted message
Show quoted text
Are some of the bits in xstateen allocated for custom use?
Bill
-----Original Message-----
From: tech-privileged@... <tech-privileged@...> On Behalf Of John Hauser
Sent: Tuesday, April 20, 2021 2:18 PM
To: tech-privileged@...
Subject: [RISC-V] [tech-privileged] proposal for stateen CSRs
EXTERNAL MAIL
Hello tech-privileged,
The proposal below has been discussed by some of the principle RISC-V architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and the RISC-V Advanced Interrupt Architecture, which are other extensions being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the potential to open covert channels between separate user threads, or between separate guest OSes running under a hypervisor. The problem occurs when an extension adds processor state---usually explicit registers, but possibly other forms of state---that the main OS or hypervisor is unaware of (and hence won't context-switch) but that can be modified/written by one user thread or guest OS and perceived/ examined/read by another.
Consider, for example, that the N extension is someday ratified by the RISC-V Association, and a hart implements both S mode and the N extension, with misa.N hardwired = 1. The OS in use on this hart might be oblivious to the N extension and hence might not test for the extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that case, most of these CSRs provide an obvious covert channel between user threads. Although traditional practices might consider such a communication channel harmless, the intense focus on security today argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the V registers of the vector extension would also be potential covert channels, except for the existence of the FS and VS fields in the sstatus register. An OS that is unaware of, say, the vector extension and its V registers will unwittingly prevent access to those registers by initializing unknown fields of sstatus to zeros, which in this case will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as a covert channel would be to add to sstatus an "NS" field for the N extension, paralleling the V extension's VS field. However, this is not considered a general solution to the problem due to the number of potential future extensions that may add small amounts of state. Even with a 64-bit sstatus (necessitating adding sstatush for RV32), it is not certain there are enough remaining bits in sstatus to accommodate all future extensions. In any event, there is no need to strain sstatus (and add sstatush) for this purpose. The "enable" flags that are needed to plug covert channels are not generally expected to require swapping on context switches of user threads, making them a less-than-compelling candidate for inclusion in sstatus. Hence, a new place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may optionally implement four new 64-bit CSRs at machine level, listed with their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for the respective modes. For RV32, the registers listed above are 32-bit, and for the machine-level and hypervisor CSRs there is a corresponding set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time because it is expected the upper 32 bits of these registers will always be zeros, as explained later below.
The number of registers provided at each level is four because it is believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years to come, perhaps for as long as the RISC-V ISA is in use. The exact number four is an attempted compromise between providing too few bits on the one hand and going overboard with CSRs that will never be used on the other. A possible future doubling of the number of stateen CSRs is discussed later.
The registers at each level control access to state at all lower privilege levels, but not at its own level. This is analogous to the function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or VU mode) to an extension's state, for an extension that was not deemed "worthy" of a full XS field in sstatus like the FS and VS fields for the F and V extensions. The intention is to allocate the bits of sstateen CSRs starting at the least-significant end, bit 0, through to bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit is defined in the matching mstateen CSR to control access below machine level to the same state. The upper 32 bits of an mstateen CSR (or for RV32, the corresponding high-half CSR) control access to state that is inherently inaccessible to user level, so no corresponding enable bits in the supervisor-level sstateen CSR are applicable. The intention is to allocate bits for this purpose starting at the most-significant end, bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant end for sstateen CSRs is sufficiently low, allocation from the most- significant end of mstateen CSRs may be allowed to encroach on the lower 32 bits before jumping to the next-higher mstateen CSR. In that case, the bit positions of "encroaching" bits will remain forever read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical encoding to the mstateen CSRs, except controlling accesses for a virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart doesn't implement are read-only zeros for that hart. Likewise, all reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in the matching hstateen and sstateen CSRs. For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs to indicate the state it is prepared to allow lower-privilege software to access. For OSes and hypervisors, this usually means the state that the OS or hypervisor is prepared to swap on a context switch, or to manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform standards can always make them mandatory). When the stateen CSRs are not implemented, all state added by an extension is accessible as defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control access to the matching supervisor-level sstateen CSR. That is, bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63 of mstateen1 and hstateen1 controls access to sstateen1; etc. A hypervisor may need this control over accesses to the sstateen CSRs if it ever must emulate for a virtual machine an extension that is supposed to be affected by a bit in an sstateen CSR. (Even if such emulation is uncommon, it shouldn't be excluded.) Machine-level software needs identical control to be able to emulate the hypervisor extension. (That is, machine level needs control over accesses to the supervisor-level sstaten CSRs in order to emulate the hstateen CSRs, which have such control.)
If the hypervisor extension is not implemented and a supervisor-level sstateen CSR is all read-only zeros, an implementation may make bit 63 of the matching mstateen read-only zero. In that case, machine-level software should preferably emulate attempts to access the affected sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0, mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information returned by the optional QUERY instruction, even though this cannot act as a covert channel between user threads or guest OSes. For more, see the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions operate on X registers instead of F registers. Whenever misa.F = 1, bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs are implemented and misa.F = 0, then if bit 1 of a relevant stateen0 CSR is zero, _all_ floating-point instructions cause an illegal instruction trap (or possibly a virtual instruction trap, if executed in a virtual machine), as though they all touch fcsr, regardless of whether they really do.
In addition to the bits listed above for user-accessible state, the following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros on reset, machine-level software can set bits in these registers to enable lower-privilege access to the controlled state. This may be either because machine-level software knows how to swap the state or, more likely, because machine-level software isn't swapping supervisor- level environments. (Recall that the main reason the mstateen CSRs must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize the matching hstateen CSRs to zeros if the hypervisor extension is implemented. And if any mstateen bits that are set to one have matching bits in the sstateen CSRs, machine-level software must initialize those sstateen CSRs to zeros. Ordinarily, machine-level software will want to set bit 63 of each mstateen CSR, necessitating that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to zeros when the OS starts. It can set bits in these registers to enable user-level access to the controlled state, presumably because the OS knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for a guest OS. When it starts a new guest OS, it must ensure the sstaten CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual purpose as enables for the ISA extensions that introduce the controlled state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal because it is unclear whether they will ever be needed, and it is believed the rate of consumption of bits in the first group, numbers 0-3, will be slow enough that any looming shortage will be perceptible many years in advance. At the moment, it is not known even how many years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
From: tech-privileged@... <tech-privileged@...> On Behalf Of John Hauser
Sent: Tuesday, April 20, 2021 2:18 PM
To: tech-privileged@...
Subject: [RISC-V] [tech-privileged] proposal for stateen CSRs
EXTERNAL MAIL
Hello tech-privileged,
The proposal below has been discussed by some of the principle RISC-V architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and the RISC-V Advanced Interrupt Architecture, which are other extensions being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the potential to open covert channels between separate user threads, or between separate guest OSes running under a hypervisor. The problem occurs when an extension adds processor state---usually explicit registers, but possibly other forms of state---that the main OS or hypervisor is unaware of (and hence won't context-switch) but that can be modified/written by one user thread or guest OS and perceived/ examined/read by another.
Consider, for example, that the N extension is someday ratified by the RISC-V Association, and a hart implements both S mode and the N extension, with misa.N hardwired = 1. The OS in use on this hart might be oblivious to the N extension and hence might not test for the extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that case, most of these CSRs provide an obvious covert channel between user threads. Although traditional practices might consider such a communication channel harmless, the intense focus on security today argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the V registers of the vector extension would also be potential covert channels, except for the existence of the FS and VS fields in the sstatus register. An OS that is unaware of, say, the vector extension and its V registers will unwittingly prevent access to those registers by initializing unknown fields of sstatus to zeros, which in this case will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as a covert channel would be to add to sstatus an "NS" field for the N extension, paralleling the V extension's VS field. However, this is not considered a general solution to the problem due to the number of potential future extensions that may add small amounts of state. Even with a 64-bit sstatus (necessitating adding sstatush for RV32), it is not certain there are enough remaining bits in sstatus to accommodate all future extensions. In any event, there is no need to strain sstatus (and add sstatush) for this purpose. The "enable" flags that are needed to plug covert channels are not generally expected to require swapping on context switches of user threads, making them a less-than-compelling candidate for inclusion in sstatus. Hence, a new place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may optionally implement four new 64-bit CSRs at machine level, listed with their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for the respective modes. For RV32, the registers listed above are 32-bit, and for the machine-level and hypervisor CSRs there is a corresponding set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time because it is expected the upper 32 bits of these registers will always be zeros, as explained later below.
The number of registers provided at each level is four because it is believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years to come, perhaps for as long as the RISC-V ISA is in use. The exact number four is an attempted compromise between providing too few bits on the one hand and going overboard with CSRs that will never be used on the other. A possible future doubling of the number of stateen CSRs is discussed later.
The registers at each level control access to state at all lower privilege levels, but not at its own level. This is analogous to the function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or VU mode) to an extension's state, for an extension that was not deemed "worthy" of a full XS field in sstatus like the FS and VS fields for the F and V extensions. The intention is to allocate the bits of sstateen CSRs starting at the least-significant end, bit 0, through to bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit is defined in the matching mstateen CSR to control access below machine level to the same state. The upper 32 bits of an mstateen CSR (or for RV32, the corresponding high-half CSR) control access to state that is inherently inaccessible to user level, so no corresponding enable bits in the supervisor-level sstateen CSR are applicable. The intention is to allocate bits for this purpose starting at the most-significant end, bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant end for sstateen CSRs is sufficiently low, allocation from the most- significant end of mstateen CSRs may be allowed to encroach on the lower 32 bits before jumping to the next-higher mstateen CSR. In that case, the bit positions of "encroaching" bits will remain forever read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical encoding to the mstateen CSRs, except controlling accesses for a virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart doesn't implement are read-only zeros for that hart. Likewise, all reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in the matching hstateen and sstateen CSRs. For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs to indicate the state it is prepared to allow lower-privilege software to access. For OSes and hypervisors, this usually means the state that the OS or hypervisor is prepared to swap on a context switch, or to manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform standards can always make them mandatory). When the stateen CSRs are not implemented, all state added by an extension is accessible as defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control access to the matching supervisor-level sstateen CSR. That is, bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63 of mstateen1 and hstateen1 controls access to sstateen1; etc. A hypervisor may need this control over accesses to the sstateen CSRs if it ever must emulate for a virtual machine an extension that is supposed to be affected by a bit in an sstateen CSR. (Even if such emulation is uncommon, it shouldn't be excluded.) Machine-level software needs identical control to be able to emulate the hypervisor extension. (That is, machine level needs control over accesses to the supervisor-level sstaten CSRs in order to emulate the hstateen CSRs, which have such control.)
If the hypervisor extension is not implemented and a supervisor-level sstateen CSR is all read-only zeros, an implementation may make bit 63 of the matching mstateen read-only zero. In that case, machine-level software should preferably emulate attempts to access the affected sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0, mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information returned by the optional QUERY instruction, even though this cannot act as a covert channel between user threads or guest OSes. For more, see the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions operate on X registers instead of F registers. Whenever misa.F = 1, bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs are implemented and misa.F = 0, then if bit 1 of a relevant stateen0 CSR is zero, _all_ floating-point instructions cause an illegal instruction trap (or possibly a virtual instruction trap, if executed in a virtual machine), as though they all touch fcsr, regardless of whether they really do.
In addition to the bits listed above for user-accessible state, the following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros on reset, machine-level software can set bits in these registers to enable lower-privilege access to the controlled state. This may be either because machine-level software knows how to swap the state or, more likely, because machine-level software isn't swapping supervisor- level environments. (Recall that the main reason the mstateen CSRs must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize the matching hstateen CSRs to zeros if the hypervisor extension is implemented. And if any mstateen bits that are set to one have matching bits in the sstateen CSRs, machine-level software must initialize those sstateen CSRs to zeros. Ordinarily, machine-level software will want to set bit 63 of each mstateen CSR, necessitating that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to zeros when the OS starts. It can set bits in these registers to enable user-level access to the controlled state, presumably because the OS knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for a guest OS. When it starts a new guest OS, it must ensure the sstaten CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual purpose as enables for the ISA extensions that introduce the controlled state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal because it is unclear whether they will ever be needed, and it is believed the rate of consumption of bits in the first group, numbers 0-3, will be slow enough that any looming shortage will be perceptible many years in advance. At the moment, it is not known even how many years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
It seems the use model is to enable older environment-swapping software to run on newer hardware without opening a security hole via new state. Only if the software is aware of the state will it enable that state via *stateen.
For custom state, you can always make custom *stateen-like CSRs to enable it. You're going to need custom software to swap that state anyway.
But there's also the use model of the M-mode software that doesn't do any environment swapping and just wants to enable all state for the S-mode. It would be nice if that didn't have to be aware of custom state.
So, I join Bill in his question. It seems a good idea to reserve some bits for custom state for that latter use model.
On Tue, Apr 20, 2021 at 1:48 PM Bill Huffman <huffman@...> wrote:
Hello John,
Are some of the bits in xstateen allocated for custom use?
Bill
-----Original Message-----
From: tech-privileged@... <tech-privileged@...> On Behalf Of John Hauser
Sent: Tuesday, April 20, 2021 2:18 PM
To: tech-privileged@...
Subject: [RISC-V] [tech-privileged] proposal for stateen CSRs
EXTERNAL MAIL
Hello tech-privileged,
The proposal below has been discussed by some of the principle RISC-V architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and the RISC-V Advanced Interrupt Architecture, which are other extensions being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the potential to open covert channels between separate user threads, or between separate guest OSes running under a hypervisor. The problem occurs when an extension adds processor state---usually explicit registers, but possibly other forms of state---that the main OS or hypervisor is unaware of (and hence won't context-switch) but that can be modified/written by one user thread or guest OS and perceived/ examined/read by another.
Consider, for example, that the N extension is someday ratified by the RISC-V Association, and a hart implements both S mode and the N extension, with misa.N hardwired = 1. The OS in use on this hart might be oblivious to the N extension and hence might not test for the extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that case, most of these CSRs provide an obvious covert channel between user threads. Although traditional practices might consider such a communication channel harmless, the intense focus on security today argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the V registers of the vector extension would also be potential covert channels, except for the existence of the FS and VS fields in the sstatus register. An OS that is unaware of, say, the vector extension and its V registers will unwittingly prevent access to those registers by initializing unknown fields of sstatus to zeros, which in this case will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as a covert channel would be to add to sstatus an "NS" field for the N extension, paralleling the V extension's VS field. However, this is not considered a general solution to the problem due to the number of potential future extensions that may add small amounts of state. Even with a 64-bit sstatus (necessitating adding sstatush for RV32), it is not certain there are enough remaining bits in sstatus to accommodate all future extensions. In any event, there is no need to strain sstatus (and add sstatush) for this purpose. The "enable" flags that are needed to plug covert channels are not generally expected to require swapping on context switches of user threads, making them a less-than-compelling candidate for inclusion in sstatus. Hence, a new place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may optionally implement four new 64-bit CSRs at machine level, listed with their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for the respective modes. For RV32, the registers listed above are 32-bit, and for the machine-level and hypervisor CSRs there is a corresponding set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time because it is expected the upper 32 bits of these registers will always be zeros, as explained later below.
The number of registers provided at each level is four because it is believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years to come, perhaps for as long as the RISC-V ISA is in use. The exact number four is an attempted compromise between providing too few bits on the one hand and going overboard with CSRs that will never be used on the other. A possible future doubling of the number of stateen CSRs is discussed later.
The registers at each level control access to state at all lower privilege levels, but not at its own level. This is analogous to the function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or VU mode) to an extension's state, for an extension that was not deemed "worthy" of a full XS field in sstatus like the FS and VS fields for the F and V extensions. The intention is to allocate the bits of sstateen CSRs starting at the least-significant end, bit 0, through to bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit is defined in the matching mstateen CSR to control access below machine level to the same state. The upper 32 bits of an mstateen CSR (or for RV32, the corresponding high-half CSR) control access to state that is inherently inaccessible to user level, so no corresponding enable bits in the supervisor-level sstateen CSR are applicable. The intention is to allocate bits for this purpose starting at the most-significant end, bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant end for sstateen CSRs is sufficiently low, allocation from the most- significant end of mstateen CSRs may be allowed to encroach on the lower 32 bits before jumping to the next-higher mstateen CSR. In that case, the bit positions of "encroaching" bits will remain forever read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical encoding to the mstateen CSRs, except controlling accesses for a virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart doesn't implement are read-only zeros for that hart. Likewise, all reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in the matching hstateen and sstateen CSRs. For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs to indicate the state it is prepared to allow lower-privilege software to access. For OSes and hypervisors, this usually means the state that the OS or hypervisor is prepared to swap on a context switch, or to manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform standards can always make them mandatory). When the stateen CSRs are not implemented, all state added by an extension is accessible as defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control access to the matching supervisor-level sstateen CSR. That is, bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63 of mstateen1 and hstateen1 controls access to sstateen1; etc. A hypervisor may need this control over accesses to the sstateen CSRs if it ever must emulate for a virtual machine an extension that is supposed to be affected by a bit in an sstateen CSR. (Even if such emulation is uncommon, it shouldn't be excluded.) Machine-level software needs identical control to be able to emulate the hypervisor extension. (That is, machine level needs control over accesses to the supervisor-level sstaten CSRs in order to emulate the hstateen CSRs, which have such control.)
If the hypervisor extension is not implemented and a supervisor-level sstateen CSR is all read-only zeros, an implementation may make bit 63 of the matching mstateen read-only zero. In that case, machine-level software should preferably emulate attempts to access the affected sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0, mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information returned by the optional QUERY instruction, even though this cannot act as a covert channel between user threads or guest OSes. For more, see the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions operate on X registers instead of F registers. Whenever misa.F = 1, bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs are implemented and misa.F = 0, then if bit 1 of a relevant stateen0 CSR is zero, _all_ floating-point instructions cause an illegal instruction trap (or possibly a virtual instruction trap, if executed in a virtual machine), as though they all touch fcsr, regardless of whether they really do.
In addition to the bits listed above for user-accessible state, the following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros on reset, machine-level software can set bits in these registers to enable lower-privilege access to the controlled state. This may be either because machine-level software knows how to swap the state or, more likely, because machine-level software isn't swapping supervisor- level environments. (Recall that the main reason the mstateen CSRs must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize the matching hstateen CSRs to zeros if the hypervisor extension is implemented. And if any mstateen bits that are set to one have matching bits in the sstateen CSRs, machine-level software must initialize those sstateen CSRs to zeros. Ordinarily, machine-level software will want to set bit 63 of each mstateen CSR, necessitating that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to zeros when the OS starts. It can set bits in these registers to enable user-level access to the controlled state, presumably because the OS knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for a guest OS. When it starts a new guest OS, it must ensure the sstaten CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual purpose as enables for the ISA extensions that introduce the controlled state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal because it is unclear whether they will ever be needed, and it is believed the rate of consumption of bits in the first group, numbers 0-3, will be slow enough that any looming shortage will be perceptible many years in advance. At the moment, it is not known even how many years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
Questions: (I suspect I know the answers, but want to be clear):
-if mstateenY[n] is cleared, and s-mode code tries to read/write a CSR that is controlled by that bit
-- does the access trap?
-- else does it cause read/writes of the CSR from Smode
--- to return zero/have no effect
--- to return the value it had at the time that the bit was cleared/have no effect
Or put another way: what exactly does "control access" mean?
On Tue, Apr 20, 2021 at 1:47 PM Bill Huffman <huffman@...> wrote:
Hello John,
Are some of the bits in xstateen allocated for custom use?
Bill
-----Original Message-----
From: tech-privileged@... <tech-privileged@...> On Behalf Of John Hauser
Sent: Tuesday, April 20, 2021 2:18 PM
To: tech-privileged@...
Subject: [RISC-V] [tech-privileged] proposal for stateen CSRs
EXTERNAL MAIL
Hello tech-privileged,
The proposal below has been discussed by some of the principle RISC-V architects for incorporation into the official Privileged Architecture.
The text below makes reference to Zfinx, Sstc, a QUERY instruction, and the RISC-V Advanced Interrupt Architecture, which are other extensions being separately developed.
- John H.
----------------------------------------
The following is a proposal for an addition to the main Privileged Architecture (not a separately named extension).
--------------------
Motivation
Currently, the implementation of optional RISC-V extensions has the potential to open covert channels between separate user threads, or between separate guest OSes running under a hypervisor. The problem occurs when an extension adds processor state---usually explicit registers, but possibly other forms of state---that the main OS or hypervisor is unaware of (and hence won't context-switch) but that can be modified/written by one user thread or guest OS and perceived/ examined/read by another.
Consider, for example, that the N extension is someday ratified by the RISC-V Association, and a hart implements both S mode and the N extension, with misa.N hardwired = 1. The OS in use on this hart might be oblivious to the N extension and hence might not test for the extension or pay any attention to the eight CSRs it adds to the ISA:
ustatus, uie, utvec, uscratch, uepc, ucause, utval, and uip. In that case, most of these CSRs provide an obvious covert channel between user threads. Although traditional practices might consider such a communication channel harmless, the intense focus on security today argues that a means be offered to plug such channels.
The F registers of the RISC-V floating-point extensions and the V registers of the vector extension would also be potential covert channels, except for the existence of the FS and VS fields in the sstatus register. An OS that is unaware of, say, the vector extension and its V registers will unwittingly prevent access to those registers by initializing unknown fields of sstatus to zeros, which in this case will include the VS field.
Obviously, one way to prevent the use of the N extension's CSRs as a covert channel would be to add to sstatus an "NS" field for the N extension, paralleling the V extension's VS field. However, this is not considered a general solution to the problem due to the number of potential future extensions that may add small amounts of state. Even with a 64-bit sstatus (necessitating adding sstatush for RV32), it is not certain there are enough remaining bits in sstatus to accommodate all future extensions. In any event, there is no need to strain sstatus (and add sstatush) for this purpose. The "enable" flags that are needed to plug covert channels are not generally expected to require swapping on context switches of user threads, making them a less-than-compelling candidate for inclusion in sstatus. Hence, a new place is proposed for them instead.
--------------------
Proposal
RV64 harts that conform to the RISC-V Privileged Architecture may optionally implement four new 64-bit CSRs at machine level, listed with their CSR addresses:
0x30C mstateen0 (Machine State Enable 0)
0x30D mstateen1
0x30E mstateen2
0x30F mstateen3
If supervisor mode is implemented, another four CSRs would be defined at supervisor level:
0x10C sstateen0
0x10D sstateen1
0x10E sstateen2
0x10F sstateen3
And if the hypervisor extension is implemented, another set of CSRs is
added:
0x60C hstateen0
0x60D hstateen1
0x60E hstateen2
0x60F hstateen3
If any "stateen" CSRs is implemented, they must all be implemented for the respective modes. For RV32, the registers listed above are 32-bit, and for the machine-level and hypervisor CSRs there is a corresponding set of high-half CSRs for the upper 32 bits of each register:
0x31C mstateen0h
0x31D mstateen1h
0x31E mstateen2h
0x31F mstateen3h
0x61C hstateen0h
0x61D hstateen1h
0x61E hstateen2h
0x61F hstateen3h
For the sstateen registers, high-half CSRs are not added at this time because it is expected the upper 32 bits of these registers will always be zeros, as explained later below.
The number of registers provided at each level is four because it is believed that 4 * 64 = 256 bits for machine and hypervisor levels, and
4 * 32 = 128 bits for supervisor level, will be adequate for many years to come, perhaps for as long as the RISC-V ISA is in use. The exact number four is an attempted compromise between providing too few bits on the one hand and going overboard with CSRs that will never be used on the other. A possible future doubling of the number of stateen CSRs is discussed later.
The registers at each level control access to state at all lower privilege levels, but not at its own level. This is analogous to the function of the existing counteren CSRs.
Each bit of an sstateen CSR controls user-level access (from U mode or VU mode) to an extension's state, for an extension that was not deemed "worthy" of a full XS field in sstatus like the FS and VS fields for the F and V extensions. The intention is to allocate the bits of sstateen CSRs starting at the least-significant end, bit 0, through to bit 31, and then on to the next-higher sstateen CSR.
For every bit with a defined purpose in an sstateen CSR, the same bit is defined in the matching mstateen CSR to control access below machine level to the same state. The upper 32 bits of an mstateen CSR (or for RV32, the corresponding high-half CSR) control access to state that is inherently inaccessible to user level, so no corresponding enable bits in the supervisor-level sstateen CSR are applicable. The intention is to allocate bits for this purpose starting at the most-significant end, bit 63, through to bit 32, and then on to the next-higher mstateen CSR.
If the rate that bits are being allocated from the least-significant end for sstateen CSRs is sufficiently low, allocation from the most- significant end of mstateen CSRs may be allowed to encroach on the lower 32 bits before jumping to the next-higher mstateen CSR. In that case, the bit positions of "encroaching" bits will remain forever read-only zeros in the matching sstateen CSRs.
With the hypervisor extension, the hstateen CSRs have identical encoding to the mstateen CSRs, except controlling accesses for a virtual machine (from VS and VU modes).
Bits in any stateen CSR that are defined to control state that a hart doesn't implement are read-only zeros for that hart. Likewise, all reserved bits not yet given a defined meaning are also read-only zeros.
For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in the matching hstateen and sstateen CSRs. For every bit in an hstateen CSR that is zero (whether read-only zero or set to zero), the same bit appears as read-only zero in sstateen when accessed from a virtual machine.
On reset, all mstateen bits are initialized by the hardware to zeros.
If machine-level software changes these values, it is responsible for initializing the matching hstateen and sstateen CSRs to zeros too.
Software at each privilege level should set its respective stateen CSRs to indicate the state it is prepared to allow lower-privilege software to access. For OSes and hypervisors, this usually means the state that the OS or hypervisor is prepared to swap on a context switch, or to manage in some other way.
Implementing the stateen CSRs is optional for harts (though platform standards can always make them mandatory). When the stateen CSRs are not implemented, all state added by an extension is accessible as defined by that extension.
For each mstateen and hstateen CSR, bit 63 is defined to control access to the matching supervisor-level sstateen CSR. That is, bit 63 of mstateen0 and hstateen0 controls access to sstateen0; bit 63 of mstateen1 and hstateen1 controls access to sstateen1; etc. A hypervisor may need this control over accesses to the sstateen CSRs if it ever must emulate for a virtual machine an extension that is supposed to be affected by a bit in an sstateen CSR. (Even if such emulation is uncommon, it shouldn't be excluded.) Machine-level software needs identical control to be able to emulate the hypervisor extension. (That is, machine level needs control over accesses to the supervisor-level sstaten CSRs in order to emulate the hstateen CSRs, which have such control.)
If the hypervisor extension is not implemented and a supervisor-level sstateen CSR is all read-only zeros, an implementation may make bit 63 of the matching mstateen read-only zero. In that case, machine-level software should preferably emulate attempts to access the affected sstateen CSR from S mode, ignoring writes and returning zero for reads.
Initially, the following bits are proposed to be defined in sstaten0, mstateen0, and hstateen0:
bit 0 QUERY data
bit 1 fcsr for Zfinx and related extensions (Zdinx, etc.)
bit 2 Tentatively reserved for the N extension
As a special case, bit 0 is used to control access to the information returned by the optional QUERY instruction, even though this cannot act as a covert channel between user threads or guest OSes. For more, see the documentation for the QUERY instruction.
Bit 1 applies only for the case when floating-point instructions operate on X registers instead of F registers. Whenever misa.F = 1, bit 1 of mstateen0 is read-only zero (and hence read-only zero in
hstateen0 and sstateen0 too). For convenience, when the stateen CSRs are implemented and misa.F = 0, then if bit 1 of a relevant stateen0 CSR is zero, _all_ floating-point instructions cause an illegal instruction trap (or possibly a virtual instruction trap, if executed in a virtual machine), as though they all touch fcsr, regardless of whether they really do.
In addition to the bits listed above for user-accessible state, the following are also proposed initially for mstateen0 and hstateen0:
bit 61 Reserved for the RISC-V Advanced Interrupt Architecture
bit 62 stimecmp, vstimecmp of Sstc extension
bit 63 sstaten0
--------------------
Usage
After the machine-level mstateen CSRs are all initialized to zeros on reset, machine-level software can set bits in these registers to enable lower-privilege access to the controlled state. This may be either because machine-level software knows how to swap the state or, more likely, because machine-level software isn't swapping supervisor- level environments. (Recall that the main reason the mstateen CSRs must exist is so machine level can emulate the hypervisor extension.
When machine level isn't emulating the hypervisor extension, it is likely there will be no need to keep any mstateen bits zero.)
If machine level sets any mstateen bits to nonzero, it must initialize the matching hstateen CSRs to zeros if the hypervisor extension is implemented. And if any mstateen bits that are set to one have matching bits in the sstateen CSRs, machine-level software must initialize those sstateen CSRs to zeros. Ordinarily, machine-level software will want to set bit 63 of each mstateen CSR, necessitating that it zero all hstateen and sstateen CSRs.
An OS at supervisor level should see the sstateen CSRs initialized to zeros when the OS starts. It can set bits in these registers to enable user-level access to the controlled state, presumably because the OS knows how to context-swap the state.
A hypervisor must include the sstateen CSRs in the context it swaps for a guest OS. When it starts a new guest OS, it must ensure the sstaten CSRs are initialized to zeros.
In many cases, the various bits of the stateen CSRs will have a dual purpose as enables for the ISA extensions that introduce the controlled state.
--------------------
Possible expansion
If a need is anticipated, the set of stateen CSRs could in the future be doubled by adding these:
0x38C mstateen4 0x39C mstateen4h
0x38D mstateen5 0x39D mstateen5h
0x38E mstateen6 0x39E mstateen6h
0x38F mstateen7 0x39F mstateen7h
0x18C sstateen4
0x18D sstateen5
0x18E sstateen6
0x18F sstateen7
0x68C hstateen4 0x69C hstateen4h
0x68D hstateen5 0x69D hstateen5h
0x68E hstateen6 0x69E hstateen6h
0x68F hstateen7 0x69F hstateen7h
These additional CSRs are not a definite part of the original proposal because it is unclear whether they will ever be needed, and it is believed the rate of consumption of bits in the first group, numbers 0-3, will be slow enough that any looming shortage will be perceptible many years in advance. At the moment, it is not known even how many years it may take to exhaust just mstateen0, sstateen0, and hstateen0.
John Hauser
Scott Johnson wrote:
same effect by adding a single "write-only" bit to mstateen0. The bit
always reads as zero, and writing zero to it does nothing; but writing
a one causes all custom state to be enabled for lower privilege levels.
As you suggested, there will presumably be custom CSRs containing
one or more bits that control access to the custom state, akin to
the mstateen CSRs for standardized state. Machine-level software may
consult and modify those custom-state-controlling bits directly if it
has sufficient knowledge, but won't have to.
- John Hauser
It seems the use model is to enable older environment-swapping software toYes, that's exactly what we were thinking.
run on newer hardware without opening a security hole via new state. Only
if the software is aware of the state will it enable that state via
*stateen.
For custom state, you can always make custom *stateen-like CSRs to enable
it. You're going to need custom software to swap that state anyway.
But there's also the use model of the M-mode software that doesn't do anyThis seems like a sensible request to me, except I would accomplish the
environment swapping and just wants to enable all state for the S-mode. It
would be nice if that didn't have to be aware of custom state.
So, I join Bill in his question. It seems a good idea to reserve some bits
for custom state for that latter use model.
same effect by adding a single "write-only" bit to mstateen0. The bit
always reads as zero, and writing zero to it does nothing; but writing
a one causes all custom state to be enabled for lower privilege levels.
As you suggested, there will presumably be custom CSRs containing
one or more bits that control access to the custom state, akin to
the mstateen CSRs for standardized state. Machine-level software may
consult and modify those custom-state-controlling bits directly if it
has sufficient knowledge, but won't have to.
- John Hauser
John Hauser
Allen Baum wrote:
To quote Admiral Ackbar: "It's a trap!" You get an illegal
instruction trap, unless you're executing in a virtual machine (V = 1)
and the access is _not_ being blocked by the mstateen CSRs, in which
case you get a virtual instruction trap.
(Related to that, it's on my to-do list to add to the Privileged
Architecture's hypervisor chapter a better general explanation for
when you should get a virtual instruction trap instead of an illegal
instruction trap.)
- John Hauser
Questions: (I suspect I know the answers, but want to be clear):I forgot to say what that means, didn't I? Good point!
-if mstateenY[n] is cleared, and s-mode code tries to read/write a CSR
that is controlled by that bit
-- does the access trap?
-- else does it cause read/writes of the CSR from Smode
--- to return zero/have no effect
--- to return the value it had at the time that the bit was
cleared/have no effect
Or put another way: what exactly does "control access" mean?
To quote Admiral Ackbar: "It's a trap!" You get an illegal
instruction trap, unless you're executing in a virtual machine (V = 1)
and the access is _not_ being blocked by the mstateen CSRs, in which
case you get a virtual instruction trap.
(Related to that, it's on my to-do list to add to the Privileged
Architecture's hypervisor chapter a better general explanation for
when you should get a virtual instruction trap instead of an illegal
instruction trap.)
- John Hauser
Jonathan Behrens <behrensj@...>
The proposed mstateenX CSRs feels very similar to misa. It almost seems like you could achieve the same thing as this proposal just by adding sisa and hisa (plus misa2, misa3, ...), but I think I've convinced myself that wouldn't quite work.
I'll also point out that we'll probably want to reserve a bit in [m|s]stateen0 for the H-extension.
Jonathan
Allen Baum wrote:
> Questions: (I suspect I know the answers, but want to be clear):
> -if mstateenY[n] is cleared, and s-mode code tries to read/write a CSR
> that is controlled by that bit
> -- does the access trap?
> -- else does it cause read/writes of the CSR from Smode
> --- to return zero/have no effect
> --- to return the value it had at the time that the bit was
> cleared/have no effect
>
> Or put another way: what exactly does "control access" mean?
I forgot to say what that means, didn't I? Good point!
To quote Admiral Ackbar: "It's a trap!" You get an illegal
instruction trap, unless you're executing in a virtual machine (V = 1)
and the access is _not_ being blocked by the mstateen CSRs, in which
case you get a virtual instruction trap.
(Related to that, it's on my to-do list to add to the Privileged
Architecture's hypervisor chapter a better general explanation for
when you should get a virtual instruction trap instead of an illegal
instruction trap.)
- John Hauser
Bill Huffman
From: Scott Johnson <scott.johnson@...>
Sent: Tuesday, April 20, 2021 8:33 PM
To: Bill Huffman <huffman@...>
Cc: tech-privileged@...
Subject: Re: [RISC-V] [tech-privileged] proposal for stateen CSRs
Sent: Tuesday, April 20, 2021 8:33 PM
To: Bill Huffman <huffman@...>
Cc: tech-privileged@...
Subject: Re: [RISC-V] [tech-privileged] proposal for stateen CSRs
EXTERNAL MAIL
It seems the use model is to enable older environment-swapping software to run on newer hardware without opening a security hole via new state. Only if the software is aware of the state will it enable that state via *stateen.
For custom state, you can always make custom *stateen-like CSRs to enable it. You're going to need custom software to swap that state anyway.
True. I was thinking of unifying the two purposes when I asked the question.
Bill
I agree one bit is sufficient, but I don’t understand the write-only, read-zero behavior?
Would M-mode never be able to revoke permissions?
On Tue, Apr 20, 2021 at 6:33 PM John Hauser <jh.riscv@...> wrote:
Scott Johnson wrote:
> It seems the use model is to enable older environment-swapping software to
> run on newer hardware without opening a security hole via new state. Only
> if the software is aware of the state will it enable that state via
> *stateen.
>
> For custom state, you can always make custom *stateen-like CSRs to enable
> it. You're going to need custom software to swap that state anyway.
Yes, that's exactly what we were thinking.
> But there's also the use model of the M-mode software that doesn't do any
> environment swapping and just wants to enable all state for the S-mode. It
> would be nice if that didn't have to be aware of custom state.
>
> So, I join Bill in his question. It seems a good idea to reserve some bits
> for custom state for that latter use model.
This seems like a sensible request to me, except I would accomplish the
same effect by adding a single "write-only" bit to mstateen0. The bit
always reads as zero, and writing zero to it does nothing; but writing
a one causes all custom state to be enabled for lower privilege levels.
As you suggested, there will presumably be custom CSRs containing
one or more bits that control access to the custom state, akin to
the mstateen CSRs for standardized state. Machine-level software may
consult and modify those custom-state-controlling bits directly if it
has sufficient knowledge, but won't have to.
- John Hauser
John Hauser
Jonathan Behrens wrote:
expected to be writable.
Also, to ease future hardware support for nested hypervisors, it turns
out the hypervisor extension is a special case for which having an
enable bit located in hstateen0 is not ideal. The reason is a bit
subtle but has to do with the recursive nature of nested hypervisor
support, when hypervisors are running guests that act as hypervisors
themselves. Having the hypervisor enable bit in hstateen0 can be made
to work, but it's more efficient to place it elsewhere.
So by dumb luck, our earlier assignment of the misa "H" bit for the
hypervisor extension just happens to align with future plans for better
hardware support for nested hypervisors.
- John Hauser
I'll also point out that we'll probably want to reserve a bit inThat would be true, except we already have the "H" bit in misa which is
[m|s]stateen0 for the H-extension.
expected to be writable.
Also, to ease future hardware support for nested hypervisors, it turns
out the hypervisor extension is a special case for which having an
enable bit located in hstateen0 is not ideal. The reason is a bit
subtle but has to do with the recursive nature of nested hypervisor
support, when hypervisors are running guests that act as hypervisors
themselves. Having the hypervisor enable bit in hstateen0 can be made
to work, but it's more efficient to place it elsewhere.
So by dumb luck, our earlier assignment of the misa "H" bit for the
hypervisor extension just happens to align with future plans for better
hardware support for nested hypervisors.
- John Hauser
John Hauser
I wrote:
revoke permissions, and this is best supported with a second bit
alongside the first one. The second bit reads as one if any custom
state is enabled, and as zero if no custom state is enabled. For the
second bit, writing one does nothing, but writing zero disables access
to all the custom state.
In summary, on reads:
1st bit: always 0
2nd bit: 1 if any custom state is enabled; 0 if none is enabled
On writes:
1st bit: 0 does nothing; 1 enables all custom state
2nd bit: 0 disables all custom state; 1 does nothing
To safely support read-modify-write of the stateen CSRs, the first bit
could read as one only to indicate that all custom state is enabled.
However, I don't believe software needs to know that, hence I don't
want to require people to build the AND-gate tree for that, regardless
of how small it might be. So that's how that bit ended up as read-only
zero.
On the other hand, for the second bit, software may be interested to
know whether _any_ custom state has been enabled. The alternative
for the second bit would be to make it read-only one, which isn't as
attractive.
- John Hauser
This seems like a sensible request to me, except I would accomplish theScott Johnson:
same effect by adding a single "write-only" bit to mstateen0. The bit
always reads as zero, and writing zero to it does nothing; but writing
a one causes all custom state to be enabled for lower privilege levels.
[...]
I agree one bit is sufficient, but I don’t understand the write-only,After I wrote my earlier message, I realized we need to be able to
read-zero behavior?
Would M-mode never be able to revoke permissions?
revoke permissions, and this is best supported with a second bit
alongside the first one. The second bit reads as one if any custom
state is enabled, and as zero if no custom state is enabled. For the
second bit, writing one does nothing, but writing zero disables access
to all the custom state.
In summary, on reads:
1st bit: always 0
2nd bit: 1 if any custom state is enabled; 0 if none is enabled
On writes:
1st bit: 0 does nothing; 1 enables all custom state
2nd bit: 0 disables all custom state; 1 does nothing
To safely support read-modify-write of the stateen CSRs, the first bit
could read as one only to indicate that all custom state is enabled.
However, I don't believe software needs to know that, hence I don't
want to require people to build the AND-gate tree for that, regardless
of how small it might be. So that's how that bit ended up as read-only
zero.
On the other hand, for the second bit, software may be interested to
know whether _any_ custom state has been enabled. The alternative
for the second bit would be to make it read-only one, which isn't as
attractive.
- John Hauser
Paul Donahue
Having a more misa-like implementation would also allow virtualization of an implementation without support for a particular stateless extension such as A or B, though it would take more bits. Via emulation, it's possible for a VM to be more capable than the hardware but I don't think that it's possible for a VM to be less capable than the hardware (without a bunch of interaction with M mode using a non-existent SBI call to set misa).
Thanks,
-Paul
On Tue, Apr 20, 2021 at 8:20 PM Jonathan Behrens <behrensj@...> wrote:
The proposed mstateenX CSRs feels very similar to misa. It almost seems like you could achieve the same thing as this proposal just by adding sisa and hisa (plus misa2, misa3, ...), but I think I've convinced myself that wouldn't quite work.I'll also point out that we'll probably want to reserve a bit in [m|s]stateen0 for the H-extension.JonathanAllen Baum wrote:
> Questions: (I suspect I know the answers, but want to be clear):
> -if mstateenY[n] is cleared, and s-mode code tries to read/write a CSR
> that is controlled by that bit
> -- does the access trap?
> -- else does it cause read/writes of the CSR from Smode
> --- to return zero/have no effect
> --- to return the value it had at the time that the bit was
> cleared/have no effect
>
> Or put another way: what exactly does "control access" mean?
I forgot to say what that means, didn't I? Good point!
To quote Admiral Ackbar: "It's a trap!" You get an illegal
instruction trap, unless you're executing in a virtual machine (V = 1)
and the access is _not_ being blocked by the mstateen CSRs, in which
case you get a virtual instruction trap.
(Related to that, it's on my to-do list to add to the Privileged
Architecture's hypervisor chapter a better general explanation for
when you should get a virtual instruction trap instead of an illegal
instruction trap.)
- John Hauser
If I understand the above: you can write a 1 to the first bit, but you'll always read back zero? What does that accomplish?
I think you need to establish what the (legal) reset state(s) is/are first.
Then you can define the bits to be RW1S (readable, write 1 to set/write 0 does nothing) or RW0C (readable, write 0 to clear/write 1 does nothing) or just RW, etc
On Wed, Apr 21, 2021 at 12:09 AM John Hauser <jh.riscv@...> wrote:
I wrote:
> This seems like a sensible request to me, except I would accomplish the
> same effect by adding a single "write-only" bit to mstateen0. The bit
> always reads as zero, and writing zero to it does nothing; but writing
> a one causes all custom state to be enabled for lower privilege levels.
> [...]
Scott Johnson:
> I agree one bit is sufficient, but I don’t understand the write-only,
> read-zero behavior?
>
> Would M-mode never be able to revoke permissions?
After I wrote my earlier message, I realized we need to be able to
revoke permissions, and this is best supported with a second bit
alongside the first one. The second bit reads as one if any custom
state is enabled, and as zero if no custom state is enabled. For the
second bit, writing one does nothing, but writing zero disables access
to all the custom state.
In summary, on reads:
1st bit: always 0
2nd bit: 1 if any custom state is enabled; 0 if none is enabled
On writes:
1st bit: 0 does nothing; 1 enables all custom state
2nd bit: 0 disables all custom state; 1 does nothing
To safely support read-modify-write of the stateen CSRs, the first bit
could read as one only to indicate that all custom state is enabled.
However, I don't believe software needs to know that, hence I don't
want to require people to build the AND-gate tree for that, regardless
of how small it might be. So that's how that bit ended up as read-only
zero.
On the other hand, for the second bit, software may be interested to
know whether _any_ custom state has been enabled. The alternative
for the second bit would be to make it read-only one, which isn't as
attractive.
- John Hauser
Like Allen, I'm not following the need for this complexity. Why not one simple read/write bit that disables all custom state when 0? It would be ANDed with any custom state enable CSR bits, much like misa.X=0 disables all custom extensions.
On Wed, Apr 21, 2021 at 12:09 AM John Hauser <jh.riscv@...> wrote:
I wrote:
> This seems like a sensible request to me, except I would accomplish the
> same effect by adding a single "write-only" bit to mstateen0. The bit
> always reads as zero, and writing zero to it does nothing; but writing
> a one causes all custom state to be enabled for lower privilege levels.
> [...]
Scott Johnson:
> I agree one bit is sufficient, but I don’t understand the write-only,
> read-zero behavior?
>
> Would M-mode never be able to revoke permissions?
After I wrote my earlier message, I realized we need to be able to
revoke permissions, and this is best supported with a second bit
alongside the first one. The second bit reads as one if any custom
state is enabled, and as zero if no custom state is enabled. For the
second bit, writing one does nothing, but writing zero disables access
to all the custom state.
In summary, on reads:
1st bit: always 0
2nd bit: 1 if any custom state is enabled; 0 if none is enabled
On writes:
1st bit: 0 does nothing; 1 enables all custom state
2nd bit: 0 disables all custom state; 1 does nothing
To safely support read-modify-write of the stateen CSRs, the first bit
could read as one only to indicate that all custom state is enabled.
However, I don't believe software needs to know that, hence I don't
want to require people to build the AND-gate tree for that, regardless
of how small it might be. So that's how that bit ended up as read-only
zero.
On the other hand, for the second bit, software may be interested to
know whether _any_ custom state has been enabled. The alternative
for the second bit would be to make it read-only one, which isn't as
attractive.
- John Hauser
John Hauser
Allen Baum wrote:
access to all custom state, requiring only the minimal amount of
hardware for the task.
- John Hauser
If I understand the above: you can write a 1 to the first bit, but you'llIt provides a convenient means for software to enable lower-privilege
always read back zero? What does that accomplish?
access to all custom state, requiring only the minimal amount of
hardware for the task.
- John Hauser
Jonathan Behrens <behrensj@...>
Why does all custom state need to be controlled with a single bit? Couldn't we just designate the upper 8 or 16 bits of each xstateenY register to be custom? Any software that wanted to disable all custom state would just clear all those bits, while software that wanted to enable all custom state would just write ones. (WARL would cause any unused bits to stay zero even after they were written with a value of one).
Jonathan
Allen Baum wrote:
> If I understand the above: you can write a 1 to the first bit, but you'll
> always read back zero? What does that accomplish?
It provides a convenient means for software to enable lower-privilege
access to all custom state, requiring only the minimal amount of
hardware for the task.
- John Hauser
Code that does environment swapping will need to use custom instructions to save custom state, so might as well use custom CSRs for the individual enable bits instead of taking up space in the standard *stateen.
The use case for the single bit is only for M-mode software that wants to enable/disable all custom state. No need to take up more than a single bit for that.
On Wed, Apr 21, 2021 at 9:41 AM Jonathan Behrens <behrensj@...> wrote:
Why does all custom state need to be controlled with a single bit? Couldn't we just designate the upper 8 or 16 bits of each xstateenY register to be custom? Any software that wanted to disable all custom state would just clear all those bits, while software that wanted to enable all custom state would just write ones. (WARL would cause any unused bits to stay zero even after they were written with a value of one).JonathanAllen Baum wrote:
> If I understand the above: you can write a 1 to the first bit, but you'll
> always read back zero? What does that accomplish?
It provides a convenient means for software to enable lower-privilege
access to all custom state, requiring only the minimal amount of
hardware for the task.
- John Hauser
John Hauser
Why does all custom state need to be controlled with a single bit? Couldn'tThe more bits we dedicate to custom use to ensure that we've got
we just designate the upper 8 or 16 bits of each xstateenY register to be
custom? Any software that wanted to disable all custom state would just
clear all those bits, while software that wanted to enable all custom state
would just write ones. (WARL would cause any unused bits to stay zero even
after they were written with a value of one).
enough for everyone, the quicker we use up each *stateen CSR, when we
can be pretty sure most of those custom bits will be unused in most
implementations. My suggestion is to allocate exactly two bits in
mstateen0, hstateen0, and stateen0, and let implementations allocate
all their specific custom bits in custom registers. Personally, I'm
entirely unbothered by those two bits having magic behavior, so long as
read-modify-write works as it should for the *stateen CSRs.
- John Hauser
John Hauser
Scott Johnson wrote:
unknown custom state? You said yourself earlier:
Like Allen, I'm not following the need for this complexity. Why not oneHow would that allow one to enable lower-privilege access to all
simple read/write bit that disables all custom state when 0? It would be
ANDed with any custom state enable CSR bits, much like misa.X=0 disables
all custom extensions.
unknown custom state? You said yourself earlier:
But there's also the use model of the M-mode software that doesn't do any- John Hauser
environment swapping and just wants to enable all state for the S-mode. It
would be nice if that didn't have to be aware of custom state.