{"id":27059940,"url":"https://github.com/lupyuen/nuttx-arm64-emulator","last_synced_at":"2025-04-05T13:17:01.406Z","repository":{"id":79682088,"uuid":"603431675","full_name":"lupyuen/nuttx-arm64-emulator","owner":"lupyuen","description":"Emulate Apache NuttX RTOS for Arm64 with Unicorn Emulator (Avaota-A1 SBC)","archived":false,"fork":false,"pushed_at":"2025-03-31T02:20:29.000Z","size":147782,"stargazers_count":40,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T02:26:01.344Z","etag":null,"topics":["allwinner-t527","arm64","assembly","avaota-a1","emulator","nuttx","pinephone","qemu","rust","unicorn-emulator"],"latest_commit_sha":null,"homepage":"https://lupyuen.org/articles/unicorn3.html","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lupyuen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["lupyuen"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["paypal.me/lupyuen"]}},"created_at":"2023-02-18T13:49:03.000Z","updated_at":"2025-03-31T01:29:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"be6dcaef-ca91-482b-83e9-b8c105cf7cdf","html_url":"https://github.com/lupyuen/nuttx-arm64-emulator","commit_stats":null,"previous_names":["lupyuen/nuttx-arm64-emulator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fnuttx-arm64-emulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fnuttx-arm64-emulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fnuttx-arm64-emulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lupyuen%2Fnuttx-arm64-emulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lupyuen","download_url":"https://codeload.github.com/lupyuen/nuttx-arm64-emulator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289381,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allwinner-t527","arm64","assembly","avaota-a1","emulator","nuttx","pinephone","qemu","rust","unicorn-emulator"],"created_at":"2025-04-05T13:17:00.901Z","updated_at":"2025-04-05T13:17:01.375Z","avatar_url":"https://github.com/lupyuen.png","language":"Assembly","funding_links":["https://github.com/sponsors/lupyuen","paypal.me/lupyuen"],"categories":[],"sub_categories":[],"readme":"# Unicorn Emulator for Apache NuttX RTOS on Avaota-A1 Arm64 SBC\n\nSee https://github.com/lupyuen/nuttx-arm64-emulator/tree/avaota\n\n# Unicorn Emulator for Apache NuttX RTOS on QEMU Arm64\n\nSee https://github.com/lupyuen/nuttx-arm64-emulator/tree/qemu\n\n# Emulate PinePhone with Unicorn Emulator\n\nRead the articles...\n\n-   [\"Inside Arm64 MMU: Unicorn Emulator vs Apache NuttX RTOS\"](https://lupyuen.org/articles/unicorn3.html)\n\n-   [\"(Possibly) Emulate PinePhone with Unicorn Emulator\"](https://lupyuen.org/articles/unicorn.html)\n\n-   [\"(Clickable) Call Graph for Apache NuttX Real-Time Operating System\"](https://lupyuen.org/articles/unicorn2.html)\n\nWe're porting a new operating system ([Apache NuttX RTOS](https://lupyuen.github.io/articles/what)) to [Pine64 PinePhone](https://wiki.pine64.org/index.php/PinePhone). And I wondered...\n\n_To make PinePhone testing easier..._\n\n_Can we emulate Arm64 PinePhone with [Unicorn Emulator](https://www.unicorn-engine.org/)?_\n\nLet's find out! We'll call the [Unicorn Emulator](https://www.unicorn-engine.org/) in Rust (instead of C).\n\n(Because I'm too old to write meticulous C... But I'm OK to get nagged by Rust Compiler if I miss something!)\n\nWe begin by emulating simple Arm64 Machine Code...\n\n# Emulate Arm64 Machine Code\n\n![Emulate Arm64 Machine Code](https://lupyuen.github.io/images/unicorn-code.png)\n\nSuppose we wish to emulate some Arm64 Machine Code...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/bc5643dea66c70f57a150955a12884f695acf1a4/src/main.rs#L7-L8\n\nHere's our Rust Program that calls Unicorn Emulator to emulate the Arm64 Machine Code...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/bc5643dea66c70f57a150955a12884f695acf1a4/src/main.rs#L1-L55\n\nWe add `unicorn-engine` to [Cargo.toml](Cargo.toml)...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/bc5643dea66c70f57a150955a12884f695acf1a4/Cargo.toml#L8-L9\n\nAnd we run our Rust Program...\n\n```text\n→ cargo run --verbose\n  Fresh cc v1.0.79\n  Fresh cmake v0.1.49\n  Fresh pkg-config v0.3.26\n  Fresh bitflags v1.3.2\n  Fresh libc v0.2.139\n  Fresh unicorn-engine v2.0.1\n  Fresh nuttx-arm64-emulator v0.1.0\nFinished dev [unoptimized + debuginfo] target(s) in 0.08s\n  Running `target/debug/nuttx-arm64-emulator`\n```\n\nOur Rust Program works OK for emulating Arm64 Memory and Arm64 Registers.\n\nLet's talk about Arm64 Memory-Mapped Input / Output...\n\n# Memory Access Hook for Arm64 Emulation\n\n![Memory Access Hook for Arm64 Emulation](https://lupyuen.github.io/images/unicorn-code2.png)\n\n_How will we emulate Arm64 Memory-Mapped Input / Output?_\n\nUnicorn Emulator lets us attach hooks to Emulate Memory Access.\n\nHere's a Hook Function for Memory Access...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L83-L95\n\nOur Hook Function prints all Read / Write Access to Emulated Arm64 Memory.\n\n[(Return value is unused)](https://github.com/unicorn-engine/unicorn/blob/dev/docs/FAQ.md#i-cant-recover-from-unmapped-readwrite-even-i-return-true-in-the-hook-why)\n\nThis is how we attach the Hook Function to the Unicorn Emulator...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L59-L74\n\nWhen we run our Rust Program, we see the Read and Write Memory Accesses made by our [Emulated Arm64 Code](https://github.com/lupyuen/nuttx-arm64-emulator/blob/bc5643dea66c70f57a150955a12884f695acf1a4/src/main.rs#L7-L8)...\n\n```text\nhook_memory: \n  mem_type=WRITE, \n  address=0x10008, \n  size=4, \n  value=0x12345678\n\nhook_memory: \n  mem_type=READ, \n  address=0x10008, \n  size=1, \n  value=0x0\n```\n\nThis Memory Access Hook Function will be helpful when we emulate Memory-Mapped Input/Output on PinePhone.\n\n(Like for the Allwinner A64 UART Controller)\n\nUnicorn Emulator allows Code Execution Hooks too...\n\n# Code Execution Hook for Arm64 Emulation\n\n![Code Execution Hook for Arm64 Emulation](https://lupyuen.github.io/images/unicorn-code3.png)\n\n_Can we intercept every Arm64 Instruction that will be emulated?_\n\nYep we can call Unicorn Emulator to add a Code Execution Hook.\n\nHere's a sample Hook Function that will be called for every Arm64 Instruction...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L108-L117\n\nAnd this is how we call Unicorn Emulator to add the above Hook Function...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L52-L57\n\nWhen we run our Rust Program, we see the Address of every Arm64 Instruction emulated (and its size)...\n\n```text\nhook_code:\n  address=0x10000,\n  size=4\n\nhook_code:\n  address=0x10004,\n  size=4\n```\n\nWe might use this to emulate special Arm64 Instructions.\n\nIf we don't need to intercept every single instruction, try the Block Execution Hook...\n\n# Block Execution Hook for Arm64 Emulation\n\n_Is there something that works like a Code Execution Hook..._\n\n_But doesn't stop at every single Arm64 Instruction?_\n\nYep Unicorn Emulator supports Block Execution Hooks.\n\nThis Hook Function will be called once when executing a Block of Arm64 Instructions...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L97-L106\n\nThis is how we add the Block Execution Hook...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/3655ac2875664376f42ad3a3ced5cbf067790782/src/main.rs#L48-L50\n\nWhen we run the Rust Program, we see that that the Block Size is 8...\n\n```text\nhook_block:\n  address=0x10000,\n  size=8\n```\n\nWhich means that Unicorn Emulator calls our Hook Function only once for the entire Block of 2 Arm64 Instructions.\n\nThis Block Execution Hook will be super helpful for monitoring the Execution Flow of our emulated code.\n\nLet's talk about the Block...\n\n# What is a Block of Arm64 Instructions?\n\n_What exactly is a Block of Arm64 Instructions?_\n\nWhen we run this code from Apache NuttX RTOS (that handles UART Output)...\n\n```text\nSECTION_FUNC(text, up_lowputc)\n  ldr   x15, =UART0_BASE_ADDRESS\n  400801f0:\t580000cf \tldr\tx15, 40080208 \u003cup_lowputc+0x18\u003e\nnuttx/arch/arm64/src/chip/a64_lowputc.S:89\n  early_uart_ready x15, w2\n  400801f4:\t794029e2 \tldrh\tw2, [x15, #20]\n  400801f8:\t721b005f \ttst\tw2, #0x20\n  400801fc:\t54ffffc0 \tb.eq\t400801f4 \u003cup_lowputc+0x4\u003e  // b.none\nnuttx/arch/arm64/src/chip/a64_lowputc.S:90\n  early_uart_transmit x15, w0\n  40080200:\t390001e0 \tstrb\tw0, [x15]\nnuttx/arch/arm64/src/chip/a64_lowputc.S:91\n  ret\n  40080204:\td65f03c0 \tret\n```\n\n[(Arm64 Disassembly)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/a1fb82d829856d86d6845c477709c2be24373aca/nuttx/nuttx.S#L3398-L3411)\n\n[(Source Code)](https://github.com/apache/nuttx/blob/master/arch/arm64/src/a64/a64_lowputc.S#L61-L71)\n\nWe observe that Unicorm Emulator treats `400801f0` to `400801fc` as a Block of Arm64 Instructins...\n\n```text\nhook_block:  address=0x400801f0, size=16\nhook_code:   address=0x400801f0, size=4\nhook_code:   address=0x400801f4, size=4\nhook_code:   address=0x400801f4, size=4\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\n\nhook_block:  address=0x400801f4, size=12\nhook_code:   address=0x400801f4, size=4\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\n\nhook_block:  address=0x400801f4, size=12\nhook_code:   address=0x400801f4, size=4\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\n```\n\n[(Source)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/cd030954c2ace4cf0207872f275abc3ffb7343c6/README.md#block-execution-hooks-for-arm64-emulation)\n\nThe Block ends at `400801fc` because there's an Arm64 Branch Instruction `b.eq`.\n\nFrom this we deduce that Unicorn Emulator treats a sequence of Arm64 Instructions as a Block, until it sees a Branch Instruction. (Including function calls)\n\n# Unmapped Memory in Unicorn Emulator\n\n_What happens when Unicorn Emulator tries to access memory that isn't mapped?_\n\nUnicorn Emulator will call our Memory Access Hook with `mem_type` set to `READ_UNMAPPED`...\n\n```text\nhook_memory:\n  address=0x01c28014,\n  size=2,\n  mem_type=READ_UNMAPPED,\n  value=0x0\n```\n\n[(Source)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/b842358ba457b67ffa9f4c1a362b0386cfd97c4a/README.md#block-execution-hooks-for-arm64-emulation)\n\nThe log above says that address `0x01c2` `8014` is unmapped.\n\nThis is how we map the memory...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/cd030954c2ace4cf0207872f275abc3ffb7343c6/src/main.rs#L26-L32\n\n[(See the NuttX Memory Map)](https://github.com/apache/nuttx/blob/master/arch/arm64/include/a64/chip.h#L44-L52)\n\n_Can we map Memory Regions during emulation?_\n\nYep we may use a Memory Access Hook to map memory regions on the fly. [(See this)](https://github.com/unicorn-engine/unicorn/blob/dev/docs/FAQ.md#i-cant-recover-from-unmapped-readwrite-even-i-return-true-in-the-hook-why)\n\n# Run Apache NuttX RTOS in Unicorn Emulator\n\n![Run Apache NuttX RTOS in Unicorn Emulator](https://lupyuen.github.io/images/unicorn-code4.png)\n\nLet's run Apache NuttX RTOS in Unicorn Emulator!\n\nWe have compiled [Apache NuttX RTOS for PinePhone](nuttx) into an Arm64 Binary Image `nuttx.bin`.\n\nThis is how we load the NuttX Binary Image into Unicorn...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/aa24d1c61256f38f92cf627d52c3e9a0c189bfc6/src/main.rs#L6-L40\n\nIn our Rust Program above, we mapped 2 Memory Regions for NuttX...\n\n-   Map 128 MB Executable Memory at `0x4000` `0000` for Arm64 Machine Code\n\n-   Map 512 MB Read/Write Memory at `0x0000` `0000` for Memory-Mapped I/O by Allwinner A64 Peripherals\n\nThis is based on the [NuttX Memory Map](https://github.com/apache/nuttx/blob/master/arch/arm64/include/a64/chip.h#L44-L52) for PinePhone.\n\nWhen we run this, Unicorn Emulator loops forever. Let's find out why...\n\n# Unicorn Emulator Waits Forever for UART Controller Ready\n\n![Emulating the Allwinner A64 UART Controller](https://lupyuen.github.io/images/unicorn-code5.png)\n\nHere's the output when we run NuttX RTOS in Unicorn Emulator...\n\n```text\nhook_memory: address=0x01c28014, size=2, mem_type=READ, value=0x0\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\nhook_block:  address=0x400801f4, size=12\nhook_code:   address=0x400801f4, size=4\n\nhook_memory: address=0x01c28014, size=2, mem_type=READ, value=0x0\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\nhook_block:  address=0x400801f4, size=12\nhook_code:   address=0x400801f4, size=4\n\nhook_memory: address=0x01c28014, size=2, mem_type=READ, value=0x0\nhook_code:   address=0x400801f8, size=4\nhook_code:   address=0x400801fc, size=4\nhook_block:  address=0x400801f4, size=12\nhook_code:   address=0x400801f4, size=4\n...\n```\n\n[(Source)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/045fa5da84d9e07ead5a820a075c1445661328b6/README.md#unicorn-emulator-waits-forever-for-uart-controller-ready)\n\nThe above log shows that Unicorn Emulator loops forever at address `0x4008` `01f4`, while reading the data from address `0x01c2` `8014`.\n\nLet's check the NuttX Arm64 Code at address `0x4008` `01f4`...\n\n```text\nSECTION_FUNC(text, up_lowputc)\n  ldr   x15, =UART0_BASE_ADDRESS\n  400801f0:\t580000cf \tldr\tx15, 40080208 \u003cup_lowputc+0x18\u003e\nnuttx/arch/arm64/src/chip/a64_lowputc.S:89\n  early_uart_ready x15, w2\n  400801f4:\t794029e2 \tldrh\tw2, [x15, #20]\n  400801f8:\t721b005f \ttst\tw2, #0x20\n  400801fc:\t54ffffc0 \tb.eq\t400801f4 \u003cup_lowputc+0x4\u003e  // b.none\nnuttx/arch/arm64/src/chip/a64_lowputc.S:90\n  early_uart_transmit x15, w0\n  40080200:\t390001e0 \tstrb\tw0, [x15]\nnuttx/arch/arm64/src/chip/a64_lowputc.S:91\n  ret\n  40080204:\td65f03c0 \tret\n```\n\n[(Arm64 Disassembly)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/a1fb82d829856d86d6845c477709c2be24373aca/nuttx/nuttx.S#L3398-L3411)\n\nWhich comes from this NuttX Source Code...\n\n```text\n/* Wait for A64 UART to be ready to transmit\n * xb: Register that contains the UART Base Address\n * wt: Scratch register number\n */\n.macro early_uart_ready xb, wt\n1:\n  ldrh  \\wt, [\\xb, #0x14]      /* UART_LSR (Line Status Register) */\n  tst   \\wt, #0x20             /* Check THRE (TX Holding Register Empty) */\n  b.eq  1b                     /* Wait for the UART to be ready (THRE=1) */\n.endm\n```\n\n[(Source Code)](https://github.com/apache/nuttx/blob/master/arch/arm64/src/a64/a64_lowputc.S#L61-L71)\n\nThis code waits for the UART Controller to be ready (before printing UART Output), by checking the value at `0x01c2` `8014`. The code is explained here...\n\n-   [\"Wait for UART Ready\"](https://lupyuen.github.io/articles/uboot#wait-for-uart-ready)\n\n_What is `0x01c2` `8014`?_\n\nAccording to the Allwinner A64 Doc...\n\n-   [\"Wait To Transmit\"](https://lupyuen.github.io/articles/serial#wait-to-transmit)\n\n`0x01c2` `8014` is the UART Line Status Register (UART_LSR) at Offset 0x14.\n\nBit 5 needs to be set to 1 to indicate that the UART Transmit FIFO is ready.\n\nWe emulate the UART Ready Bit like so...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/4d78876ad6f40126bf68cb2da4a43f56d9ef6e76/src/main.rs#L42-L49\n\nAnd Unicorn Emulator stops looping! It continues execution to `memset()` (to init the BSS Section to 0)...\n\n```text\nhook_block:  address=0x40089328, size=8\nhook_memory: address=0x400b6a52, size=1, mem_type=WRITE, value=0x0\nhook_block:  address=0x40089328, size=8\nhook_memory: address=0x400b6a53, size=1, mem_type=WRITE, value=0x0\nhook_block:  address=0x40089328, size=8\nhook_memory: address=0x400b6a54, size=1, mem_type=WRITE, value=0x0\n...\n```\n\n[(Source)](https://github.com/lupyuen/nuttx-arm64-emulator/blob/045fa5da84d9e07ead5a820a075c1445661328b6/README.md#unicorn-emulator-waits-forever-for-uart-controller-ready)\n\nBut we don't see any UART Output. Let's print the UART Output...\n\n# Emulate UART Output in Unicorn Emulator\n\n![Emulating UART Output in Unicorn Emulator](https://lupyuen.github.io/images/unicorn-code6.png)\n\n_How do we print the UART Output?_\n\nAccording to the Allwinner A64 Doc...\n\n-   [\"Transmit UART\"](https://lupyuen.github.io/articles/serial#transmit-uart)\n\nNuttX RTOS will write the UART Output to the UART Transmit Holding Register (THR) at `0x01c2` `8000`.\n\nIn our Memory Access Hook, let's intercept all writes to `0x01c2` `8000` and dump the characters written to UART Output...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/aa6dd986857231a935617e8346978d7750aa51e7/src/main.rs#L89-L111\n\nWhen we run this, we see a long chain of UART Output...\n\n```text\n→ cargo run | grep uart\nuart output: '-'\nuart output: ' '\nuart output: 'R'\nuart output: 'e'\nuart output: 'a'\nuart output: 'd'\nuart output: 'y'\n...\n```\n\n[(Source)](https://gist.github.com/lupyuen/587dbeb9329d9755e4d007dd8e1246cd)\n\nWhich reads as...\n\n```text\n- Ready to Boot CPU\n- Boot from EL2\n- Boot from EL1\n- Boot to C runtime for OS Initialize\n```\n\n[(Similar to this)](https://lupyuen.github.io/articles/uboot#pinephone-boots-nuttx)\n\nYep NuttX RTOS is booting on Unicorn Emulator! But Unicorn Emulator halts while booting NuttX...\n\n# Unicorn Emulator Halts in NuttX MMU\n\nUnicorn Emulator halts with an __Arm64 Exception__ at address __`4008` `0EF8`__...\n\n```text\nhook_block:  address=0x40080cec, size=16\nhook_code:   address=0x40080cec, size=4\nhook_memory: address=0x400c3f90, size=8, mem_type=READ, value=0x0\nhook_memory: address=0x400c3f98, size=8, mem_type=READ, value=0x0\nhook_code:   address=0x40080cf0, size=4\nhook_memory: address=0x400c3fa0, size=8, mem_type=READ, value=0x0\nhook_code:   address=0x40080cf4, size=4\nhook_memory: address=0x400c3f80, size=8, mem_type=READ, value=0x0\nhook_memory: address=0x400c3f88, size=8, mem_type=READ, value=0x0\nhook_code:   address=0x40080cf8, size=4\nhook_block:  address=0x40080eb0, size=12\nhook_code:   address=0x40080eb0, size=4\nhook_code:   address=0x40080eb4, size=4\nhook_code:   address=0x40080eb8, size=4\nhook_block:  address=0x40080ebc, size=16\nhook_code:   address=0x40080ebc, size=4\nhook_code:   address=0x40080ec0, size=4\nhook_code:   address=0x40080ec4, size=4\nhook_code:   address=0x40080ec8, size=4\nhook_block:  address=0x40080ecc, size=16\nhook_code:   address=0x40080ecc, size=4\nhook_code:   address=0x40080ed0, size=4\nhook_code:   address=0x40080ed4, size=4\nhook_code:   address=0x40080ed8, size=4\nhook_block:  address=0x40080edc, size=12\nhook_code:   address=0x40080edc, size=4\nhook_code:   address=0x40080ee0, size=4\nhook_code:   address=0x40080ee4, size=4\nhook_block:  address=0x40080ee8, size=4\nhook_code:   address=0x40080ee8, size=4\nhook_block:  address=0x40080eec, size=16\nhook_code:   address=0x40080eec, size=4\nhook_code:   address=0x40080ef0, size=4\nhook_code:   address=0x40080ef4, size=4\nhook_code:   address=0x40080ef8, size=4\nerr=Err(EXCEPTION)\n```\n\n[(See the Complete Log)](https://gist.github.com/lupyuen/778f15875edf632ccb5a093a656084cb)\n\nUnicorn Emulator halts at the NuttX MMU (EL1) code at `0x4008` `0ef8`...\n\n```text\nnuttx/arch/arm64/src/common/arm64_mmu.c:544\n  write_sysreg((value | SCTLR_M_BIT | SCTLR_C_BIT), sctlr_el1);\n    40080ef0:\td28000a1 \tmov\tx1, #0x5                   \t// #5\n    40080ef4:\taa010000 \torr\tx0, x0, x1\n    40080ef8:\td5181000 \tmsr\tsctlr_el1, x0\n```\n\n_Why did MSR fail with an Exception?_\n\nHere's the context...\n\n```text\nenable_mmu_el1():\nnuttx/arch/arm64/src/common/arm64_mmu.c:533\n  write_sysreg(MEMORY_ATTRIBUTES, mair_el1);\n    40080ebc:\td2808000 \tmov\tx0, #0x400                 \t// #1024\n    40080ec0:\tf2a88180 \tmovk\tx0, #0x440c, lsl #16\n    40080ec4:\tf2c01fe0 \tmovk\tx0, #0xff, lsl #32\n    40080ec8:\td518a200 \tmsr\tmair_el1, x0\nnuttx/arch/arm64/src/common/arm64_mmu.c:534\n  write_sysreg(get_tcr(1), tcr_el1);\n    40080ecc:\td286a380 \tmov\tx0, #0x351c                \t// #13596\n    40080ed0:\tf2a01000 \tmovk\tx0, #0x80, lsl #16\n    40080ed4:\tf2c00020 \tmovk\tx0, #0x1, lsl #32\n    40080ed8:\td5182040 \tmsr\ttcr_el1, x0\nnuttx/arch/arm64/src/common/arm64_mmu.c:535\n  write_sysreg(((uint64_t)base_xlat_table), ttbr0_el1);\n    40080edc:\td00001a0 \tadrp\tx0, 400b6000 \u003cg_uart1port\u003e\n    40080ee0:\t91200000 \tadd\tx0, x0, #0x800\n    40080ee4:\td5182000 \tmsr\tttbr0_el1, x0\narm64_isb():\nnuttx/arch/arm64/src/common/barriers.h:58\n  __asm__ volatile (\"isb\" : : : \"memory\");\n    40080ee8:\td5033fdf \tisb\nenable_mmu_el1():\nnuttx/arch/arm64/src/common/arm64_mmu.c:543\n  value = read_sysreg(sctlr_el1);\n    40080eec:\td5381000 \tmrs\tx0, sctlr_el1\nnuttx/arch/arm64/src/common/arm64_mmu.c:544\n  write_sysreg((value | SCTLR_M_BIT | SCTLR_C_BIT), sctlr_el1);\n    40080ef0:\td28000a1 \tmov\tx1, #0x5                   \t// #5\n    40080ef4:\taa010000 \torr\tx0, x0, x1\n    40080ef8:\td5181000 \tmsr\tsctlr_el1, x0\narm64_isb():\nnuttx/arch/arm64/src/common/barriers.h:58\n    40080efc:\td5033fdf \tisb\n```\n\nWhich comes from this __NuttX Source Code__: [arm64_mmu.c](https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_mmu.c#L541-L544)\n\n```c\n// Enable the MMU and data cache:\n// Read from System Control Register EL1\nvalue = read_sysreg(sctlr_el1);\n\n// Write to System Control Register EL1\nwrite_sysreg(  // Write to System Register...\n  value | SCTLR_M_BIT | SCTLR_C_BIT,  // Enable Address Translation and Caching\n  sctlr_el1    // System Control Register EL1\n);\n```\n\nLet's dump the Arm64 Exception...\n\n# Dump the Arm64 Exception\n\nTo find out the cause of the Arm64 Exception, let's dump the Exception Syndrome Register (ESR).\n\nBut this won't work...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/1cbfa48de10ef4735ebaf91ab85631cb48e37591/src/main.rs#L86-L91\n\nBecause `ESR_EL` is [no longer supported](https://github.com/unicorn-engine/unicorn/blob/master/bindings/rust/src/arm64.rs#L288-L307) and `CP_REG` can't be read in Rust...\n\n```text\nerr=Err(EXCEPTION)\nCP_REG=Err(ARG)\nESR_EL0=Ok(0)\nESR_EL1=Ok(0)\nESR_EL2=Ok(0)\nESR_EL3=Ok(0)\n```\n\n[(See the Complete Log)](https://gist.github.com/lupyuen/778f15875edf632ccb5a093a656084cb)\n\n`CP_REG` can't be read in Rust because Unicorn needs a pointer to `uc_arm64_cp_reg`...\n\n```c\nstatic uc_err reg_read(CPUARMState *env, unsigned int regid, void *value) {\n  ...\n  case UC_ARM64_REG_CP_REG:\n      ret = read_cp_reg(env, (uc_arm64_cp_reg *)value);\n      break;\n```\n\n[(Source)](https://github.com/unicorn-engine/unicorn/blob/master/qemu/target/arm/unicorn_aarch64.c#L225-L227)\n\nWhich isn't supported by the [Rust Bindings](https://github.com/unicorn-engine/unicorn/blob/master/bindings/rust/src/lib.rs#L528-L543).\n\n[(Works in Python though)](https://github.com/unicorn-engine/unicorn/blob/master/bindings/python/sample_arm64.py#L76-L82)\n\nSo instead we set a breakpoint at `arm64_reg_read()` (pic below) in...\n\n```text\n.cargo/registry/src/github.com-1ecc6299db9ec823/unicorn-engine-2.0.1/qemu/target/arm/unicorn_aarch64.c\n```\n\n(`arm64_reg_read()` calls `reg_read()` in unicorn_aarch64.c)\n\nWhich shows the Exception as...\n\n```text\nenv.exception = {\n  syndrome: 0x8600 003f, \n  fsr: 5, \n  vaddress: 0x400c 3fff,\n  target_el: 1\n}\n```\n\nLet's study the Arm64 Exception...\n\n![Debug the Arm64 Exception](https://lupyuen.github.io/images/unicorn-debug.png)\n\n# Arm64 MMU Exception\n\nEarlier we saw this Arm64 Exception in Unicorn Emulator...\n\n```text\nenv.exception = {\n  syndrome: 0x8600 003f, \n  fsr: 5, \n  vaddress: 0x400c 3fff,\n  target_el: 1\n}\n```\n\nTODO: What is address `0x400c` `3fff`?\n\n_What is Syndrome 0x8600 003f?_\n\nBits 26-31 of Syndrome = 0b100001, which means...\n\n\u003e 0b100001: Instruction Abort taken without a change in Exception level.\n\n\u003e Used for MMU faults generated by instruction accesses and synchronous External aborts, including synchronous parity or ECC errors. Not used for debug-related exceptions.\n\n[(Source)](https://developer.arm.com/documentation/ddi0601/2022-03/AArch64-Registers/ESR-EL1--Exception-Syndrome-Register--EL1-)\n\n_What is FSR 5?_\n\nFSR 5 means...\n\n\u003e 0b00101: Translation Fault (in) Section\n\n[(Source)](https://developer.arm.com/documentation/ddi0500/d/system-control/aarch64-register-descriptions/instruction-fault-status-register--el2)\n\n_Why the MMU Fault?_\n\nUnicorn Emulator triggers the exception when NuttX writes to SCTLR_EL1...\n\n```c\n  /* Enable the MMU and data cache */\n  value = read_sysreg(sctlr_el1);\n  write_sysreg((value | SCTLR_M_BIT | SCTLR_C_BIT), sctlr_el1);\n```\n\n[(Source)](https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_mmu.c#L541-L544)\n\nThe above code sets these flags in SCTLR_EL1 (System Control Register EL1)...\n\n- SCTLR_M_BIT (Bit 0): Enable Address Translation for EL0 and EL1 Stage 1\n\n- SCTLR_C_BIT (Bit 2): Enable Caching for EL0 and EL1 Stage 1\n\n[(More about SCTLR_EL1)](https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/SCTLR-EL1--System-Control-Register--EL1-)\n\nTODO: Why did the Address Translation (or Caching) fail?\n\nTODO: Should we skip the MMU Update to SCTLR_EL1? Since we don't use MMU?\n\n# Debug the Unicorn Emulator\n\n_To troubleshoot the Arm64 MMU Exception..._\n\n_Can we use a debugger to step through Unicorn Emulator?_\n\nYes but it gets messy.\n\nTo trace the exception in the debugger. Look for...\n\n```text\n$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823/unicorn-engine-2.0.1/qemu/target/arm/translate-a64.c\n```\n\nSet a breakpoint in `aarch64_tr_translate_insn()`\n\n-   Which calls `disas_b_exc_sys()`\n\n-   Which calls `disas_system()`\n\n-   Which calls `handle_sys()` to handle system instructions\n\nTo inspect the Emulator Settings, set a breakpoint at `cpu_aarch64_init()` in...\n\n```text\n$HOME/.cargo/registry/src/github.com-1ecc6299db9ec823/unicorn-engine-2.0.1/qemu/target/arm/cpu64.c\n```\n\nTODO: Check that the CPU Setting is correct for PinePhone. (CPU Model should be Cortex-A53)\n\n# Map Address to Function with ELF File\n\nRead the article...\n\n-   [\"(Clickable) Call Graph for Apache NuttX Real-Time Operating System\"](https://lupyuen.github.io/articles/unicorn2)\n\nOur __Block Execution Hook__ now prints the __Function Name__ and the __Filename__...\n\n```text\nhook_block:  \n  address=0x40080eb0, \n  size=12, \n  setup_page_tables, \n  arch/arm64/src/common/arm64_mmu.c:516:25\n\nhook_block:  \n  address=0x40080eec, \n  size=16, \n  enable_mmu_el1, \n  arch/arm64/src/common/arm64_mmu.c:543:11\n\nerr=Err(EXCEPTION)\n```\n\n[(Source)](https://gist.github.com/lupyuen/f2e883b2b8054d75fbac7de661f0ee5a)\n\nOur Hook Function looks up the Address in the [__DWARF Debug Symbols__](https://crates.io/crates/gimli) of the [__NuttX ELF File__](https://github.com/lupyuen/nuttx-arm64-emulator/blob/main/nuttx/nuttx).\n\nThis is explained here...\n\n-   [\"Map Address to Function with ELF File\"](https://lupyuen.github.io/articles/unicorn#appendix-map-address-to-function-with-elf-file)\n\n# Call Graph for Apache NuttX RTOS\n\nTo troubleshoot the Apache NuttX MMU Fault on Unicorn Emulator, we auto-generated this Call Graph...\n\n(To see the NuttX Source Code: Right-click the Node and select \"Open Link\")\n\n```mermaid\n  flowchart TD\n  START --\u003e arm64_head\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L104\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L58\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L177\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  a64_lowputc --\u003e arm64_head\n  click a64_lowputc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_lowputc.S#L87\" \"arch/arm64/src/a64/a64_lowputc.S \" _blank\n  arm64_head --\u003e a64_lowputc\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  arm64_head --\u003e arm64_boot_el1_init\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  arm64_boot_el1_init --\u003e arm64_isb\n  click arm64_boot_el1_init href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_boot.c#L137\" \"arch/arm64/src/common/arm64_boot.c \" _blank\n  arm64_isb --\u003e arm64_boot_el1_init\n  click arm64_isb href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/barriers.h#L57\" \"arch/arm64/src/common/barriers.h \" _blank\n  arm64_boot_el1_init --\u003e arm64_isb\n  click arm64_boot_el1_init href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_boot.c#L145\" \"arch/arm64/src/common/arm64_boot.c \" _blank\n  arm64_isb --\u003e arm64_boot_el1_init\n  click arm64_isb href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/barriers.h#L57\" \"arch/arm64/src/common/barriers.h \" _blank\n  arm64_head --\u003e arm64_boot_primary_c_routine\n  click arm64_head href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_head.S#L298\" \"arch/arm64/src/common/arm64_head.S \" _blank\n  arm64_boot_primary_c_routine --\u003e memset\n  click arm64_boot_primary_c_routine href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_boot.c#L180\" \"arch/arm64/src/common/arm64_boot.c \" _blank\n  memset --\u003e arm64_boot_primary_c_routine\n  click memset href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/libs/libc/string/lib_memset.c#L168\" \"libs/libc/string/lib_memset.c \" _blank\n  arm64_boot_primary_c_routine --\u003e arm64_chip_boot\n  click arm64_boot_primary_c_routine href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_boot.c#L181\" \"arch/arm64/src/common/arm64_boot.c \" _blank\n  arm64_chip_boot --\u003e arm64_mmu_init\n  click arm64_chip_boot href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/a64/a64_boot.c#L81\" \"arch/arm64/src/a64/a64_boot.c \" _blank\n  arm64_mmu_init --\u003e setup_page_tables\n  click arm64_mmu_init href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L583\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  setup_page_tables --\u003e init_xlat_tables\n  click setup_page_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L490\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L417\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e init_xlat_tables\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e pte_desc_type\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  pte_desc_type --\u003e new_prealloc_table\n  click pte_desc_type href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L234\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  new_prealloc_table --\u003e init_xlat_tables\n  click new_prealloc_table href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L378\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L437\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e pte_desc_type\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  pte_desc_type --\u003e calculate_pte_index\n  click pte_desc_type href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L234\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e init_xlat_tables\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L247\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  set_pte_block_desc --\u003e init_xlat_tables\n  click set_pte_block_desc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L293\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e init_xlat_tables\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e pte_desc_type\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  pte_desc_type --\u003e init_xlat_tables\n  click pte_desc_type href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L234\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L472\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e pte_desc_type\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  pte_desc_type --\u003e calculate_pte_index\n  click pte_desc_type href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L234\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e init_xlat_tables\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L247\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e pte_desc_type\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e calculate_pte_index\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L472\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e pte_desc_type\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e pte_desc_type\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  calculate_pte_index --\u003e pte_desc_type\n  click calculate_pte_index href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L246\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e set_pte_block_desc\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L447\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e setup_page_tables\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  pte_desc_type --\u003e new_prealloc_table\n  click pte_desc_type href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L234\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e setup_page_tables\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e new_prealloc_table\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L472\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  new_prealloc_table --\u003e split_pte_block_desc\n  click new_prealloc_table href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L378\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  split_pte_block_desc --\u003e set_pte_table_desc\n  click split_pte_block_desc href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L401\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e setup_page_tables\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e setup_page_tables\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  init_xlat_tables --\u003e setup_page_tables\n  click init_xlat_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L456\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  setup_page_tables --\u003e enable_mmu_el1\n  click setup_page_tables href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L515\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  enable_mmu_el1 --\u003e arm64_isb\n  click enable_mmu_el1 href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L532\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n  arm64_isb --\u003e enable_mmu_el1\n  click arm64_isb href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/barriers.h#L57\" \"arch/arm64/src/common/barriers.h \" _blank\n  enable_mmu_el1 --\u003e ***_HALT_***\n  click enable_mmu_el1 href \"https://github.com/apache/nuttx/blob/0f20888a0ececc5dc7419d57a01ac508ac3ace5b/arch/arm64/src/common/arm64_mmu.c#L542\" \"arch/arm64/src/common/arm64_mmu.c \" _blank\n```\n\nWe generated the Call Graph with this command...\n\n```bash\ncargo run | grep call_graph | cut -c 12-\n```\n\n(`cut` command removes columns 1 to 11)\n\nWhich produces this [Mermaid Flowchart](https://mermaid.js.org/syntax/flowchart.html)...\n\n```text\n→ cargo run | grep call_graph | cut -c 12- \n  flowchart TD\n  arm64_boot_el1_init --\u003e arm64_isb\n  click arm64_boot_el1_init href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_boot.c#L137\" \"arch/arm64/src/common/arm64_boot.c \"\n  arm64_isb --\u003e arm64_boot_el1_init\n  click arm64_isb href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/barriers.h#L57\" \"arch/arm64/src/common/barriers.h \"\n  arm64_boot_el1_init --\u003e arm64_isb\n  click arm64_boot_el1_init href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_boot.c#L145\" \"arch/arm64/src/common/arm64_boot.c \"\n  arm64_isb --\u003e arm64_boot_el1_init\n  ...\n  setup_page_tables --\u003e enable_mmu_el1\n  click setup_page_tables href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_mmu.c#L515\" \"arch/arm64/src/common/arm64_mmu.c \"\n  enable_mmu_el1 --\u003e arm64_isb\n  click enable_mmu_el1 href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_mmu.c#L532\" \"arch/arm64/src/common/arm64_mmu.c \"\n  arm64_isb --\u003e enable_mmu_el1\n  click arm64_isb href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/barriers.h#L57\" \"arch/arm64/src/common/barriers.h \"\n  enable_mmu_el1 --\u003e ***_HALT_***\n  click enable_mmu_el1 href \"https://github.com/apache/nuttx/blob/master/arch/arm64/src/common/arm64_mmu.c#L542\" \"arch/arm64/src/common/arm64_mmu.c \"\n```\n\n[(Source)](https://gist.github.com/lupyuen/b0e4019801aaf9860bcb234c8a9c8584)\n\nThe Call Graph is generated by our Block Execution Hook like so...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/b23c1d251a7fb244f2e396419d12ab532deb3e6b/src/main.rs#L130-L159\n\n`call_graph` prints the Call Graph by looking up the Block Address in the ELF Context...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/b23c1d251a7fb244f2e396419d12ab532deb3e6b/src/main.rs#L224-L265\n\nWe map the Block Address to Function Name and Source File in `map_address_to_function` and `map_address_to_location`...\n\nhttps://github.com/lupyuen/nuttx-arm64-emulator/blob/b23c1d251a7fb244f2e396419d12ab532deb3e6b/src/main.rs#L175-L222\n\n`ELF_CONTEXT` is explained here...\n\n-   [\"(Clickable) Call Graph for Apache NuttX Real-Time Operating System\"](https://lupyuen.github.io/articles/unicorn2)\n\n# Other Emulators\n\n_What about emulating popular operating systems: Linux / macOS / Windows / Android?_\n\nCheck out the Qiling Binary Emulation Framework...\n\n-   [qilingframework/qiling](https://github.com/qilingframework/qiling)\n\n_How about other hardware platforms: STM32 Blue Pill and ESP32?_\n\nCheck out QEMU...\n\n-   [\"STM32 Blue Pill — Unit Testing with Qemu Blue Pill Emulator\"](https://lupyuen.github.io/articles/stm32-blue-pill-unit-testing-with-qemu-blue-pill-emulator)\n\n-   [\"NuttX on an emulated ESP32 using QEMU\"](https://medium.com/@lucassvaz/nuttx-on-an-emulated-esp32-using-qemu-8d8d93d24c63)\n\n# TODO\n\nTODO: Emulate Input Interupts from UART Controller\n\nTODO: Emulate Apache NuttX NSH Shell with UART Controller\n\nTODO: Select Arm Cortex-A53 as CPU\n\nTODO: Emulate Multiple CPUs\n\nTODO: Emulate Arm64 Memory Protection\n\nTODO: Emulate Arm64 Generic Interrupt Controller version 2\n\nTODO: Read the Symbol Table in NuttX ELF File to match the addresses received by Block Execution Hook\n\nTODO: Emulate PinePhone's Allwinner A64 Display Engine. How to render the emulated graphics: Use Web Browser + WebAssembly + Unicorn.js? Will framebuffer emulation be slow?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flupyuen%2Fnuttx-arm64-emulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flupyuen%2Fnuttx-arm64-emulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flupyuen%2Fnuttx-arm64-emulator/lists"}