Previously cache block size had to be initialized via special
set_chache_blocksz setter function and was uninitialized if you didn't
call it. In this commit I move initialization of the block size to the
mmu_t's constructor. The configuration of this member goes through cfg_t
struct.
These are the changes:
- Zvkg (vghsh.vv, vgmul.vv)
- vl must be a multiple of EGS=4. (spec p.13)
- Check alignment of vd, vs1, vs2 with lmul
- Zvksh (vsm3c.vi, vsm3me.vv)
- vstart, vl must be multiple of EGS=4 (spec p.17)
- Check alignment of vd, vs1, vs2 with lmul
- Zvksed (vsm4k.[vi,vs,vv])
- vstart, vl must be multiple of EGS=4 (spec p.16)
- Check alignment of vd, vs1, vs2 with lmul
- For vsm4r.vs, check overlap between vs2 and vd (spec p.7)
- Zvbb (vwsll.[vv,vx,vi])
- Check alignment of vd, vs1, vs2 with lmul (for widening instructions)
- Check overlap between vs2 and vd
- Zvkned
- vstart, vl must be multiple of EGS=4 (spec p.14)
- Check alignment of vd, vs1, vs2 with lmul
- For vaes*.vs, check overlap between vs2 and vd (spec p.7)
- Zvknh
- Check alignment of vd, vs1, vs2 with lmul
Prior to this commit when calling processor_t's constructor xlen was
explicitly initialized with zero (hence get_xlen and get_const_xlen both
returned zero). Later the value of xlen was being corrected in the first reset
call. Which made it impossible to use xlen on custom extension registration
(before first reset). This patch initializes xlen with the correct value
from the start.
An interrupt is pending at VS level if and only if vstopi is not 0.
The modification is backward compatible because hvictl is implicitly 0
without AIA.
If hvictl.IPRIOM=1, vstopi.IPRIO indicates the priority of the
highest-priority interrupt if vstopi is nonzero.
For a supervisor external interrupt, vstopi.IPRIO is hvictl.IPRIO if
hvictl.IID=9 and hvictl.IPRIO!=0; otherwise, vstopi.IPRIO is 255.
For other interrupts under hvictl.VTI=1, vstopi.IPRIO is 0 if
hvictl.iprio=0 and hvictl.dpr=0; vstopi.IPRIO is hvictl.iprio if
hvictl.iprio!=0; vstopi.IPRIO is 255 if hvictl.iprio=0 and hvictl.dpr=1.
For other interrupts under hvictl.VTI=0, vstopi.IPRIO is 255 (lowest
priority). That is because other interrupts have the same priority value
0 due to hviprio1=hviprio2=0. In other words, the hvictl.IPRIO of other
interrupts is determined by the default priority, which is lower than
the SEI with the lowest priority value 255.
If hvictl.VTI=1, there are two interrupt candidates for VS level. One is
a supervisor extenal interrupt if bit 9 is one in both vsip and vsie.
The other one is specified by hvictl.IID if hvictl.IID is not 9. The
hvictl.DPR determines the priority order between two interrupts.
If hvictl.VTI=0, vstopi returns information about the highest-priority
pending-and-enabled major interrupt indicated by vsip and vsie.
If hvictl.VTI=1, vstopi return information about a supervisor extenal
interrupt if bit 9 is one in both vsip and vsie.
The pair hvictl.IID=9 and hvictl.IPRIO=0 generally represent no
interrupt in hvictl.
While zeroing also signifies no interrupt, this intermediate commit in
the AIA series aims to explicitly state the absence of an interrupt
condition to prevent confusion in subsequent intermediate commits.
AIA introduces the concept of inaccessible CSR, where accessing from
M-mode or HS-mode raises an illegal instruction exception, but doing so
from VS-mode or VU-mode raises a virtual instruction exception.
Without IMSIC, mtopei and stopei do not exist. In contrast, vstopei is
an inaccessible CSR even without IMSIC, i.e., exits and is HS-qualified.
In summary, accessing stopei from M-mode or HS-mode (v=0) raises illegal
instruction, and accessing stopei (actually vstopei) from VS-mode or
VU-mode (v=1) raises virtual instruction.
The AIA spec specifies the sie[n] behavior conditionally:
(1) When mideleg[n]=0 and mvien[n]=0, sie[n] is read-only 0.
(2) When mideleg[n]=0 and mvien[n]=1, sie[n] is writable.
(3) When mideleg[n]=1, sie[n] is an alias of mie[n].
Points (1) and (3) describe the same behavior without AIA. This commit
provides the behavior of point (2).
The AIA spec specifies the sip[n] behavior conditionally:
(1) When mideleg[n]=0 and mvien[n]=0, sip[n] is read-only 0.
(2) When mideleg[n]=0 and mvien[n]=1, sip[n] is an alias of mvip[n].
(3) When mideleg[n]=1, sip[n] is an alias of mip[n].
Points (1) and (3) describe the same behavior without AIA. This commit
provides the behavior of point (2).
When mvien.SEIP=0, mip.SEIP includes the software-writable bit, i.e.,
mvip.SEIP.
When mvien.SEIP=1, mip.SEIP is read-only and does not include the value
of mvip.SEIP.
The mip.SEIP is the logical-OR of a software-writable bit and signal
from an external interrupt controller (e.g., APLIC or IMSIC). The AIA
spec lets the software-writable bit be the mvip.SEIP.
This commit follows the concept that the mvip.SEIP is a sub-component of
mip.SEIP. Writing mip.SEIP actually updates the software-writable bit,
i.e., mvip.SEIP. Reading mip.SEIP returns a value consisting of the
software-writable bit, i.e., mvip.SEIP. The SEIP bit in mip::val becomes
a placeholder for the external interrupt controller.
Accessing mvip.SEIP reads from and writes to mvip.SEIP normally.
Reference: https://github.com/riscv/riscv-aia/issues/64
When mvien.SSIP=0, mvip.SSIP is an alias of mip.SSIP. Accessing
mvip.SSIP reads from and writes to mip.SSIP.
When mvien.SSIP=1, mvip.SSIP is a separate writable bit independent of
mip.SSIP. Accessing mvip.SSIP reads from and writes to the separate,
writable, independent bit normally.