@@ -77,9 +77,8 @@ <h1 class="title">Inside Arm64 MMU: Unicorn Emulator vs Apache NuttX RTOS</h1>
7777< li > < a href ="#after-fixing-nuttx " title ="After Fixing NuttX "> 10 After Fixing NuttX</ a > < ul > </ ul > </ li >
7878< li > < a href ="#boot-flow " title ="Boot Flow "> 11 Boot Flow</ a > < ul > </ ul > </ li >
7979< li > < a href ="#todo " title ="TODO "> 12 TODO</ a > < ul > </ ul > </ li >
80- < li > < a href ="#todo-1 " title ="TODO "> 13 TODO</ a > < ul > </ ul > </ li >
81- < li > < a href ="#whats-next " title ="What’s Next "> 14 What’s Next</ a > < ul > </ ul > </ li >
82- < li > < a href ="#appendix-simplified-nuttx-for-qemu " title ="Appendix: Simplified NuttX for QEMU "> 15 Appendix: Simplified NuttX for QEMU</ a > < ul > </ ul > </ li > </ ul > </ nav > < p > 📝 < em > 9 Apr 2025</ em > </ p >
80+ < li > < a href ="#whats-next " title ="What’s Next "> 13 What’s Next</ a > < ul > </ ul > </ li >
81+ < li > < a href ="#appendix-simplified-nuttx-for-qemu " title ="Appendix: Simplified NuttX for QEMU "> 14 Appendix: Simplified NuttX for QEMU</ a > < ul > </ ul > </ li > </ ul > </ nav > < p > 📝 < em > 9 Apr 2025</ em > </ p >
8382< p > < img src ="https://lupyuen.org/images/unicorn3-title.png " alt ="TODO " /> </ p >
8483< p > < a href ="TODO "> < strong > Unicorn Emulator</ strong > </ a > has a fascinating demo of < a href ="TODO "> < strong > Arm64 MMU</ strong > </ a > < em > (Memory Management Unit)</ em > … Only < a href ="TODO "> < strong > 18 Lines of Arm64 Assembly</ strong > </ a > ! < em > (Pic above)</ em > </ p >
8584< p > This article deciphers the code inside < strong > Arm64 MMU Demo</ strong > , how it works. And why it’s super helpful for emulating < a href ="TODO "> < strong > Apache NuttX RTOS</ strong > </ a > compiled for Arm64 SBCs!</ p >
@@ -213,7 +212,7 @@ <h1 id="level-1-page-table"><a class="doc-anchor" href="#level-1-page-table">§<
213212// TTBR0_EL1 becomes ttb0_base
214213</ span > adr X0, ttb0_base < span class ="comment "> // Load ttb0_base into Register X0
215214</ span > msr TTBR0_EL1, X0 < span class ="comment "> // Write X0 into System Register TTBR0_EL1</ span > </ code > </ pre > </ div >
216- < p > This code will < strong > Map Virtual Address</ strong > to Physical Address, so that < em > 0x8000_0000</ em > (virtually) becomes < em > 0x4000_0000</ em > . We ’ll explain TCR and MAIR in the next section , but first…</ p >
215+ < p > This code will < strong > Map Virtual Address</ strong > to Physical Address, so that < em > 0x8000_0000</ em > (virtually) becomes < em > 0x4000_0000</ em > . Later we ’ll explain TCR and MAIR, but first…</ p >
217216< p > < em > What’s TTBR0_EL1? Why set it to ttb0_base?</ em > </ p >
218217< p > That’s the < a href ="TODO "> < strong > Level 1 Page Table</ strong > </ a > telling MMU our < strong > Virtual-to-Physical Mapping</ strong > . Suppose we’re mapping this…</ p >
219218< div > < table > < thead > < tr > < th style ="text-align: center "> Virtual Address</ th > < th style ="text-align: center "> Physical Address</ th > </ tr > </ thead > < tbody >
@@ -275,7 +274,7 @@ <h1 id="page-table-entry"><a class="doc-anchor" href="#page-table-entry">§</a>3
275274#define PTE_BLOCK_DESC_PXN (1ULL << 53) // Kernel Execute Never
276275#define PTE_BLOCK_DESC_UXN (1ULL << 54) // User Execute Never</ code > </ pre > </ div >
277276< p > < em > What if we read from 0x4000_0000 AFTER enabling MMU?</ em > </ p >
278- < p > We’ll see < a href ="TODO "> < em > 0xAA AA AA AA…</ em > </ a > . Yep the MMU can remap memory in fun interesting ways!</ p >
277+ < p > TODO: We’ll see < a href ="TODO "> < em > 0xAA AA AA AA…</ em > </ a > . Yep the MMU can remap memory in fun interesting ways!</ p >
279278< p > < em > Why map 0x0000_0000 to itself?</ em > </ p >
280279< p > TODO</ p >
281280< p > < em > Why Inner vs Outer Shareable? Something about “Severance”?</ em > </ p >
@@ -302,24 +301,7 @@ <h1 id="page-table-entry"><a class="doc-anchor" href="#page-table-entry">§</a>3
302301— For a stage 2 translation, translate an IPA to a PA for the stage 1 OA.</ code > </ pre > </ div >
303302< p > < em > Why are we doing Stage 1? Not Stage 2?</ em > </ p >
304303< p > < img src ="https://lupyuen.org/images/unicorn3-stage.png " alt ="TODO " /> </ p >
305- < p > TODO: PTE_BLOCK_DESC_AP_USER=1</ p >
306- < div class ="example-wrap "> < pre class ="language-text "> < code > [7] AP[2] Stage 1 Indirect permissions are disabled.
307- See Stage 1 data accesses using Direct permissions.
308-
309- [6] RES1 Stage 1 Indirect permissions are disabled and the translation regime supports a single privilege
310- level.
311- AP[1] Stage 1 Indirect permissions are disabled and the translation regime supports two privilege
312- levels.
313- See Stage 1 data accesses using Direct permissions.
314- PIIndex[0] Stage 1 Indirect permissions are enabled.
315- See Stage 1 Indirect permissions.</ code > </ pre > </ div >
316- < p > TODO: AP[2:1]</ p >
317- < div class ="example-wrap "> < pre class ="language-text "> < code > AP[2:1] Permissions
318- 00 PrivRead, PrivWrite
319- 01 PrivRead, PrivWrite, UnprivRead, UnprivWrite
320- 10 PrivRead
321- 11 PrivRead, UnprivRead
322- RPSZJJ</ code > </ pre > </ div >
304+ < p > TODO</ p >
323305< p > < img src ="https://lupyuen.org/images/unicorn3-table.png " alt ="TODO " /> </ p >
324306< p > TODO</ p >
325307< p > < img src ="https://lupyuen.org/images/unicorn3-access.png " alt ="TODO " /> </ p >
@@ -717,6 +699,26 @@ <h1 id="after-fixing-nuttx"><a class="doc-anchor" href="#after-fixing-nuttx">§<
717699< h1 id ="boot-flow "> < a class ="doc-anchor " href ="#boot-flow "> §</ a > 11 Boot Flow</ h1 >
718700< p > TODO</ p >
719701< h1 id ="todo "> < a class ="doc-anchor " href ="#todo "> §</ a > 12 TODO</ h1 >
702+ < p > TODO: PTE_BLOCK_DESC_AP_USER=1</ p >
703+ < div class ="example-wrap "> < pre class ="language-text "> < code > [7] AP[2] Stage 1 Indirect permissions are disabled.
704+ See Stage 1 data accesses using Direct permissions.
705+
706+ [6] RES1 Stage 1 Indirect permissions are disabled and the translation regime supports a single privilege
707+ level.
708+ AP[1] Stage 1 Indirect permissions are disabled and the translation regime supports two privilege
709+ levels.
710+ See Stage 1 data accesses using Direct permissions.
711+ PIIndex[0] Stage 1 Indirect permissions are enabled.
712+ See Stage 1 Indirect permissions.</ code > </ pre > </ div >
713+ < p > TODO: AP[2:1]</ p >
714+ < div class ="example-wrap "> < pre class ="language-text "> < code > AP[2:1] Permissions
715+ 00 PrivRead, PrivWrite
716+ 01 PrivRead, PrivWrite, UnprivRead, UnprivWrite
717+ 10 PrivRead
718+ 11 PrivRead, UnprivRead
719+ RPSZJJ</ code > </ pre > </ div >
720+ < p > TODO</ p >
721+
720722< div class ="example-wrap "> < pre class ="rust rust-example-rendered "> < code > < span class ="comment "> // Read data from physical address
721723</ span > ldr X0, =< span class ="number "> 0x40000000
722724</ span > ldr X1, [X0]
@@ -743,7 +745,8 @@ <h1 id="todo"><a class="doc-anchor" href="#todo">§</a>12 TODO</h1>
743745< span class ="comment "> // Read the same memory area through virtual address
744746</ span > ldr X0, =< span class ="number "> 0x80000000
745747</ span > ldr X2, [X0]</ code > </ pre > </ div >
746- < h1 id ="todo-1 "> < a class ="doc-anchor " href ="#todo-1 "> §</ a > 13 TODO</ h1 > < div class ="example-wrap "> < pre class ="language-bash "> < code > ## Level 1 Page Table with 4 Page Table Entries
748+ < p > TODO</ p >
749+ < div class ="example-wrap "> < pre class ="language-bash "> < code > ## Level 1 Page Table with 4 Page Table Entries
747750## Entry #0
748751Page Table Entry @ 0x1000:
749752 0x0000_0741
@@ -1291,7 +1294,7 @@ <h1 id="todo-1"><a class="doc-anchor" href="#todo-1">§</a>13 TODO</h1><div clas
12911294call_graph: tasklist_initialize --> gic_validate_redist_version
12921295call_graph: click tasklist_initialize href "https://github.com/apache/nuttx/blob/master/sched/init/nx_start.c#L313" "sched/init/nx_start.c " _blank
12931296hook_block: address=0x40281514, size=32, arm64_syscall, arch/arm64/src/common/arm64_syscall.c:299:32
1294- call_graph: gic_validate_redist_version --> arm64_syscall</ code > </ pre > </ div > < h1 id ="whats-next "> < a class ="doc-anchor " href ="#whats-next "> §</ a > 14 What’s Next</ h1 >
1297+ call_graph: gic_validate_redist_version --> arm64_syscall</ code > </ pre > </ div > < h1 id ="whats-next "> < a class ="doc-anchor " href ="#whats-next "> §</ a > 13 What’s Next</ h1 >
12951298< p > Special Thanks to < a href ="https://lupyuen.org/articles/sponsor "> < strong > My Sponsors</ strong > </ a > for supporting my writing. Your support means so much to me 🙏</ p >
12961299< ul >
12971300< li >
@@ -1321,7 +1324,7 @@ <h1 id="todo-1"><a class="doc-anchor" href="#todo-1">§</a>13 TODO</h1><div clas
13211324</ ul >
13221325< p > < em > Got a question, comment or suggestion? Create an Issue or submit a Pull Request here…</ em > </ p >
13231326< p > < a href ="https://codeberg.org/lupyuen/lupyuen.org/src/branch/master/src/unicorn3.md "> < strong > lupyuen.org/src/unicorn3.md</ strong > </ a > </ p >
1324- < h1 id ="appendix-simplified-nuttx-for-qemu "> < a class ="doc-anchor " href ="#appendix-simplified-nuttx-for-qemu "> §</ a > 15 Appendix: Simplified NuttX for QEMU</ h1 >
1327+ < h1 id ="appendix-simplified-nuttx-for-qemu "> < a class ="doc-anchor " href ="#appendix-simplified-nuttx-for-qemu "> §</ a > 14 Appendix: Simplified NuttX for QEMU</ h1 >
13251328< p > TODO: Simpler for debugging</ p >
13261329< p > (Could one of these changes, contribute to Unicorn Non-Crashing? It’s possible)</ p >
13271330< p > Why did we simplify? So we can be as close to MMU Demo as possible. And isolate the crashing problem.</ p >
0 commit comments