From 792a22f3a90658be2aebd3bbba044527ad4ffe66 Mon Sep 17 00:00:00 2001
From: Oliver Ford <oliford@NervousEnergy.(none)>
Date: Sun, 20 Apr 2008 11:50:21 +0100
Subject: [PATCH] MMU L1 table merging output:
    Use part of memcmds.cpp:memDumpMMU() to output and scan L2 tables detected, hoping they're still in memory
---
 include/memcmds.h |    5 ++
 src/irq.cpp       |   41 +++++++++++++++----
 src/memcmds.cpp   |  116 +++++++++++++++++++++++++++++++---------------------
 3 files changed, 107 insertions(+), 55 deletions(-)
 create mode 100644 include/memcmds.h

diff --git a/include/memcmds.h b/include/memcmds.h
new file mode 100644
index 0000000..fd6a761
--- /dev/null
+++ b/include/memcmds.h
@@ -0,0 +1,5 @@
+
+
+//mmu dumping routine used by MMU merge
+int parseL1Entry(uint32 mb, uint32 l1d, uint32 pL1, 
+       uint32 l1only, uint32 showall, uint32 start, uint32 size );
diff --git a/src/irq.cpp b/src/irq.cpp
index 2d10ec5..e294518 100644
--- a/src/irq.cpp
+++ b/src/irq.cpp
@@ -19,6 +19,7 @@
 #include "lateload.h" // LATE_LOAD
 #include "winvectors.h" // findWinCEirq
 #include "irq.h"
+#include "memcmds.h"
 
 /*
  * Theory of operation:
@@ -518,6 +519,13 @@ static uint32 MMUMergeCount;
 REG_VAR_INT(testWirqAvail,"MMUMergeCount",MMUMergeCount,
             "Number of MMU level 1 table entries to watch. Making this too big (~> 512) may seriously slow/crash your system!")
 
+static uint32 MMUMergeTargetStart = 0x40000000; //pxa regs
+REG_VAR_INT(testWirqAvail,"MMUMergeTargetStart",MMUMergeTargetStart,
+            "Physical address to scan the merged table for on completion of wirq.")
+static uint32 MMUMergeTargetSize = 0x10000000; //the whole bank
+REG_VAR_INT(testWirqAvail,"MMUMergeTargetSize",MMUMergeTargetSize,
+            "Size of physical address range to scan the merged table for on completion of wirq")
+
 
 // setup
 int prepMMUMerge(struct irqData *data)
@@ -526,7 +534,12 @@ int prepMMUMerge(struct irqData *data)
 	data->mergeTableCount = MMUMergeCount;
 
 	if( !data->mergeTableCount ){
-		Output("MMU Table merging disabled");
+		Output("MMU table merging disabled");
+		return 0;
+	}
+	if( data->mergeTableCount > 4096){
+		Output("MMU table merging request too long (max = 4096)");
+		data->mergeTableCount = 0;
 		return 0;
 	}
 	
@@ -565,13 +578,25 @@ void __irq stopMMUMerge(struct irqData *data)
 void dumpMMUMerge(struct irqData *data){
 	if( !data->mergeTableCount ) return;
 
-	Output("MMU Merge table:");
-	Output("Index  ( vAddr  ) = Last entry  x Change count");
-	for(uint i=0;i < data->mergeTableCount;i++)
-		if(data->l1Changed[i]){
-			uint idx = data->mergeTableStart + i;
-			Output("%5i  (%08x) = %08x   x %i",idx,(idx << 20), data->l1Copy[i],data->l1Changed[i]);
-		}	
+	Output("Dumping MMU Merge table (last change mappings):");
+	Output("  Virtual | Physical | Description |  Flags");
+	Output("  address | address  |             |");
+	Output("----------+----------+-------------+------------------------");
+	//now search the entire table, l1s and l2s, for anything in the range we're interested in
+	for(uint i=0;i < data->mergeTableCount;i++){
+		if(!data->l1Changed[i])continue;
+
+		uint32 l1d = data->l1Copy[i]; 		
+		uint32 mb = data->mergeTableStart + i;
+		int count = parseL1Entry(mb,l1d,	//reuse part of the main 'MMU DUMP' code
+			0xffffffff,			//pL1=0xffffffff (no sense of previous here)
+			0,				//l1only = 0,
+			(MMUMergeTargetSize == 0),	//showall = 1 if no range given;
+			MMUMergeTargetStart, MMUMergeTargetSize);
+
+		if(count > 0)
+			Output("----- End L1 entry %5i (%08x) change count: %i  -----",mb,(mb << 20),data->l1Changed[i]);
+	}
 }
 
 // perform check and merge
diff --git a/src/memcmds.cpp b/src/memcmds.cpp
index 2168c49..6ae122a 100644
--- a/src/memcmds.cpp
+++ b/src/memcmds.cpp
@@ -13,7 +13,7 @@
 #include "cpu.h" // DEF_GETCPR
 #include "exceptions.h" // TRY_EXCEPTION_HANDLER
 #include "resource.h" // DLG_PROGRESS
-
+#include "memcmds.h"
 
 /****************************************************************
  * Reading values from memory
@@ -434,52 +434,9 @@ memDumpMMU(const char *tok, const char *args)
 
             // Read 1st level descriptor
             l1d = memPhysRead(mmu + mb * 4);
-            uint32 vaddr=mb<<20;
-            int type = l1d & MMU_L1_TYPE_MASK;
-            const struct pageinfo *pi = &L1PageInfo[type];
-            uint32 paddr = l1d & pi->mask;
-            char flagbuf[64];
-            __flags_l1(flagbuf, l1d & ~pi->mask);
-            switch (type) {
-            case MMU_L1_UNMAPPED:
-                if (showall && (l1d ^ pL1) & MMU_L1_TYPE_MASK)
-                    Output("%08x  |          | %11s |", vaddr, pi->name);
-                continue;
-            case MMU_L1_SECTION:
-                if (showall
-                    || RANGES_OVERLAP(start, size, paddr, 1<<pi->map_shift))
-                    Output("%08x  | %08x | %11s |%s"
-                           , vaddr, paddr, pi->name, flagbuf);
-                continue;
-            }
-            if (showall)
-                Output("%08x  |          | %11s |%s", vaddr, pi->name, flagbuf);
-
-            if (l1only)
-                continue;
-
-            // Walk the 2nd level descriptor table
-            uint l2_count = 1 << (20 - pi->map_shift);
-            uint32 pL2, l2d = 0xffffffff;
-            for (uint d = 0; d < l2_count; d++) {
-                pL2 = l2d;
-                l2d = memPhysRead(paddr + d * 4);
-                uint32 l2vaddr = vaddr + (d << pi->map_shift);
-                uint32 l2type = l2d & MMU_L2_TYPE_MASK;
-                const struct pageinfo *pi2 = &L2PageInfo[l2type];
-                uint32 l2paddr = l2d & pi2->mask;
-                __flags_l2(flagbuf, l2d & ~pi2->mask);
-
-                if (l2type == MMU_L2_UNMAPPED) {
-                    if (showall && (l2d ^ pL2) & MMU_L2_TYPE_MASK)
-                        Output(" %08x |          | %11s |", l2vaddr, pi2->name);
-                    continue;
-                }
-                if (showall
-                    || RANGES_OVERLAP(start, size, l2paddr, 1<<pi->map_shift))
-                    Output(" %08x | %08x | %11s |%s"
-                           , l2vaddr, l2paddr, pi2->name, flagbuf);
-            }
+
+            parseL1Entry(mb, l1d, pL1, l1only, showall, start, size);
+            
         }
     } CATCH_EXCEPTION_HANDLER {
         Output(C_ERROR "EXCEPTION CAUGHT AT MEGABYTE %d!", mb);
@@ -489,6 +446,71 @@ memDumpMMU(const char *tok, const char *args)
         Output("End of virtual address space");
     DoneProgress();
 }
+
+//mb=entry no, l1d=l1 descriptor (the entry), pL1 = previous L1
+//l1only=don't parse L2, start:size is what to look for (phys)
+int parseL1Entry(uint32 mb, uint32 l1d, uint32 pL1,
+                    uint32 l1only, uint32 showall, uint32 start, uint32 size ){
+    int linesOut = 0; //no. lines outputted
+    uint32 vaddr=mb<<20;
+    int type = l1d & MMU_L1_TYPE_MASK;
+    const struct pageinfo *pi = &L1PageInfo[type];
+    uint32 paddr = l1d & pi->mask;
+    char flagbuf[64];
+    __flags_l1(flagbuf, l1d & ~pi->mask);
+    switch (type) {
+    case MMU_L1_UNMAPPED:
+        if (showall && (l1d ^ pL1) & MMU_L1_TYPE_MASK){
+            Output("%08x  |          | %11s |", vaddr, pi->name);
+            linesOut++;
+        }
+        return linesOut;
+    case MMU_L1_SECTION:
+        if (showall
+                || RANGES_OVERLAP(start, size, paddr, 1<<pi->map_shift)){
+            Output("%08x  | %08x | %11s |%s"
+                , vaddr, paddr, pi->name, flagbuf);
+            linesOut++;
+        }
+        return linesOut;
+    }
+    if (showall){
+        Output("%08x  |          | %11s |%s", vaddr, pi->name, flagbuf);
+        linesOut++;
+    }
+
+    if (l1only)
+        return linesOut;
+
+    // Walk the 2nd level descriptor table
+    uint l2_count = 1 << (20 - pi->map_shift);
+    uint32 pL2, l2d = 0xffffffff;
+    for (uint d = 0; d < l2_count; d++) {
+        pL2 = l2d;
+        l2d = memPhysRead(paddr + d * 4);
+        uint32 l2vaddr = vaddr + (d << pi->map_shift);
+        uint32 l2type = l2d & MMU_L2_TYPE_MASK;
+        const struct pageinfo *pi2 = &L2PageInfo[l2type];
+        uint32 l2paddr = l2d & pi2->mask;
+        __flags_l2(flagbuf, l2d & ~pi2->mask);
+
+        if (l2type == MMU_L2_UNMAPPED) {
+            if (showall && (l2d ^ pL2) & MMU_L2_TYPE_MASK){
+                Output(" %08x |          | %11s |", l2vaddr, pi2->name);
+                linesOut++;
+            }
+            continue;
+        }
+        if (showall
+            || RANGES_OVERLAP(start, size, l2paddr, 1<<pi->map_shift)){
+            Output(" %08x | %08x | %11s |%s"
+                   , l2vaddr, l2paddr, pi2->name, flagbuf);
+            linesOut++;
+        }
+    }
+    return linesOut;
+}
+
 REG_DUMP(0, "MMU", memDumpMMU,
          "MMU [<1|2> [<start> [<size>]]] \n"
          "  Show virtual memory map (4Gb address space). One may give an\n"
-- 
1.5.2.5

