fix(l1tlb_check): correct the check for only VS stage (#452)

As a legacy issue of supporting Sv48, the default level of do_s2xlate when mode=0 is incorrect. Also, for only VS stage case (onlyS1), it should not do_s2xlate at all. This patch fixes these problems.
This commit is contained in:
Xu, Zefan 2024-08-28 21:42:01 +08:00 committed by GitHub
parent 2aa82c8ce5
commit abfdcdf4df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 5 additions and 4 deletions

View File

@ -62,9 +62,9 @@ typedef union atpStruct {
uint64_t val;
} Satp, Hgatp;
#define noS2xlate 0
#define allStage 3
#define onlyStage1 1
#define onlyStage2 2
#define allStage 3
#define VPNiSHFT(i) (12 + 9 * (i))
#define GVPNi(addr, i, max) (((addr) >> (9 * (i) + 12)) & ((i == 3 || (i == 2 && max == 2)) ? 0x7ff : 0x1ff))
#define VPNi(vpn, i) (((vpn) >> (9 * (i))) & 0x1ff)

View File

@ -777,7 +777,7 @@ r_s2xlate do_s2xlate(Hgatp *hgatp, uint64_t gpaddr) {
r_s2xlate r_s2;
if (hgatp->mode == 0) {
r_s2.pte.ppn = gpaddr >> 12;
r_s2.level = 2;
r_s2.level = 0;
return r_s2;
}
int max_level = hgatp->mode == 8 ? 2 : 3;
@ -811,6 +811,7 @@ int Difftest::do_l1tlb_check() {
Hgatp *hgatp = (Hgatp *)&dut->l1tlb[i].hgatp;
uint8_t hasS2xlate = dut->l1tlb[i].s2xlate != noS2xlate;
uint8_t onlyS2 = dut->l1tlb[i].s2xlate == onlyStage2;
uint8_t hasAllStage = dut->l1tlb[i].s2xlate == allStage;
uint64_t pg_base = (hasS2xlate ? vsatp->ppn : satp->ppn) << 12;
int mode = hasS2xlate ? vsatp->mode : satp->mode;
int max_level = mode == 8 ? 2 : 3;
@ -821,7 +822,7 @@ int Difftest::do_l1tlb_check() {
} else {
for (difftest_level = max_level; difftest_level >= 0; difftest_level--) {
paddr = pg_base + VPNi(dut->l1tlb[i].vpn, difftest_level) * sizeof(uint64_t);
if (hasS2xlate) {
if (hasAllStage) {
r_s2 = do_s2xlate(hgatp, paddr);
uint64_t pg_mask = ((1ull << VPNiSHFT(r_s2.level)) - 1);
pg_base = (r_s2.pte.ppn << 12 & ~pg_mask) | (paddr & pg_mask & ~PAGE_MASK);
@ -837,7 +838,7 @@ int Difftest::do_l1tlb_check() {
uint64_t pg_mask = ((1ull << VPNiSHFT(difftest_level)) - 1);
pg_base = (pte.ppn << 12 & ~pg_mask) | (dut->l1tlb[i].vpn << 12 & pg_mask & ~PAGE_MASK);
}
if (hasS2xlate && pte.v) {
if (hasAllStage && pte.v) {
r_s2 = do_s2xlate(hgatp, pg_base);
pte = r_s2.pte;
difftest_level = r_s2.level;