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

Reply via email to