Ayaz Akram has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/46279 )
Change subject: arch-riscv: add pma/pmp checks during page table walks
......................................................................
arch-riscv: add pma/pmp checks during page table walks
This change adds pma/pmp checks when page table entries
are accessed by hardware page table walker.
Change-Id: I161aad514bb7421e61a8c56af088c73969837704
---
M src/arch/riscv/pagetable_walker.cc
M src/arch/riscv/pmp.cc
2 files changed, 103 insertions(+), 64 deletions(-)
diff --git a/src/arch/riscv/pagetable_walker.cc
b/src/arch/riscv/pagetable_walker.cc
index d3c3905..54725e7 100644
--- a/src/arch/riscv/pagetable_walker.cc
+++ b/src/arch/riscv/pagetable_walker.cc
@@ -295,76 +295,99 @@
DPRINTF(PageTableWalker, "Got level%d PTE: %#x\n", level, pte);
- // step 2: TODO check PMA and PMP
+ // step 2:
+ // Performing PMA/PMP checks on physical address of PTE
- // step 3:
- if (!pte.v || (!pte.r && pte.w)) {
- doEndWalk = true;
- DPRINTF(PageTableWalker, "PTE invalid, raising PF\n");
- fault = pageFault(pte.v);
- }
- else {
- // step 4:
- if (pte.r || pte.x) {
- // step 5: leaf PTE
+ walker->pma->check(read->req);
+ fault = walker->pmp->pmpCheck(read->req, mode, pmode, tc);
+
+ if (fault == NoFault) {
+ // step 3:
+ if (!pte.v || (!pte.r && pte.w)) {
doEndWalk = true;
- fault = walker->tlb->checkPermissions(status, pmode,
- entry.vaddr, mode, pte);
-
- // step 6
- if (fault == NoFault) {
- if (level >= 1 && pte.ppn0 != 0) {
- DPRINTF(PageTableWalker,
- "PTE has misaligned PPN, raising PF\n");
- fault = pageFault(true);
- }
- else if (level == 2 && pte.ppn1 != 0) {
- DPRINTF(PageTableWalker,
- "PTE has misaligned PPN, raising PF\n");
- fault = pageFault(true);
- }
- }
-
- if (fault == NoFault) {
- // step 7
- if (!pte.a) {
- pte.a = 1;
- doWrite = true;
- }
- if (!pte.d && mode == TLB::Write) {
- pte.d = 1;
- doWrite = true;
- }
- // TODO check if this violates a PMA or PMP
-
- // step 8
- entry.logBytes = PageShift + (level * LEVEL_BITS);
- entry.paddr = pte.ppn;
- entry.vaddr &= ~((1 << entry.logBytes) - 1);
- entry.pte = pte;
- // put it non-writable into the TLB to detect writes and
redo
- // the page table walk in order to update the dirty flag.
- if (!pte.d && mode != TLB::Write)
- entry.pte.w = 0;
- doTLBInsert = true;
- }
+ DPRINTF(PageTableWalker, "PTE invalid, raising PF\n");
+ fault = pageFault(pte.v);
}
else {
- level--;
- if (level < 0) {
- DPRINTF(PageTableWalker, "No leaf PTE found, raising
PF\n");
+ // step 4:
+ if (pte.r || pte.x) {
+ // step 5: leaf PTE
doEndWalk = true;
- fault = pageFault(true);
+ fault = walker->tlb->checkPermissions(status, pmode,
+ entry.vaddr, mode,
pte);
+
+ // step 6
+ if (fault == NoFault) {
+ if (level >= 1 && pte.ppn0 != 0) {
+ DPRINTF(PageTableWalker,
+ "PTE has misaligned PPN, raising PF\n");
+ fault = pageFault(true);
+ }
+ else if (level == 2 && pte.ppn1 != 0) {
+ DPRINTF(PageTableWalker,
+ "PTE has misaligned PPN, raising PF\n");
+ fault = pageFault(true);
+ }
+ }
+
+ if (fault == NoFault) {
+ // step 7
+ if (!pte.a) {
+ pte.a = 1;
+ doWrite = true;
+ }
+ if (!pte.d && mode == TLB::Write) {
+ pte.d = 1;
+ doWrite = true;
+ }
+ // Performing PMA/PMP checks
+
+ if (doWrite) {
+
+ // this read will eventually become write
+ // if doWrite is True
+
+ walker->pma->check(read->req);
+
+ fault = walker->pmp->pmpCheck(read->req,
+ mode, pmode, tc);
+
+ }
+ // perform step 8 only if pmp checks pass
+ if (fault == NoFault) {
+
+ // step 8
+ entry.logBytes = PageShift + (level * LEVEL_BITS);
+ entry.paddr = pte.ppn;
+ entry.vaddr &= ~((1 << entry.logBytes) - 1);
+ entry.pte = pte;
+ // put it non-writable into the TLB to detect
writes and redo
+ // the page table walk in order to update the
dirty flag.
+ if (!pte.d && mode != TLB::Write)
+ entry.pte.w = 0;
+ doTLBInsert = true;
+ }
+ }
}
else {
- Addr shift = (PageShift + LEVEL_BITS * level);
- Addr idx = (entry.vaddr >> shift) & LEVEL_MASK;
- nextRead = (pte.ppn << PageShift) + (idx * sizeof(pte));
- nextState = Translate;
+ level--;
+ if (level < 0) {
+ DPRINTF(PageTableWalker, "No leaf PTE found, raising
PF\n");
+ doEndWalk = true;
+ fault = pageFault(true);
+ }
+ else {
+ Addr shift = (PageShift + LEVEL_BITS * level);
+ Addr idx = (entry.vaddr >> shift) & LEVEL_MASK;
+ nextRead = (pte.ppn << PageShift) + (idx *
sizeof(pte));
+ nextState = Translate;
+ }
}
}
}
-
+ else {
+ doEndWalk = true;
+ }
PacketPtr oldRead = read;
Request::Flags flags = oldRead->req->getFlags();
diff --git a/src/arch/riscv/pmp.cc b/src/arch/riscv/pmp.cc
index e9fcb7b..9fe0a2d 100644
--- a/src/arch/riscv/pmp.cc
+++ b/src/arch/riscv/pmp.cc
@@ -57,8 +57,14 @@
if (!shouldCheckPMP(pmode, mode, tc))
return NoFault;
- DPRINTF(PMP, "Checking pmp permissions for va: %#x , pa: %#x\n",
- req->getVaddr(), req->getPaddr());
+ if (req->hasVaddr()) {
+ DPRINTF(PMP, "Checking pmp permissions for va: %#x , pa: %#x\n",
+ req->getVaddr(), req->getPaddr());
+ }
+ else { // this access is corresponding to a page table walk
+ DPRINTF(PMP, "Checking pmp permissions for pa: %#x\n",
+ req->getPaddr());
+ }
// An access should be successful if there are
// no rules defined yet or we are in M mode (based
@@ -100,12 +106,22 @@
(PMP_EXEC & allowed_privs)) {
return NoFault;
} else {
- return createAddrfault(req->getVaddr(), mode);
+ if (req->hasVaddr()) {
+ return createAddrfault(req->getVaddr(), mode);
+ }
+ else {
+ return createAddrfault(req->getPaddr(), mode);
+ }
}
}
}
// if no entry matched and we are not in M mode return fault
- return createAddrfault(req->getVaddr(), mode);
+ if (req->hasVaddr()) {
+ return createAddrfault(req->getVaddr(), mode);
+ }
+ else {
+ return createAddrfault(req->getPaddr(), mode);
+ }
}
Fault
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/46279
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I161aad514bb7421e61a8c56af088c73969837704
Gerrit-Change-Number: 46279
Gerrit-PatchSet: 1
Gerrit-Owner: Ayaz Akram <yazak...@ucdavis.edu>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s