Skip to content

Commit

Permalink
Merge pull request #23 from riscv-software-src/dhower/profiles
Browse files Browse the repository at this point in the history
Profiles schema and RVA20/22 implementations
  • Loading branch information
dhower-qc authored Sep 16, 2024
2 parents 45fdc6e + 1ab64e7 commit b3756c1
Show file tree
Hide file tree
Showing 264 changed files with 9,450 additions and 3,537 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
gen
node_modules
_site
images
89 changes: 50 additions & 39 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,53 +62,64 @@ task :clean do
FileUtils.rm_rf $root / ".stamps"
end

desc "Validate the arch docs"
task validate: "gen:arch" do
validator = Validator.instance
puts "Checking arch files against schema.."
arch_files = Dir.glob("#{$root}/arch/**/*.yaml")
progressbar = ProgressBar.create(total: arch_files.size)
arch_files.each do |f|
progressbar.increment
validator.validate(f)
end
puts "All files validate against their schema"

puts "Type checking IDL code..."
arch_def = arch_def_for("_")
progressbar = ProgressBar.create(title: "Instructions", total: arch_def.instructions.size)
arch_def.instructions.each do |inst|
progressbar.increment
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_32, 32) if inst.rv32?
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_64, 64) if inst.rv64?
# also need to check for an RV64 machine running with effective XLEN of 32
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_64, 32) if inst.rv64? && inst.rv32?
namespace :validate do
task schema: "gen:arch" do
validator = Validator.instance
puts "Checking arch files against schema.."
arch_files = Dir.glob("#{$root}/arch/**/*.yaml")
progressbar = ProgressBar.create(total: arch_files.size)
arch_files.each do |f|
progressbar.increment
validator.validate(f)
end
puts "All files validate against their schema"
end
progressbar = ProgressBar.create(title: "CSRs", total: arch_def.csrs.size)
arch_def.csrs.each do |csr|
progressbar.increment
if csr.has_custom_sw_read?
csr.type_checked_sw_read_ast(arch_def.sym_table_32) if csr.defined_in_base32?
csr.type_checked_sw_read_ast(arch_def.sym_table_64) if csr.defined_in_base64?
task idl: "gen:arch" do
puts "Type checking IDL code..."
arch_def = arch_def_for("_")
progressbar = ProgressBar.create(title: "Instructions", total: arch_def.instructions.size)
arch_def.instructions.each do |inst|
progressbar.increment
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_32, 32) if inst.rv32?
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_64, 64) if inst.rv64?
# also need to check for an RV64 machine running with effective XLEN of 32
inst.type_checked_operation_ast(arch_def.idl_compiler, arch_def.sym_table_64, 32) if inst.rv64? && inst.rv32?
end
csr.fields.each do |field|
unless field.type_ast(arch_def.idl_compiler).nil?
field.type_checked_type_ast(arch_def.sym_table_32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_type_ast(arch_def.sym_table_64) if csr.defined_in_base64? && field.defined_in_base64?
progressbar = ProgressBar.create(title: "CSRs", total: arch_def.csrs.size)
arch_def.csrs.each do |csr|
progressbar.increment
if csr.has_custom_sw_read?
csr.type_checked_sw_read_ast(arch_def.sym_table_32) if csr.defined_in_base32?
csr.type_checked_sw_read_ast(arch_def.sym_table_64) if csr.defined_in_base64?
end
unless field.reset_value_ast(arch_def.idl_compiler).nil?
field.type_checked_reset_value_ast(arch_def.sym_table_32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_reset_value_ast(arch_def.sym_table_64) if csr.defined_in_base64? && field.defined_in_base64?
end
unless field.sw_write_ast(arch_def.idl_compiler).nil?
field.type_checked_sw_write_ast(arch_def.sym_table_32, 32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_sw_write_ast(arch_def.sym_table_64, 64) if csr.defined_in_base64? && field.defined_in_base64?
csr.fields.each do |field|
unless field.type_ast(arch_def.idl_compiler).nil?
field.type_checked_type_ast(arch_def.sym_table_32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_type_ast(arch_def.sym_table_64) if csr.defined_in_base64? && field.defined_in_base64?
end
unless field.reset_value_ast(arch_def.idl_compiler).nil?
field.type_checked_reset_value_ast(arch_def.sym_table_32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_reset_value_ast(arch_def.sym_table_64) if csr.defined_in_base64? && field.defined_in_base64?
end
unless field.sw_write_ast(arch_def.idl_compiler).nil?
field.type_checked_sw_write_ast(arch_def.sym_table_32, 32) if csr.defined_in_base32? && field.defined_in_base32?
field.type_checked_sw_write_ast(arch_def.sym_table_64, 64) if csr.defined_in_base64? && field.defined_in_base64?
end
end
end
progressbar = ProgressBar.create(title: "Functions", total: arch_def.functions.size)
arch_def.functions.each do |func|
progressbar.increment
func.type_check_body(arch_def.sym_table_32)
func.type_check_body(arch_def.sym_table_64)
end
puts "All IDL passed type checking"
end
puts "All IDL passed type checking"
end

desc "Validate the arch docs"
task validate: ["validate:schema", "validate:idl"]

def insert_warning(str, from)
# insert a warning on the second line
lines = str.lines
Expand Down
284 changes: 284 additions & 0 deletions arch/csr/H/henvcfg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
# yaml-language-server: $schema=../../../schemas/csr_schema.json

henvcfg:
address: 0x60A
long_name: Hypervisor Environment Configuration
description: |
The henvcfg CSR is a 64-bit read/write register that controls certain characteristics of the
execution environment when virtualization mode V=1.
If bit `henvcfg.FIOM` (Fence of I/O implies Memory) is set to one in henvcfg, `fence`
instructions executed when V=1 are modified so the requirement to order accesses to device I/O
implies also the requirement to order main memory accesses.
<<henvcfg-FIOM>> details the modified interpretation of FENCE instruction bits PI, PO, SI, and SO when
FIOM=1 and V=1.
Similarly, when `henvcfg.FIOM`=1 and V=1, if an atomic instruction that accesses a
region ordered as device I/O has its _aq_ and/or _rl_ bit set, then that
instruction is ordered as though it accesses both device I/O and memory.
[[henvcfg-FIOM]]
.Modified interpretation of FENCE predecessor and successor sets when FIOM=1 and virtualization mode V=1.
[%autowidth,float="center",align="center",cols="^,<",options="header"]
|===
|Instruction bit |Meaning when set
|PI +
PO
|Predecessor device input and memory reads (PR implied) +
Predecessor device output and memory writes (PW implied)
|SI +
SO
|Successor device input and memory reads (SR implied) +
Successor device output and memory writes (SW implied)
|===
The PBMTE bit controls whether the Svpbmt extension is available for use
in VS-stage address translation. When PBMTE=1, Svpbmt is available for
VS-stage address translation. When PBMTE=0, the implementation behaves
as though Svpbmt were not implemented for VS-stage address translation.
If Svpbmt is not implemented, PBMTE is read-only zero.
If the Svadu extension is implemented, the ADUE bit controls whether hardware
updating of PTE A/D bits is enabled for VS-stage address translation.
When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage
address translation, and the implementation behaves as though the Svade
extension were not implemented for VS-mode address translation.
When ADUE=0, the implementation behaves as though Svade were implemented for
VS-stage address translation.
If Svadu is not implemented, ADUE is read-only zero.
The definition of the STCE field is furnished by the Sstc extension.
The definition of the CBZE field is furnished by the Zicboz extension.
The definitions of the CBCFE and CBIE fields are furnished by the Zicbom extension.
The definition of the PMM field will be furnished by the forthcoming
Ssnpm extension. Its allocation within `henvcfg` may change prior to the
ratification of that extension.
The Zicfilp extension adds the `LPE` field in `henvcfg`. When the `LPE` field
is set to 1, the Zicfilp extension is enabled in VS-mode. When the `LPE` field
is 0, the Zicfilp extension is not enabled in VS-mode and the following rules
apply to VS-mode:
* The hart does not update the `ELP` state; it remains as `NO_LP_EXPECTED`.
* The `LPAD` instruction operates as a no-op.
The Zicfiss extension adds the `SSE` field in `henvcfg`. If the `SSE` field is
set to 1, the Zicfiss extension is activated in VS-mode. When the `SSE` field is
0, the Zicfiss extension remains inactive in VS-mode, and the following rules
apply when `V=1`:
* 32-bit Zicfiss instructions will revert to their behavior as defined by Zimop.
* 16-bit Zicfiss instructions will revert to their behavior as defined by Zcmop.
* The `pte.xwr=010b` encoding in VS-stage page tables becomes reserved.
* The `senvcfg.SSE` field will read as zero and is read-only.
* When `menvcfg.SSE` is one, `SSAMOSWAP.W/D` raises a virtual instruction
exception.
The Ssdbltrp extension adds the double-trap-enable (`DTE`) field in `henvcfg`.
When `henvcfg.DTE` is zero, the implementation behaves as though Ssdbltrp is not
implemented for VS-mode and the `vsstatus.SDT` bit is read-only zero.
When XLEN=32, `henvcfgh` is a
32-bit read/write register that aliases bits 63:32
of `henvcfg`. Register `henvcfgh` does not exist when
XLEN=64.
priv_mode: S
length: 64
definedBy: H
fields:
STCE:
location: 63
description: |
*STimecmp Enable*
When set, `stimecmp` is operational in VS-mode if `menvcfg.STCE` is also set.
When `menvcfg.STCE` is zero:
* `henvcfg.STCE` reads-as-zero
* `vstimecmp` access raises an `IllegalInstruction` exception.
* `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented.
* VS-mode timer interrupts will not be generated
When `menvcfg.STCE` is one and `henvcfg.STCE` is zero:
* Accessing `stimecmp` in VS-mode or VU-mode (really `vstimecmp`) raises a VirtualInterrupt exception
* `hip.VSTIP` reverts to its defined behavior as if Sstc is not implemented.
* VS-mode timer interrupts will not be generated
definedBy: Sstc
type(): |
return (implemented?(ExtensionName::Sstc)) ? CsrFieldType::RO : CsrFieldType::RW;
reset_value(): |
return (implemented?(ExtensionName::Sstc)) ? UNDEFINED_LEGAL : 0;
PBMTE:
location: 62
description: |
*Page Based Memory Type Enable*
The PBMTE bit controls whether the `Svpbmt` extension is available for use in VS-stage
address translation.
When PBMTE=1, Svpbmt is available for VS-stage address translation.
When PBMTE=0, the implementation behaves as though `Svpbmt` were not implemented for
VS-stage address translation.
If `Svpbmt` is not implemented, PBMTE is read-only zero.
`henvcfg.PBMTE` is read-as-zero if `menvcfg.PBMTE` is zero.
If the setting of the PBMTE bit in `menvcfg` is changed, an `hfence.gvma` instruction with
_rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation
of G-stage and VS-stage PTEs' PBMT fields.
By contrast, if the PBMTE bit in `henvcfg` is changed, executing an `hfence.vvma` with
_rs1_=_x0_ and _rs2_=_x0_ suffices to synchronize with respect to the altered interpretation
of VS-stage PTEs' PBMT fields for the currently active VMID.
[NOTE]
--
No mechanism is provided to atomically change `vsatp` and `hgatp` together.
Hence, to prevent speculative execution causing one guest's VS-stage translations to be
cached under another guest's VMID, world-switch code should zero `vsatp`, then swap `hgatp`,
then finally write the new `vsatp` value.
Similarly, if `henvcfg.PBMTE` need be world-switched, it should be switched after zeroing
`vsatp` but before writing the new `vsatp` value, obviating the need to execute an
`hfence.vvma` instruction.
--
definedBy: Svpbmt
type(): |
return (implemented?(ExtensionName::Svpbmt)) ? CsrFieldType::RO : CsrFieldType::RW;
reset_value(): |
return (implemented?(ExtensionName::Svpbmt)) ? UNDEFINED_LEGAL : 0;
ADUE:
location: 61
description: |
If the `Svadu` extension is implemented, the ADUE bit controls whether hardware updating of
PTE A/D bits is enabled for VS-stage address translation.
When ADUE=1, hardware updating of PTE A/D bits is enabled during VS-stage address
translation, and the implementation behaves as though the Svade extension were not
implemented for VS-mode address translation.
When ADUE=0, the implementation behaves as though Svade were implemented for VS-stage
address translation.
If Svadu is not implemented, ADUE is read-only zero.
Furthermore, for implementations with the hypervisor extension, henvcfg.ADUE is read-only
zero if menvcfg.ADUE is zero.
definedBy: Svadu
type(): |
return (implemented?(ExtensionName::Svadu)) ? CsrFieldType::RO : CsrFieldType::RW;
reset_value(): |
return (implemented?(ExtensionName::Svadu)) ? UNDEFINED_LEGAL : 0;
CBZE:
location: 7
description: |
*Cache Block Zero instruction Enable*
Enables the execution of the cache block zero instruction, `CBO.ZERO`,
<% if ext?(:S) %>
in S-mode
<% elsif ext?(:U) %>
in U-mode
<% end %>.
* `0`: The instruction raises an illegal instruction or virtual instruction exception
* `1`: The instruction is executed
definedBy: Zicboz
type: RW
reset_value: UNDEFINED_LEGAL
CBCFE:
location: 6
description: |
*Cache Block Clean and Flush instruction Enable*
Enables the execution of the cache block clean instruction, `CBO.CLEAN`, and the
cache block flush instruction, `CBO.FLUSH`,
<% if ext?(:S) %>
in S-mode
<% elsif ext?(:U) %>
in U-mode
<% end %>.
* `0`: The instruction raises an illegal instruction or virtual instruction exception
* `1`: The instruction is executed
definedBy: Zicbom
type: RW
reset_value: UNDEFINED_LEGAL
CBIE:
location: 5-4
description: |
*Cache Block Invalidate instruction Enable*
Enables the execution of the cache block invalidate instruction, `CBO.INVAL`,
<% if ext?(:S) %>
in S-mode
<% elsif ext?(:U) %>
in U-mode
<% end %>.
* `00`: The instruction raises an illegal instruction or virtual instruction exception
* `01`: The instruction is executed and performs a flush operation
* `10`: _Reserved_
* `11`: The instruction is executed and performs an invalidate operation
definedBy: Zicbom
type: RW-R
sw_write(csr_value): |
if (csr_value.CBIE == 0 || csr_value.CBIE == 1 || csr_value.CBIE == 3) {
return csr_value.CBIE;
} else {
return CSR[menvcfg].CBIE;
}
reset_value: UNDEFINED_LEGAL
FIOM:
location: 0
description: |
*Fence of I/O implies Memory*
When `menvcfg.FIOM` is set,
FENCE instructions ordering I/O regions also implicitly order memory regions when executed
in any mode less privileged than M-mode.
[separator="!",%autowidth,float="center",align="center",cols="^,<",options="header"]
!===
!Instruction bit !Meaning when set
!PI +
PO
!Predecessor device input and memory reads (PR implied) +
Predecessor device output and memory writes (PW implied)
!SI +
SO
!Successor device input and memory reads (SR implied) +
Successor device output and memory writes (SW implied)
!===
Similarly, for modes less privileged than M when FIOM=1, if an atomic
instruction that accesses a region ordered as device I/O has its _aq_
and/or _rl_ bit set, then that instruction is ordered as though it
accesses both device I/O and memory.
type: RW
reset_value: UNDEFINED_LEGAL
sw_read(): |
Bits<64> value = $bits(CSR[henvcfg]);
if (implemented?(ExtensionName::Sstc) && CSR[menvcfg].STCE == 0) {
# henvcfg.STCE must read-as-zero
value = value & ~(1 << 63);
}
if (implemented?(ExtensionName::Svpbmt) && CSR[menvcfg].PBMTE == 0) {
# henvcfg.PBMTE must read-as-zero
value = value & ~(1 << 62);
}
if (implemented?(ExtensionName::Svadu) && CSR[menvcfg].ADUE == 0) {
# henvcfg.ADUE must read-as-zero
value = value & ~(1 << 61);
}
return value;
Loading

0 comments on commit b3756c1

Please sign in to comment.