master 644474cc09f7 cached
1175 files
4.0 MB
1.1M tokens
6228 symbols
1 requests
Download .txt
Showing preview only (4,505K chars total). Download the full file or copy to clipboard to get everything.
Repository: rust-embedded/rust-raspi3-tutorial
Branch: master
Commit: 644474cc09f7
Files: 1175
Total size: 4.0 MB

Directory structure:
gitextract_d1imolyg/

├── .editorconfig
├── .githooks/
│   └── pre-commit
├── .github/
│   ├── FUNDING.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build_rpi3.yml
│       ├── build_rpi4.yml
│       ├── sanity.yml
│       ├── test_integration.yml
│       ├── test_unit.yml
│       └── test_xtra.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .rubocop.yml
├── .ruby-version
├── .rustfmt.toml
├── .vscode/
│   └── settings.json
├── 00_before_we_start/
│   ├── README.CN.md
│   ├── README.ES.md
│   └── README.md
├── 01_wait_forever/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   └── src/
│       ├── _arch/
│       │   └── aarch64/
│       │       └── cpu/
│       │           ├── boot.rs
│       │           └── boot.s
│       ├── bsp/
│       │   ├── raspberrypi/
│       │   │   └── kernel.ld
│       │   └── raspberrypi.rs
│       ├── bsp.rs
│       ├── cpu/
│       │   └── boot.rs
│       ├── cpu.rs
│       ├── main.rs
│       └── panic_wait.rs
├── 02_runtime_init/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   └── src/
│       ├── _arch/
│       │   └── aarch64/
│       │       ├── cpu/
│       │       │   ├── boot.rs
│       │       │   └── boot.s
│       │       └── cpu.rs
│       ├── bsp/
│       │   ├── raspberrypi/
│       │   │   ├── cpu.rs
│       │   │   └── kernel.ld
│       │   └── raspberrypi.rs
│       ├── bsp.rs
│       ├── cpu/
│       │   └── boot.rs
│       ├── cpu.rs
│       ├── main.rs
│       └── panic_wait.rs
├── 03_hacky_hello_world/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   └── kernel.ld
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   └── print.rs
│   └── tests/
│       └── boot_test_string.rb
├── 04_safe_globals/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   └── kernel.ld
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   └── tests/
│       └── boot_test_string.rb
├── 05_drivers_gpio_uart/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   └── tests/
│       └── boot_test_string.rb
├── 06_uart_chainloader/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── demo_payload_rpi3.img
│   ├── demo_payload_rpi4.img
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   ├── tests/
│   │   └── chainboot_test.rb
│   └── update.sh
├── 07_timestamps/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 08_hw_debug_JTAG/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 09_privilege_level/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 10_virtual_mem_part1_identity_mapping/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       ├── memory/
│   │   │       │   ├── mmu/
│   │   │       │   │   └── translation_table.rs
│   │   │       │   └── mmu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   ├── memory/
│   │   │   │   │   └── mmu.rs
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── common.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── memory/
│   │   │   ├── mmu/
│   │   │   │   └── translation_table.rs
│   │   │   └── mmu.rs
│   │   ├── memory.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 11_exceptions_part1_groundwork/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       ├── exception.s
│   │   │       ├── memory/
│   │   │       │   ├── mmu/
│   │   │       │   │   └── translation_table.rs
│   │   │       │   └── mmu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   ├── memory/
│   │   │   │   │   └── mmu.rs
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── common.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── memory/
│   │   │   ├── mmu/
│   │   │   │   └── translation_table.rs
│   │   │   └── mmu.rs
│   │   ├── memory.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 12_integrated_testing/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   └── boot.s
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   └── boot.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   └── translation_table.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 13_exceptions_part2_peripheral_IRQs/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   └── translation_table.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 14_virtual_mem_part2_mmio_remap/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 15_virtual_mem_part3_precomputed_tables/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── libraries/
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 16_virtual_mem_part4_higher_half_kernel/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── libraries/
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 17_kernel_symbols/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 18_backtrace/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 19_kernel_heap/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── buffer_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── heap_alloc.rs
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 20_timer_callbacks/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   ├── local_ic.rs
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── buffer_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── heap_alloc.rs
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── Gemfile
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.CN.md
├── README.ES.md
├── README.md
├── SPONSORING.md
├── X1_JTAG_boot/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── build.rs
│   ├── jtag_boot_rpi3.img
│   ├── jtag_boot_rpi4.img
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   ├── tests/
│   │   └── boot_test_string.rb
│   └── update.sh
├── common/
│   ├── docker.mk
│   ├── format.mk
│   ├── operating_system.mk
│   ├── serial/
│   │   ├── minipush/
│   │   │   └── progressbar_patch.rb
│   │   ├── minipush.rb
│   │   └── miniterm.rb
│   └── tests/
│       ├── boot_test.rb
│       ├── console_io_test.rb
│       ├── dispatch.rb
│       ├── exit_code_test.rb
│       └── test.rb
├── contributor_setup.sh
├── devtool_completion.bash
├── doc/
│   ├── 09_wiring_jtag.fzz
│   ├── 09_wiring_jtag.xcf
│   ├── 14_BCM_driver.drawio
│   ├── 14_GICv2_driver.drawio
│   ├── 14_header.drawio
│   ├── demo_PS1.txt
│   ├── source_section_divider.txt
│   └── wiring.fzz
├── docker/
│   ├── README.md
│   └── rustembedded-osdev-utils/
│       ├── Dockerfile
│       ├── Makefile
│       ├── auto
│       ├── rpi3.cfg
│       └── rpi4.cfg
├── rust-toolchain.toml
└── utils/
    ├── devtool/
    │   └── copyright.rb
    ├── devtool.rb
    ├── diff_tut_folders.bash
    └── update_copyright.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
trim_trailing_whitespace = true
max_line_length = 100

[Dockerfile]
indent_size = 4

[{Makefile,*.mk}]
indent_style = tab
indent_size = 8

[*.rb]
indent_size = 4

[*.rs]
indent_size = 4

[*.s]
indent_style = tab
indent_size = 8

[*.sh]
indent_size = 4

[*.toml]
indent_size = 4

[*.{yml,yaml}]
indent_size = 2


================================================
FILE: .githooks/pre-commit
================================================
#!/usr/bin/env ruby
# frozen_string_literal: true

# SPDX-License-Identifier: MIT OR Apache-2.0
#
# Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

require_relative '../utils/devtool/copyright'

def copyright_check(staged_files)
    source_files_exts = ['.S', '.rs', '.rb']

    staged_files = staged_files.select do |f|
        next if f.include?('build.rs')
        next if f.include?('boot_test_string.rb')

        f.include?('Makefile') ||
            f.include?('Dockerfile') ||
            source_files_exts.include?(File.extname(f))
    end
    return true if staged_files.empty?

    copyright_check_files(staged_files)
end

## -------------------------------------------------------------------------------------------------
## Execution starts here
## -------------------------------------------------------------------------------------------------
staged_files = `git --no-pager diff --name-only --cached --diff-filter=d`.split(/\n/)
root_dir = `git rev-parse --show-toplevel`.strip

# Copyright must be fixed manually.
exit(1) unless copyright_check(staged_files)

# Brute-force format. Don't care if it affects non-staged files as well, since we only add back the
# staged ones.
Dir.chdir(root_dir) { system('ruby utils/devtool.rb fmt') }

staged_files.each { |f| system("git add #{f}") }
exit(0)


================================================
FILE: .github/FUNDING.yml
================================================
custom: ["https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/master/SPONSORING.md"]


================================================
FILE: .github/pull_request_template.md
================================================
### Description

<Please describe the issues fixed by this PR>

Related Issue: <Insert link here if applicable>

### Pre-commit steps

 - [ ] Tested on QEMU and real HW Rasperry Pi.
     - Not needed if it is just a README change or similar.
 - [ ] Ran `./contributor_setup.sh` followed by `./devtool ready_for_publish`
     - You'll need `Ruby` with `Bundler` and `NPM` installed locally.
     - If no Rust-related files were changed, `./devtool ready_for_publish_no_rust` can be used instead (faster).
     - This step is optional, but much appreciated if done.


================================================
FILE: .github/workflows/build_rpi3.yml
================================================
name: BSP-RPi3

on:
    push:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    pull_request:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    schedule:
        - cron: "0 5 * * *"

jobs:
    build:
        name: Build kernels
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  cargo install cargo-binutils rustfilt
            - name: Set up Ruby
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Run
              run: |
                  BSP=rpi3 bundle exec ruby utils/devtool.rb make


================================================
FILE: .github/workflows/build_rpi4.yml
================================================
name: BSP-RPi4

on:
    push:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    pull_request:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    schedule:
        - cron: "0 5 * * *"

jobs:
    build:
        name: Build kernels
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  cargo install cargo-binutils rustfilt
            - name: Set up Ruby
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Run
              run: |
                  BSP=rpi4 bundle exec ruby utils/devtool.rb make


================================================
FILE: .github/workflows/sanity.yml
================================================
name: Various Sanity Checks

on:
    push:
        branches:
            - master
    pull_request:
        branches:
            - master

jobs:
    build:
        name: Various Sanity Checks
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Node
              uses: actions/setup-node@v1
              with:
                  node-version: "16"
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  rustup component add clippy
            - name: Set up Bundler
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Set up Prettier
              run: |
                  npm install prettier
            - name: Setup misspell
              run: |
                  curl -L -o ./install-misspell.sh https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh
                  sh ./install-misspell.sh -b .vendor
            - name: Run checks
              run: |
                  BSP=rpi3 bundle exec ruby utils/devtool.rb clippy
                  BSP=rpi4 bundle exec ruby utils/devtool.rb clippy
                  bundle exec ruby utils/devtool.rb copyright
                  bundle exec ruby utils/devtool.rb fmt_check
                  bundle exec ruby utils/devtool.rb misspell
                  bundle exec ruby utils/devtool.rb rubocop


================================================
FILE: .github/workflows/test_integration.yml
================================================
name: Integration-Tests

on:
    push:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    pull_request:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    schedule:
        - cron: "0 5 * * *"

jobs:
    build:
        name: Run integration tests
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  cargo install cargo-binutils rustfilt
            - name: Set up Ruby
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Run
              run: |
                  bundle exec ruby utils/devtool.rb test_integration


================================================
FILE: .github/workflows/test_unit.yml
================================================
name: Boot-and-Unit-Tests

on:
    push:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    pull_request:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    schedule:
        - cron: "0 5 * * *"

jobs:
    build:
        name: Run boot and unit tests
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  cargo install cargo-binutils rustfilt
            - name: Set up Ruby
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Run
              run: |
                  bundle exec ruby utils/devtool.rb test_boot
                  bundle exec ruby utils/devtool.rb test_unit


================================================
FILE: .github/workflows/test_xtra.yml
================================================
name: Xtra-Tests

on:
    push:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    pull_request:
        branches:
            - master
        paths-ignore:
            - "utils/**"
            - "doc/**"
            - "docker/**"
    schedule:
        - cron: "0 5 * * *"

jobs:
    build:
        name: Run xtra tests
        runs-on: ubuntu-22.04

        steps:
            - uses: actions/checkout@v3
            - name: Set up Ruby
              uses: ruby/setup-ruby@v1
            - name: Set up Rust nightly
              run: |
                  cargo install cargo-binutils
            - name: Set up Ruby
              run: |
                  gem install bundler
                  bundle config set without 'uart'
                  bundle install --retry 3
            - name: Run
              run: |
                  bundle exec ruby utils/devtool.rb make_xtra


================================================
FILE: .gitignore
================================================
**/target/*
**/.gdb_history
**/kernel8.img

node_modules
.bundle
.vendor

Gemfile.lock
package*.json


================================================
FILE: .prettierignore
================================================
**/*
!**/*/

**/target/
node_modules/
.vendor/

!*.json
!*.yml


================================================
FILE: .prettierrc.json
================================================
{
    "printWidth": 100,
    "tabWidth": 4,
    "useTabs": false,
    "semi": true,
    "singleQuote": false,
    "trailingComma": "es5",
    "bracketSpacing": true,
    "jsxBracketSameLine": false,
    "arrowParens": "always",
    "requirePragma": false,
    "insertPragma": false,
    "proseWrap": "preserve",
    "endOfLine": "auto",
    "overrides": [
        {
            "files": "*.rs",
            "options": {
                "printWidth": 100,
                "tabWidth": 4,
                "useTabs": false,
                "semi": true,
                "singleQuote": false,
                "trailingComma": "es5",
                "bracketSpacing": true,
                "jsxBracketSameLine": false,
                "arrowParens": "always",
                "requirePragma": false,
                "insertPragma": false,
                "proseWrap": "preserve",
                "endOfLine": "auto"
            }
        }
    ]
}


================================================
FILE: .rubocop.yml
================================================
# The behavior of RuboCop can be controlled via the .rubocop.yml
# configuration file. It makes it possible to enable/disable
# certain cops (checks) and to alter their behavior if they accept
# any parameters. The file can be placed either in your home
# directory or in some project directory.
#
# RuboCop will start looking for the configuration file in the directory
# where the inspected file is and continue its way up to the root directory.
#
# See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md

Layout/IndentationWidth:
    Width: 4
    AllowedPatterns: ['^\s*module']

Layout/LineLength:
    Max: 100

Lint/UnusedMethodArgument:
    AutoCorrect: False

Metrics/AbcSize:
    Max: 25

Metrics/ClassLength:
    Enabled: false

Metrics/MethodLength:
    Max: 20

AllCops:
    NewCops: enable


================================================
FILE: .ruby-version
================================================
3.0.2


================================================
FILE: .rustfmt.toml
================================================
newline_style = "Unix"
edition = "2021"
imports_granularity = "Crate"
format_code_in_doc_comments = true
normalize_comments = true
wrap_comments = true
comment_width = 100


================================================
FILE: .vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--lib", "--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 00_before_we_start/README.CN.md
================================================
# 在我们开始之前

下面的文本内容是1:1 复制的文档。在每个教程的内核主要源代码文档的头部。它描述了源代码的主要结构并且试着去传达各个方法背后的理念。请阅读文章以便你能熟悉你在教程中将会遇到的东西。这将帮助你更好的浏览代码和理解不同章节的区别和增量内容。

另请注意,以下文字将引用源代码文件(例如`**/memory.rs`)或在本教程的第一批教程中尚不存在的功能。 它们将被逐渐添加到本教程。

玩的开心!

## 代码组织和结构

代码被划分成不同的*模块*,每个模块代表一个内核典型的子系统。子系统的顶层模块文件直接位于`src`文件夹中。例如,`src/memory.rs`这个包含了所有与内存管理有关的代码。

## 处理器架构代码的可见性

有的内核的子系统是基于特定目标架构的处理器的低级代码。对于每种支持的处理器架构,都有一个子文件夹在`src/_arch`中。例如,`src/_arch/aarch64`

子模块系统在每个处理器架构的`src`文件夹中。例如,属于内核内存子系统(`src/memory.rs`)的代码将会被放在`src/_arch/aarch64/memory.rs`.后一个文件将被直接包含和重新导出到`src/memory.rs`中,以便架构代码部分是明显的遵循代码模块化。这意味着在`src/_arch/aarch64/memory.rs`中定义的公共函数foo()。仅可通过`crate :: memory :: foo()`访问。

`_arch`中的`_`表示此文件夹不属于标准模块层次结构。而是使用`#[path =“ _ arch/xxx/yyy.rs”]`属性将其内容有条件地引入各自的文件中。

## BSP 代码
`BSP` 表示 Board Support Package。`BSP`代码在`src/bsp.rs`中,而且包含目标主板特殊的定义和功能。这些是诸如主板的内存映射或相应主板上的设备驱动程序实例之类的东西。

就像处理器架构代码一样,`BSP`代码模块架构也是试着镜像`kernel`的子系统模块,但是这次它没有明显地包含和重新导出。这意味着必须从bsp名称空间开始调用提供的所有内容,例如,`bsp::driver::driver_manager()`。

## 内核接口

`arch`和`bsp`都包含根据实际目标和主板不同而编译的代码。例如,`interrupt controller`对于硬件`Raspberry Pi 3`和`Raspberry Pi 4`是不同的,但是我们想让`kernel`剩下的代码可以轻松地适配它们。

为了在`arch`,`bsp`和`generic kernel code`之间提供一个清晰的抽象,`interface`特征在*在可能的情况下*和*在可能的地方*被提供。它们在各自的子系统模块中定义,并有助于将程序的调用方法体现到接口,而不是具体实现上。例如,有一个通用IRQ处理接口,由两个树莓派不同的中断控制器驱动将实现的,并且仅将接口导出到`kernel`剩下的代码中。

```
        +-------------------+
        | Interface (Trait) |
        |                   |
        +--+-------------+--+
           ^             ^
           |             |
           |             |
+----------+--+       +--+----------+
| kernel code |       |  bsp code   |
|             |       |  arch code  |
+-------------+       +-------------+
```

# 总结
对于一个逻辑`kernel`子系统,相应的代码可以分布在几个物理位置。这里有个内存子系统的例子:
- `src/memory.rs` and `src/memory/**/*`
  - 与目标处理器体系结构和“BSP”特性无关的通用代码。
    - 例如: 将大块内存归零的函数
  - 通过`arch`和`BSP`代码实现的内存子系统接口。
    - 例如: 一个`MMU`接口定义的`MMU`功能原型
 - `src/bsp/__board_name__/memory.rs` 和 `src/bsp/__board_name__/memory/**/*`
   - `BSP` 具体代码.
   - 例如: 主板内存映射 (DRAM物理地址 和 MMIO 设备).
- `src/_arch/__arch_name__/memory.rs` 和 `src/_arch/__arch_name__/memory/**/*`
  - 处理器架构的具体代码。
  - 例如:为`__arch_name__` 处理器架构实现的`MMU`接口。
  
从一个命名空间角度来看,内存子系统代码在:
  - `crate::memory::*`
  - `crate::bsp::memory::*`


================================================
FILE: 00_before_we_start/README.ES.md
================================================
# Antes de comenzar

El texto a continuación es una copia 1:1 de la documentación que 
puede ser encontrada al principio del archivo del código fuente 
del núcleo (kernel) en cada tutorial. Esta describe la estructura 
general del código fuente, e intenta transmitir la filosofía detrás
de cada enfoque. Por favor leélo para familiarizarte
con lo que te vas a encontrar durante los tutoriales. Te ayudará a navegar el código de una mejor manera y a entender las diferencias y agregados entre los diferentes tutoriales.

Por favor, nota también que el siguiente texto va a referenciar
los archivos del código fuente (p. e.j. `**/memory.rs`) o funciones que
no van a existir aún en los primeros tutoriales. Estos archivos serán agregados 
a medida que el tutorial avance.

¡Diviértanse!

# La estructura del código y la arquitectura

El código está dividido en diferentes módulos donde cada uno representa un
subsistema típico del `kernel (núcleo)`. Los módulos de más alto nivel de los subsistemas se encuentran directamente en la carpeta `src`.
Por ejemplo, `src/memory.rs` contiene el código que está relacionado
con el manejo de memoria.

## Visibilidad del código de arquitectura del procesador

Algunos de los subsistemas del `núcleo (kernel)` dependen del código de bajo nivel (low-level) dedicado a la arquitectura del procesador.
Por cada arquitectura de procesador que está soportada, existe una subcarpeta en `src/_arch`, por ejemplo, `src/_arch/aarch64`.

La carpeta de arquitecturas refleja los módulos del subsistema establecidos en `src`. Por ejemplo, el código de arquitectura que pertenece al subsistema MMU del `núcleo(kernel)` (`src/memory/mmu.rs`) irá dentro de (`src/_arch/aarch64/memory/mmu.rs`).
Este archivo puede ser cargado como un módulo en `src/memory/mmu.rs` usando el `path attribute` (atributo de ruta). Usualmente, el nombre del módulo elegido es el nombre del módulo genérico con el prefijo de `arch_`

Por ejemplo, esta es la parte superior de `src/memory/mmu.rs`:

```
#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/memory/mmu.rs"]
mod arch_mmu;
```

En muchas ocasiones, los elementos de `arch_module` serán reexportados públicamente por el módulo principal.
De esta manera, cada módulo específico de la arquitectura puede proporcionar su implementación de un elemento, mientras que el *invocante* no debe de preocuparse por la arquitectura que se ha compilado condicionalmente.

## Código BSP

`BSP` significa Board Support Package (Paquete de Soporte de la Placa).
El código `BSP` está dentro de `src/bsp.rs` y contiene las definiciones y funciones de la placa base específica elegida. 
Entre estas cosas se encuentran diferentes elementos como el mapa de memoria de la placa o instancias de controladores para dispositivos que se presentan en la placa elegida.

Justo como el código de la arquitectura del procesador, la estructura del módulo del código `BSP` trata de reflejar los módulos del subsistema del `núcleo (kernel)`, pero no ocurre una reexportación esta vez. Eso significa que lo que sea que se esté proporcionando debe ser llamado empezando por el *namespace* (espacio de nombres) de `bsp`, p. ej. `bsp::driver::driver_manager()`.

## La interfaz del núcleo (kernel)

El `arch` y el `bsp` contienen código que se compilará condicionalmente dependiendo del procesador y placa actual para la que se compila el núcleo (kernel).
Por ejemplo, el hardware de control de interrupciones de la `Raspberry Pi 3` y la  `Raspberry Pi 4` es diferente, pero nosotros queremos que el resto del código del kernel funcione correctamente con cualquiera de los dos sin mucha complicación.

Para poder dar una limpia abstracción entre `arch`, `bsp` y código genérico del núcleo, los rasgos de `interface` se proporcionan *siempre y cuando tenga sentido*. Son definidos en su módulo de subsistema correspondiente y ayuda a reforzar el patrón de programar con respecto a una interfaz, sin importar la implementación concreta.

Por ejemplo, habrá una *IRQ handling interface* (interfaz de manejo de interrupciones) común, el cual los dos diferentes controladores de ambas `Raspberry` implementarán, y solo exportarán la interfaz común al resto del `núcleo (kernel)`.

```
        +-------------------+
        | Interface (Trait) |
        |                   |
        +--+-------------+--+
           ^             ^
           |             |
           |             |
+----------+--+       +--+----------+
| kernel code |       |  bsp code   |
|             |       |  arch code  |
+-------------+       +-------------+
```

# Resumen

Para un subsistema lógico del `núcleo (kernel)`, el código correspondiente puede ser distribuido sobre diferentes localizaciones físicas. Aquí un ejemplo para el subsistema de memoria:

- `src/memory.rs` y `src/memory/**/*`
  
  - Código común que es independiente de la arquitectura del procesador de destino y las características de la placa (`BSP`).
    - Ejemplo: Una función para poner a cero un trozo de memoria.
  - Las interfaces para el subsistema de la memoria que son implementados por código de `arch` o `BSP`.
    - Ejemplo: Una interfaz `MMU` que define prototipos de función de `MMU`.

- `src/bsp/__board_name__/memory.rs` y `src/bsp/__board_name__/memory/**/*`
  
  - Código específico de `BSP`.
  - Ejemplo: El mapa de memoria de la placa (direcciones físicas de DRAM y dispositivos MMIO).

- `src/_arch/__arch_name__/memory.rs` y `src/_arch/__arch_name__/memory/**/*`
  
  - El código específico de la arquitectura del procesador.
  - Ejemplo: Implementación de la interfaz `MMU` para la arquitectura `__arch_name__`.

Desde una perspectiva de *namespace*, el código del subsistema de **memoria** vive en:

- `crate::memory::*`
- `crate::bsp::memory::*`

# Flujo de Boot / Boot flow

1. El punto de entrada del núcleo (kernel) es la función `cpu::boot::arch_boot::_start()`.
   - Está implementado en `src/_arch/__arch_name__/cpu/boot.s`.


================================================
FILE: 00_before_we_start/README.md
================================================
# Before we start

The following text is a 1:1 copy of the documentation that can be found at the top of the kernel's
main source code file in each tutorial. It describes the general structure of the source code, and
tries to convey the philosophy behind the respective approach. Please read it to make yourself
familiar with what you will encounter during the tutorials. It will help you to navigate the code
better and understand the differences and additions between the separate tutorials.

Please also note that the following text will reference source code files (e.g. `**/memory.rs`) or
functions that won't exist yet in the first bunch of the tutorials. They will be added gradually as
the tutorials advance.

Have fun!

# Code organization and architecture

The code is divided into different *modules*, each representing a typical **subsystem** of the
`kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example,
`src/memory.rs` contains code that is concerned with all things memory management.

## Visibility of processor architecture code

Some of the `kernel`'s subsystems depend on low-level code that is specific to the target processor
architecture. For each supported processor architecture, there exists a subfolder in `src/_arch`,
for example, `src/_arch/aarch64`.

The architecture folders mirror the subsystem modules laid out in `src`. For example, architectural
code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go into
`src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in `src/memory/mmu.rs`
using the `path attribute`. Usually, the chosen module name is the generic module's name prefixed
with `arch_`.

For example, this is the top of `src/memory/mmu.rs`:

```
#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/memory/mmu.rs"]
mod arch_mmu;
```

Often times, items from the `arch_ module` will be publicly reexported by the parent module. This
way, each architecture specific module can provide its implementation of an item, while the caller
must not be concerned which architecture has been conditionally compiled.

## BSP code

`BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains
target board specific definitions and functions. These are things such as the board's memory map or
instances of drivers for devices that are featured on the respective board.

Just like processor architecture code, the `BSP` code's module structure tries to mirror the
`kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is provided
must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`.

## Kernel interfaces

Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target and
board for which the kernel is compiled. For example, the `interrupt controller` hardware of the
`Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel` code to
play nicely with any of the two without much hassle.

In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`, `interface`
traits are provided *whenever possible* and *where it makes sense*. They are defined in the
respective subsystem module and help to enforce the idiom of *program to an interface, not an
implementation*. For example, there will be a common IRQ handling interface which the two different
interrupt controller `drivers` of both Raspberrys will implement, and only export the interface to
the rest of the `kernel`.

```
        +-------------------+
        | Interface (Trait) |
        |                   |
        +--+-------------+--+
           ^             ^
           |             |
           |             |
+----------+--+       +--+----------+
| kernel code |       |  bsp code   |
|             |       |  arch code  |
+-------------+       +-------------+
```

# Summary

For a logical `kernel` subsystem, corresponding code can be distributed over several physical
locations. Here is an example for the **memory** subsystem:

- `src/memory.rs` and `src/memory/**/*`
  - Common code that is agnostic of target processor architecture and `BSP` characteristics.
    - Example: A function to zero a chunk of memory.
  - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code.
    - Example: An `MMU` interface that defines `MMU` function prototypes.
- `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*`
  - `BSP` specific code.
  - Example: The board's memory map (physical addresses of DRAM and MMIO devices).
- `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*`
  - Processor architecture specific code.
  - Example: Implementation of the `MMU` interface for the `__arch_name__` processor
    architecture.

From a namespace perspective, **memory** subsystem code lives in:

- `crate::memory::*`
- `crate::bsp::memory::*`

# Boot flow

1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
    - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.




================================================
FILE: 01_wait_forever/.vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 01_wait_forever/Cargo.toml
================================================
[package]
name = "mingo"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2021"

[profile.release]
lto = true

[features]
default = []
bsp_rpi3 = []
bsp_rpi4 = []

[[bin]]
name = "kernel"
path = "src/main.rs"

##--------------------------------------------------------------------------------------------------
## Dependencies
##--------------------------------------------------------------------------------------------------

[dependencies]

================================================
FILE: 01_wait_forever/Makefile
================================================
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

include ../common/docker.mk
include ../common/format.mk
include ../common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi3.
BSP ?= rpi3



##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi3)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE = raspi3
    QEMU_RELEASE_ARGS = -d in_asm -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a53
else ifeq ($(BSP),rpi4)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE =
    QEMU_RELEASE_ARGS = -d in_asm -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a72
endif

# Export for build.rs.
export LD_SCRIPT_PATH



##--------------------------------------------------------------------------------------------------
## Targets and Prerequisites
##--------------------------------------------------------------------------------------------------
KERNEL_MANIFEST      = Cargo.toml
KERNEL_LINKER_SCRIPT = kernel.ld
LAST_BUILD_CONFIG    = target/$(BSP).build_config

KERNEL_ELF      = target/$(TARGET)/release/kernel
# This parses cargo's dep-info file.
# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files
KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG)



##--------------------------------------------------------------------------------------------------
## Command building blocks
##--------------------------------------------------------------------------------------------------
RUSTFLAGS = $(RUSTC_MISC_ARGS)                   \
    -C link-arg=--library-path=$(LD_SCRIPT_PATH) \
    -C link-arg=--script=$(KERNEL_LINKER_SCRIPT)

RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \
    -D warnings                   \
    -D missing_docs

FEATURES      = --features bsp_$(BSP)
COMPILER_ARGS = --target=$(TARGET) \
    $(FEATURES)                    \
    --release

RUSTC_CMD   = cargo rustc $(COMPILER_ARGS)
DOC_CMD     = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD  = cargo clippy $(COMPILER_ARGS)
OBJCOPY_CMD = rust-objcopy \
    --strip-all            \
    -O binary

EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD          = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)



##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all doc qemu clippy clean readelf objdump nm check

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Save the configuration as a file, so make understands if it changed.
##------------------------------------------------------------------------------
$(LAST_BUILD_CONFIG):
	@rm -f target/*.build_config
	@mkdir -p target
	@touch $(LAST_BUILD_CONFIG)

##------------------------------------------------------------------------------
## Compile the kernel ELF
##------------------------------------------------------------------------------
$(KERNEL_ELF): $(KERNEL_ELF_DEPS)
	$(call color_header, "Compiling kernel ELF - $(BSP)")
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
## Generate the stripped kernel binary
##------------------------------------------------------------------------------
$(KERNEL_BIN): $(KERNEL_ELF)
	$(call color_header, "Generating stripped binary")
	@$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN)
	$(call color_progress_prefix, "Name")
	@echo $(KERNEL_BIN)
	$(call color_progress_prefix, "Size")
	$(call disk_usage_KiB, $(KERNEL_BIN))

##------------------------------------------------------------------------------
## Generate the documentation
##------------------------------------------------------------------------------
doc:
	$(call color_header, "Generating docs")
	@$(DOC_CMD) --document-private-items --open

##------------------------------------------------------------------------------
## Run the kernel in QEMU
##------------------------------------------------------------------------------
ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

qemu:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

qemu: $(KERNEL_BIN)
	$(call color_header, "Launching QEMU")
	@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
endif

##------------------------------------------------------------------------------
## Run clippy
##------------------------------------------------------------------------------
clippy:
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)

##------------------------------------------------------------------------------
## Clean
##------------------------------------------------------------------------------
clean:
	rm -rf target $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Run readelf
##------------------------------------------------------------------------------
readelf: $(KERNEL_ELF)
	$(call color_header, "Launching readelf")
	@$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF)

##------------------------------------------------------------------------------
## Run objdump
##------------------------------------------------------------------------------
objdump: $(KERNEL_ELF)
	$(call color_header, "Launching objdump")
	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                --section .text   \
                $(KERNEL_ELF) | rustfilt

##------------------------------------------------------------------------------
## Run nm
##------------------------------------------------------------------------------
nm: $(KERNEL_ELF)
	$(call color_header, "Launching nm")
	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt



================================================
FILE: 01_wait_forever/README.CN.md
================================================
# 教程 01 - 一直等待(死循环)

## tl;dr

项目框架已经构建完成;目前代码做的仅仅是挂起CPU核心执行内核代码。

-  `Makefile` 目标项:
    - `doc`: 生成文档。
    - `qemu`: 在 QEMU 中运行 `kernel`。
    - `clippy`
    - `clean`
    - `readelf`: 检查 `ELF` 输出。
    - `objdump`: 检查汇编。
    - `nm`: 检查符号。
- 代码按照 `kernel`, `arch` 和 `BSP` (板级支持包)的形式组织。
    - 条件编译会根据用户提供的参数编译各自的  `arch` 和  `BSP` 的内容。
- 自定义 `kernel.ld` 链接脚本.
    - 载入地址为 `0x80_000`
    - 目前仅有 `.text` 小节(section)。
- `main.rs`: 重要的 [inner attributes]:
    - `#![no_std]`, `#![no_main]`
- 汇编函数 `_start()` 会执行  `wfe` (Wait For Event), 并挂起所有正在执行  `_start()` 的核心。
- 我们(必须)定义一个 `#[panic_handler]` 函数。
    - 用于等待cpu事件的发生。

[inner attributes]: https://doc.rust-lang.org/reference/attributes.html

### 测试一下!

在项目文件夹下调用 QEMU 并观察在 `wfe` 中CPU核心的运转情况:
```console
» make qemu
[...]
IN:
0x00080000:  d503205f  wfe
0x00080004:  17ffffff  b        #0x80000
```


================================================
FILE: 01_wait_forever/README.ES.md
================================================
# Tutorial 01 - Esperar infinitamente

## tl;dr

* Se configura la estructura que tiene el proyecto.

* Se ejecuta una pequeño código hecho en ensamblador que tiene como función detener todos los núcleos del procesador que están ejecutando el kernel.

## Compilar

* El archivo `Makefile` permite ejecutar:

  * `doc`: Genera la documentación.

  * `qemu`: Ejecutar el kernel en QEMU.

  * `clippy`: Analiza el código y sugiere mejoras.

  * `clean`: Elimina todos los archivos generados durante la compilación, etc.

  * `readelf`: Inspecciona el archivo `ELF` de salida.

  * `objdump`: Inspecciona el ensamblador.

  * `nm`: Inspecciona los símbolos.

## Código a revisar

* El script para enlazado específico para la `BSP` llamado `kernel.ld`.

  * Carga la dirección en `0x8_0000`.

  * Solo la sección `.text`.

* `main.rs`: [Atributos internos](https://doc.rust-lang.org/reference/attributes.html) importantes:

  * `#![no_std]`, `#![no_main]`.

* `boot.s`: La función de ensamblador `_start()` que inicia `wfe` (Wait For Event / Esperar Hasta Un Evento), detiene todos los núcleos del procesador que están ejecutando `_start()`.

* Tenemos que definir una función que funcione como `#[panic_handler]` (manejador de pánico) para que el compilador no nos cause problemas.

  * Hazla `unimplemented!()` porque se eliminará ya que no está siendo usada.

## Pruébalo

Dentro de la carpeta del proyecto, ejecuta a QEMU y mira el núcleo del procesador ejecutando `wfe` en bucle:

```
$ make qemu
[...]
IN:
0x00080000:  d503205f  wfe
0x00080004:  17ffffff  b        #0x80000
```


================================================
FILE: 01_wait_forever/README.md
================================================
# Tutorial 01 - Wait Forever

## tl;dr

- The project skeleton is set up.
- A small piece of assembly code runs that just halts all CPU cores executing the kernel code.

## Building

- `Makefile` targets:
    - `doc`: Generate documentation.
    - `qemu`: Run the `kernel` in QEMU
    - `clippy`
    - `clean`
    - `readelf`: Inspect the `ELF` output.
    - `objdump`: Inspect the assembly.
    - `nm`: Inspect the symbols.

## Code to look at

- `BSP`-specific `kernel.ld` linker script.
    - Load address at `0x8_0000`
    - Only `.text` section.
- `main.rs`: Important [inner attributes]:
    - `#![no_std]`, `#![no_main]`
- `boot.s`: Assembly `_start()` function that executes `wfe` (Wait For Event), halting all cores
  that are executing `_start()`.
- We (have to) define a `#[panic_handler]` function to make the compiler happy.
    - Make it `unimplemented!()` because it will be stripped out since it is not used.

[inner attributes]: https://doc.rust-lang.org/reference/attributes.html

### Test it

In the project folder, invoke QEMU and observe the CPU core spinning on `wfe`:

```console
$ make qemu
[...]
IN:
0x00080000:  d503205f  wfe
0x00080004:  17ffffff  b        #0x80000
```


================================================
FILE: 01_wait_forever/build.rs
================================================
use std::{env, fs, process};

fn main() {
    let ld_script_path = match env::var("LD_SCRIPT_PATH") {
        Ok(var) => var,
        _ => process::exit(0),
    };

    let files = fs::read_dir(ld_script_path).unwrap();
    files
        .filter_map(Result::ok)
        .filter(|d| {
            if let Some(e) = d.path().extension() {
                e == "ld"
            } else {
                false
            }
        })
        .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display()));
}


================================================
FILE: 01_wait_forever/src/_arch/aarch64/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural boot code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::boot::arch_boot

use core::arch::global_asm;

// Assembly counterpart to this file.
global_asm!(include_str!("boot.s"));


================================================
FILE: 01_wait_forever/src/_arch/aarch64/cpu/boot.s
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
.section .text._start

//------------------------------------------------------------------------------
// fn _start()
//------------------------------------------------------------------------------
_start:
	// Infinitely wait for events (aka "park the core").
.L_parking_loop:
	wfe
	b	.L_parking_loop

.size	_start, . - _start
.type	_start, function
.global	_start


================================================
FILE: 01_wait_forever/src/bsp/raspberrypi/kernel.ld
================================================
/* SPDX-License-Identifier: MIT OR Apache-2.0
 *
 * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
 */

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;


ENTRY(__rpi_phys_binary_load_addr)

/* Flags:
 *     4 == R
 *     5 == RX
 *     6 == RW
 */
PHDRS
{
    segment_code PT_LOAD FLAGS(5);
}

SECTIONS
{
    . =  __rpi_phys_binary_load_addr;

    /***********************************************************************************************
    * Code
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
    } :segment_code
}


================================================
FILE: 01_wait_forever/src/bsp/raspberrypi.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Top-level BSP file for the Raspberry Pi 3 and 4.

// Coming soon.


================================================
FILE: 01_wait_forever/src/bsp.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Conditional reexporting of Board Support Packages.

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
mod raspberrypi;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;


================================================
FILE: 01_wait_forever/src/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Boot code.

#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/cpu/boot.rs"]
mod arch_boot;


================================================
FILE: 01_wait_forever/src/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>

//! Processor code.

mod boot;


================================================
FILE: 01_wait_forever/src/main.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

// Rust embedded logo for `make doc`.
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png"
)]

//! The `kernel` binary.
//!
//! # Code organization and architecture
//!
//! The code is divided into different *modules*, each representing a typical **subsystem** of the
//! `kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example,
//! `src/memory.rs` contains code that is concerned with all things memory management.
//!
//! ## Visibility of processor architecture code
//!
//! Some of the `kernel`'s subsystems depend on low-level code that is specific to the target
//! processor architecture. For each supported processor architecture, there exists a subfolder in
//! `src/_arch`, for example, `src/_arch/aarch64`.
//!
//! The architecture folders mirror the subsystem modules laid out in `src`. For example,
//! architectural code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go
//! into `src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in
//! `src/memory/mmu.rs` using the `path attribute`. Usually, the chosen module name is the generic
//! module's name prefixed with `arch_`.
//!
//! For example, this is the top of `src/memory/mmu.rs`:
//!
//! ```
//! #[cfg(target_arch = "aarch64")]
//! #[path = "../_arch/aarch64/memory/mmu.rs"]
//! mod arch_mmu;
//! ```
//!
//! Often times, items from the `arch_ module` will be publicly reexported by the parent module.
//! This way, each architecture specific module can provide its implementation of an item, while the
//! caller must not be concerned which architecture has been conditionally compiled.
//!
//! ## BSP code
//!
//! `BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains
//! target board specific definitions and functions. These are things such as the board's memory map
//! or instances of drivers for devices that are featured on the respective board.
//!
//! Just like processor architecture code, the `BSP` code's module structure tries to mirror the
//! `kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is
//! provided must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`.
//!
//! ## Kernel interfaces
//!
//! Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target
//! and board for which the kernel is compiled. For example, the `interrupt controller` hardware of
//! the `Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel`
//! code to play nicely with any of the two without much hassle.
//!
//! In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`,
//! `interface` traits are provided *whenever possible* and *where it makes sense*. They are defined
//! in the respective subsystem module and help to enforce the idiom of *program to an interface,
//! not an implementation*. For example, there will be a common IRQ handling interface which the two
//! different interrupt controller `drivers` of both Raspberrys will implement, and only export the
//! interface to the rest of the `kernel`.
//!
//! ```
//!         +-------------------+
//!         | Interface (Trait) |
//!         |                   |
//!         +--+-------------+--+
//!            ^             ^
//!            |             |
//!            |             |
//! +----------+--+       +--+----------+
//! | kernel code |       |  bsp code   |
//! |             |       |  arch code  |
//! +-------------+       +-------------+
//! ```
//!
//! # Summary
//!
//! For a logical `kernel` subsystem, corresponding code can be distributed over several physical
//! locations. Here is an example for the **memory** subsystem:
//!
//! - `src/memory.rs` and `src/memory/**/*`
//!   - Common code that is agnostic of target processor architecture and `BSP` characteristics.
//!     - Example: A function to zero a chunk of memory.
//!   - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code.
//!     - Example: An `MMU` interface that defines `MMU` function prototypes.
//! - `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*`
//!   - `BSP` specific code.
//!   - Example: The board's memory map (physical addresses of DRAM and MMIO devices).
//! - `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*`
//!   - Processor architecture specific code.
//!   - Example: Implementation of the `MMU` interface for the `__arch_name__` processor
//!     architecture.
//!
//! From a namespace perspective, **memory** subsystem code lives in:
//!
//! - `crate::memory::*`
//! - `crate::bsp::memory::*`
//!
//! # Boot flow
//!
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
//!     - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.

#![no_main]
#![no_std]

mod bsp;
mod cpu;
mod panic_wait;

// Kernel code coming next tutorial.


================================================
FILE: 01_wait_forever/src/panic_wait.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! A panic handler that infinitely waits.

use core::panic::PanicInfo;

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    unimplemented!()
}


================================================
FILE: 02_runtime_init/.vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 02_runtime_init/Cargo.toml
================================================
[package]
name = "mingo"
version = "0.2.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2021"

[profile.release]
lto = true

[features]
default = []
bsp_rpi3 = []
bsp_rpi4 = []

[[bin]]
name = "kernel"
path = "src/main.rs"

##--------------------------------------------------------------------------------------------------
## Dependencies
##--------------------------------------------------------------------------------------------------

[dependencies]

# Platform specific dependencies
[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = { version = "9.x.x" }


================================================
FILE: 02_runtime_init/Makefile
================================================
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

include ../common/docker.mk
include ../common/format.mk
include ../common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi3.
BSP ?= rpi3



##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi3)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE = raspi3
    QEMU_RELEASE_ARGS = -d in_asm -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a53
else ifeq ($(BSP),rpi4)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE =
    QEMU_RELEASE_ARGS = -d in_asm -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a72
endif

# Export for build.rs.
export LD_SCRIPT_PATH



##--------------------------------------------------------------------------------------------------
## Targets and Prerequisites
##--------------------------------------------------------------------------------------------------
KERNEL_MANIFEST      = Cargo.toml
KERNEL_LINKER_SCRIPT = kernel.ld
LAST_BUILD_CONFIG    = target/$(BSP).build_config

KERNEL_ELF      = target/$(TARGET)/release/kernel
# This parses cargo's dep-info file.
# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files
KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG)



##--------------------------------------------------------------------------------------------------
## Command building blocks
##--------------------------------------------------------------------------------------------------
RUSTFLAGS = $(RUSTC_MISC_ARGS)                   \
    -C link-arg=--library-path=$(LD_SCRIPT_PATH) \
    -C link-arg=--script=$(KERNEL_LINKER_SCRIPT)

RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \
    -D warnings                   \
    -D missing_docs

FEATURES      = --features bsp_$(BSP)
COMPILER_ARGS = --target=$(TARGET) \
    $(FEATURES)                    \
    --release

RUSTC_CMD   = cargo rustc $(COMPILER_ARGS)
DOC_CMD     = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD  = cargo clippy $(COMPILER_ARGS)
OBJCOPY_CMD = rust-objcopy \
    --strip-all            \
    -O binary

EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD          = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)



##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all doc qemu clippy clean readelf objdump nm check

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Save the configuration as a file, so make understands if it changed.
##------------------------------------------------------------------------------
$(LAST_BUILD_CONFIG):
	@rm -f target/*.build_config
	@mkdir -p target
	@touch $(LAST_BUILD_CONFIG)

##------------------------------------------------------------------------------
## Compile the kernel ELF
##------------------------------------------------------------------------------
$(KERNEL_ELF): $(KERNEL_ELF_DEPS)
	$(call color_header, "Compiling kernel ELF - $(BSP)")
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
## Generate the stripped kernel binary
##------------------------------------------------------------------------------
$(KERNEL_BIN): $(KERNEL_ELF)
	$(call color_header, "Generating stripped binary")
	@$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN)
	$(call color_progress_prefix, "Name")
	@echo $(KERNEL_BIN)
	$(call color_progress_prefix, "Size")
	$(call disk_usage_KiB, $(KERNEL_BIN))

##------------------------------------------------------------------------------
## Generate the documentation
##------------------------------------------------------------------------------
doc:
	$(call color_header, "Generating docs")
	@$(DOC_CMD) --document-private-items --open

##------------------------------------------------------------------------------
## Run the kernel in QEMU
##------------------------------------------------------------------------------
ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

qemu:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

qemu: $(KERNEL_BIN)
	$(call color_header, "Launching QEMU")
	@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
endif

##------------------------------------------------------------------------------
## Run clippy
##------------------------------------------------------------------------------
clippy:
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)

##------------------------------------------------------------------------------
## Clean
##------------------------------------------------------------------------------
clean:
	rm -rf target $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Run readelf
##------------------------------------------------------------------------------
readelf: $(KERNEL_ELF)
	$(call color_header, "Launching readelf")
	@$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF)

##------------------------------------------------------------------------------
## Run objdump
##------------------------------------------------------------------------------
objdump: $(KERNEL_ELF)
	$(call color_header, "Launching objdump")
	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                --section .text   \
                --section .rodata \
                $(KERNEL_ELF) | rustfilt

##------------------------------------------------------------------------------
## Run nm
##------------------------------------------------------------------------------
nm: $(KERNEL_ELF)
	$(call color_header, "Launching nm")
	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt



================================================
FILE: 02_runtime_init/README.CN.md
================================================
# 教程 02 - 执行初始化

## tl;dr

- 我们拓展了`boot.S`,在第一次启动的时候调用Rust代码。
  在跳转到rust代码前,对运行时进行了一些初始化工作。
- Rust通过调用`panic()`挂起CPU。
- 再次运行`make qemu`看看新增加的代码是怎么运行的。

## 值得注意的变化

- 链接脚本(linker script)中的变化:
     - 新程序段(sections): `.rodata`, `.got`, `.data`, `.bss`.
     - 使用一个独立的位置(`.text._start_arguments`)来保存`_start()`引导函数所使用的参数。
- `_start()` in `_arch/__arch_name__/cpu/boot.s`:
     1. 当核心不是`core0`第0号核心的时候,挂起该CPU核心。
     1. 通过清零`.bss`程序段来初始化`DRAM`.
     1. 初始化堆栈指针(`stack pointer`).
     1. 跳转到`arch/__arch_name__/cpu/boot.rs`文件中定义的`_start_rust()`函数
- `_start_rust()`:
     1. 它调用了`kernel_init()`, 这个函数又调用了`panic!()`, panic函数最终把`core0`和其他核心一样挂起了。
- 目前依赖 [aarch64-cpu] 程序库, 这个库零成本的包装了处理 CPU 资源时的“不安全”部分。
    - 详细请参考 `_arch/__arch_name__/cpu.rs`.

[bss]: https://en.wikipedia.org/wiki/.bss
[aarch64-cpu]: https://github.com/rust-embedded/aarch64-cpu

## 相比之前的变化(diff)
请检查[英文版本](README.md#diff-to-previous),这是最新的。



================================================
FILE: 02_runtime_init/README.ES.md
================================================
# Tutorial 02 - Inicialización del `runtime`

## tl;dr

* Extendimos la funcionalidad de `boot.s` para que sea capaz de llamar código Rust por primera vez. Antes de que el cambio a Rust ocurra, se realizan algunos trabajos de inicialización del `runtime` (soporte para ejecución de código).
* El código Rust que es llamado solo pausa la ejecución con una llamada a `panic!()`.
* Ejecuta `make qemu` de nuevo para que puedas ver el código adicional en acción.

## Adiciones importantes

* Adiciones importantes al script `kernel.ld`:

  * Nuevas secciones: `.rodata`, `.got`, `.data`, `.bss`.

  * Un lugar totalmente dedicado a enlazar argumentos de tiempo de arranque (boot-time) que necesitan estar listos cuando se llame a `_start()`.

* `_start()` en `_arch/__arch_name__/cpu/boot.s`:

  1. Para todos los núcleos expecto el núcleo 0.

  2. Inicializa la [`DRAM`](https://es.wikipedia.org/wiki/DRAM) poniendo a cero la sección [`.bss`](https://en.wikipedia.org/wiki/.bss).

  3. Configura el `stack pointer` (puntero a la memoria [pila](https://es.wikipedia.org/wiki/Pila_(inform%C3%A1tica))).

  4. Salta hacia la función `_start_rust()`, definida en `arch/__arch_name__/cpu/boot.rs`.

* `_start_rust()`:

  * Llama a `kernel_init()`, que llama a `panic!()`, que al final también pone al núcleo 0 en pausa.

* La librería ahora usa el crate [aarch64-cpu](https://github.com/rust-embedded/aarch64-cpu), que nos da abstracciones sin coste y envuelve las partes que hacen uso de un `unsafe` (partes con código que no es seguro y podría causar errores) cuando se trabaja directamente con los recursos del procesador.

  * Lo puedes ver en acción en `_arch/__arch_name__/cpu.rs`.

## Diferencia con el archivo anterior

Please check [the english version](README.md#diff-to-previous), which is kept up-to-date.


================================================
FILE: 02_runtime_init/README.md
================================================
# Tutorial 02 - Runtime Init

## tl;dr

- We extend `boot.s` to call into Rust code for the first time. Before the jump
  to Rust happens, a bit of runtime init work is done.
- The Rust code being called just halts execution with a call to `panic!()`.
- Check out `make qemu` again to see the additional code run.

## Notable additions

- More additions to the linker script:
     - New sections: `.rodata`, `.got`, `.data`, `.bss`.
     - A dedicated place for linking boot-time arguments that need to be read by `_start()`.
- `_start()` in `_arch/__arch_name__/cpu/boot.s`:
     1. Halts core if core != core0.
     1. Initializes the `DRAM` by zeroing the [bss] section.
     1. Sets up the `stack pointer`.
     1. Jumps to the `_start_rust()` function, defined in `arch/__arch_name__/cpu/boot.rs`.
- `_start_rust()`:
     - Calls `kernel_init()`, which calls `panic!()`, which eventually halts core0 as well.
- The library now uses the [aarch64-cpu] crate, which provides zero-overhead abstractions and wraps
  `unsafe` parts when dealing with the CPU's resources.
    - See it in action in `_arch/__arch_name__/cpu.rs`.

[bss]: https://en.wikipedia.org/wiki/.bss
[aarch64-cpu]: https://github.com/rust-embedded/aarch64-cpu

## Diff to previous
```diff

diff -uNr 01_wait_forever/Cargo.toml 02_runtime_init/Cargo.toml
--- 01_wait_forever/Cargo.toml
+++ 02_runtime_init/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mingo"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Andre Richter <andre.o.richter@gmail.com>"]
 edition = "2021"

@@ -21,3 +21,7 @@
 ##--------------------------------------------------------------------------------------------------

 [dependencies]
+
+# Platform specific dependencies
+[target.'cfg(target_arch = "aarch64")'.dependencies]
+aarch64-cpu = { version = "9.x.x" }

diff -uNr 01_wait_forever/Makefile 02_runtime_init/Makefile
--- 01_wait_forever/Makefile
+++ 02_runtime_init/Makefile
@@ -181,6 +181,7 @@
 	$(call color_header, "Launching objdump")
 	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                 --section .text   \
+                --section .rodata \
                 $(KERNEL_ELF) | rustfilt
 ##------------------------------------------------------------------------------

diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.rs 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.rs
+++ 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
@@ -14,4 +14,19 @@
 use core::arch::global_asm;

 // Assembly counterpart to this file.
-global_asm!(include_str!("boot.s"));
+global_asm!(
+    include_str!("boot.s"),
+    CONST_CORE_ID_MASK = const 0b11
+);
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// The Rust entry of the `kernel` binary.
+///
+/// The function is called from the assembly `_start` function.
+#[no_mangle]
+pub unsafe fn _start_rust() -> ! {
+    crate::kernel_init()
+}

diff -uNr 01_wait_forever/src/_arch/aarch64/cpu/boot.s 02_runtime_init/src/_arch/aarch64/cpu/boot.s
--- 01_wait_forever/src/_arch/aarch64/cpu/boot.s
+++ 02_runtime_init/src/_arch/aarch64/cpu/boot.s
@@ -3,6 +3,22 @@
 // Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

 //--------------------------------------------------------------------------------------------------
+// Definitions
+//--------------------------------------------------------------------------------------------------
+
+// Load the address of a symbol into a register, PC-relative.
+//
+// The symbol must lie within +/- 4 GiB of the Program Counter.
+//
+// # Resources
+//
+// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
+.macro ADR_REL register, symbol
+	adrp	\register, \symbol
+	add	\register, \register, #:lo12:\symbol
+.endm
+
+//--------------------------------------------------------------------------------------------------
 // Public Code
 //--------------------------------------------------------------------------------------------------
 .section .text._start
@@ -11,6 +27,34 @@
 // fn _start()
 //------------------------------------------------------------------------------
 _start:
+	// Only proceed on the boot core. Park it otherwise.
+	mrs	x0, MPIDR_EL1
+	and	x0, x0, {CONST_CORE_ID_MASK}
+	ldr	x1, BOOT_CORE_ID      // provided by bsp/__board_name__/cpu.rs
+	cmp	x0, x1
+	b.ne	.L_parking_loop
+
+	// If execution reaches here, it is the boot core.
+
+	// Initialize DRAM.
+	ADR_REL	x0, __bss_start
+	ADR_REL x1, __bss_end_exclusive
+
+.L_bss_init_loop:
+	cmp	x0, x1
+	b.eq	.L_prepare_rust
+	stp	xzr, xzr, [x0], #16
+	b	.L_bss_init_loop
+
+	// Prepare the jump to Rust code.
+.L_prepare_rust:
+	// Set the stack pointer.
+	ADR_REL	x0, __boot_core_stack_end_exclusive
+	mov	sp, x0
+
+	// Jump to Rust code.
+	b	_start_rust
+
 	// Infinitely wait for events (aka "park the core").
 .L_parking_loop:
 	wfe

diff -uNr 01_wait_forever/src/_arch/aarch64/cpu.rs 02_runtime_init/src/_arch/aarch64/cpu.rs
--- 01_wait_forever/src/_arch/aarch64/cpu.rs
+++ 02_runtime_init/src/_arch/aarch64/cpu.rs
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! Architectural processor code.
+//!
+//! # Orientation
+//!
+//! Since arch modules are imported into generic modules using the path attribute, the path of this
+//! file is:
+//!
+//! crate::cpu::arch_cpu
+
+use aarch64_cpu::asm;
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Pause execution on the core.
+#[inline(always)]
+pub fn wait_forever() -> ! {
+    loop {
+        asm::wfe()
+    }
+}

diff -uNr 01_wait_forever/src/bsp/raspberrypi/cpu.rs 02_runtime_init/src/bsp/raspberrypi/cpu.rs
--- 01_wait_forever/src/bsp/raspberrypi/cpu.rs
+++ 02_runtime_init/src/bsp/raspberrypi/cpu.rs
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! BSP Processor code.
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// Used by `arch` code to find the early boot core.
+#[no_mangle]
+#[link_section = ".text._start_arguments"]
+pub static BOOT_CORE_ID: u64 = 0;

diff -uNr 01_wait_forever/src/bsp/raspberrypi/kernel.ld 02_runtime_init/src/bsp/raspberrypi/kernel.ld
--- 01_wait_forever/src/bsp/raspberrypi/kernel.ld
+++ 02_runtime_init/src/bsp/raspberrypi/kernel.ld
@@ -3,6 +3,8 @@
  * Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
  */

+__rpi_phys_dram_start_addr = 0;
+
 /* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
 __rpi_phys_binary_load_addr = 0x80000;

@@ -13,21 +15,65 @@
  *     4 == R
  *     5 == RX
  *     6 == RW
+ *
+ * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
+ * It doesn't mean all of them need actually be loaded.
  */
 PHDRS
 {
-    segment_code PT_LOAD FLAGS(5);
+    segment_boot_core_stack PT_LOAD FLAGS(6);
+    segment_code            PT_LOAD FLAGS(5);
+    segment_data            PT_LOAD FLAGS(6);
 }

 SECTIONS
 {
-    . =  __rpi_phys_binary_load_addr;
+    . =  __rpi_phys_dram_start_addr;
+
+    /***********************************************************************************************
+    * Boot Core Stack
+    ***********************************************************************************************/
+    .boot_core_stack (NOLOAD) :
+    {
+                                             /*   ^             */
+                                             /*   | stack       */
+        . += __rpi_phys_binary_load_addr;    /*   | growth      */
+                                             /*   | direction   */
+        __boot_core_stack_end_exclusive = .; /*   |             */
+    } :segment_boot_core_stack

     /***********************************************************************************************
-    * Code
+    * Code + RO Data + Global Offset Table
     ***********************************************************************************************/
     .text :
     {
         KEEP(*(.text._start))
+        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
+        *(.text._start_rust)      /* The Rust entry point */
+        *(.text*)                 /* Everything else */
     } :segment_code
+
+    .rodata : ALIGN(8) { *(.rodata*) } :segment_code
+
+    /***********************************************************************************************
+    * Data + BSS
+    ***********************************************************************************************/
+    .data : { *(.data*) } :segment_data
+
+    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
+    .bss (NOLOAD) : ALIGN(16)
+    {
+        __bss_start = .;
+        *(.bss*);
+        . = ALIGN(16);
+        __bss_end_exclusive = .;
+    } :segment_data
+
+    /***********************************************************************************************
+    * Misc
+    ***********************************************************************************************/
+    .got : { *(.got*) }
+    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")
+
+    /DISCARD/ : { *(.comment*) }
 }

diff -uNr 01_wait_forever/src/bsp/raspberrypi.rs 02_runtime_init/src/bsp/raspberrypi.rs
--- 01_wait_forever/src/bsp/raspberrypi.rs
+++ 02_runtime_init/src/bsp/raspberrypi.rs
@@ -4,4 +4,4 @@

 //! Top-level BSP file for the Raspberry Pi 3 and 4.

-// Coming soon.
+pub mod cpu;

diff -uNr 01_wait_forever/src/cpu.rs 02_runtime_init/src/cpu.rs
--- 01_wait_forever/src/cpu.rs
+++ 02_runtime_init/src/cpu.rs
@@ -4,4 +4,13 @@

 //! Processor code.

+#[cfg(target_arch = "aarch64")]
+#[path = "_arch/aarch64/cpu.rs"]
+mod arch_cpu;
+
 mod boot;
+
+//--------------------------------------------------------------------------------------------------
+// Architectural Public Reexports
+//--------------------------------------------------------------------------------------------------
+pub use arch_cpu::wait_forever;

diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs
--- 01_wait_forever/src/main.rs
+++ 02_runtime_init/src/main.rs
@@ -104,7 +104,9 @@
 //!
 //! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
 //!     - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.
+//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.

+#![feature(asm_const)]
 #![no_main]
 #![no_std]

@@ -112,4 +114,11 @@
 mod cpu;
 mod panic_wait;

-// Kernel code coming next tutorial.
+/// Early init code.
+///
+/// # Safety
+///
+/// - Only a single core must be active and running this function.
+unsafe fn kernel_init() -> ! {
+    panic!()
+}

diff -uNr 01_wait_forever/src/panic_wait.rs 02_runtime_init/src/panic_wait.rs
--- 01_wait_forever/src/panic_wait.rs
+++ 02_runtime_init/src/panic_wait.rs
@@ -4,6 +4,7 @@

 //! A panic handler that infinitely waits.

+use crate::cpu;
 use core::panic::PanicInfo;

 //--------------------------------------------------------------------------------------------------
@@ -12,5 +13,5 @@

 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
-    unimplemented!()
+    cpu::wait_forever()
 }

```


================================================
FILE: 02_runtime_init/build.rs
================================================
use std::{env, fs, process};

fn main() {
    let ld_script_path = match env::var("LD_SCRIPT_PATH") {
        Ok(var) => var,
        _ => process::exit(0),
    };

    let files = fs::read_dir(ld_script_path).unwrap();
    files
        .filter_map(Result::ok)
        .filter(|d| {
            if let Some(e) = d.path().extension() {
                e == "ld"
            } else {
                false
            }
        })
        .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display()));
}


================================================
FILE: 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural boot code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::boot::arch_boot

use core::arch::global_asm;

// Assembly counterpart to this file.
global_asm!(
    include_str!("boot.s"),
    CONST_CORE_ID_MASK = const 0b11
);

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// The Rust entry of the `kernel` binary.
///
/// The function is called from the assembly `_start` function.
#[no_mangle]
pub unsafe fn _start_rust() -> ! {
    crate::kernel_init()
}


================================================
FILE: 02_runtime_init/src/_arch/aarch64/cpu/boot.s
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>

//--------------------------------------------------------------------------------------------------
// Definitions
//--------------------------------------------------------------------------------------------------

// Load the address of a symbol into a register, PC-relative.
//
// The symbol must lie within +/- 4 GiB of the Program Counter.
//
// # Resources
//
// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
.macro ADR_REL register, symbol
	adrp	\register, \symbol
	add	\register, \register, #:lo12:\symbol
.endm

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
.section .text._start

//------------------------------------------------------------------------------
// fn _start()
//------------------------------------------------------------------------------
_start:
	// Only proceed on the boot core. Park it otherwise.
	mrs	x0, MPIDR_EL1
	and	x0, x0, {CONST_CORE_ID_MASK}
	ldr	x1, BOOT_CORE_ID      // provided by bsp/__board_name__/cpu.rs
	cmp	x0, x1
	b.ne	.L_parking_loop

	// If execution reaches here, it is the boot core.

	// Initialize DRAM.
	ADR_REL	x0, __bss_start
	ADR_REL x1, __bss_end_exclusive

.L_bss_init_loop:
	cmp	x0, x1
	b.eq	.L_prepare_rust
	stp	xzr, xzr, [x0], #16
	b	.L_bss_init_loop

	// Prepare the jump to Rust code.
.L_prepare_rust:
	// Set the stack pointer.
	ADR_REL	x0, __boot_core_stack_end_exclusive
	mov	sp, x0

	// Jump to Rust code.
	b	_start_rust

	// Infinitely wait for events (aka "park the core").
.L_parking_loop:
	wfe
	b	.L_parking_loop

.size	_start, . - _start
.type	_start, function
.global	_start


================================================
FILE: 02_runtime_init/src/_arch/aarch64/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural processor code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::arch_cpu

use aarch64_cpu::asm;

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Pause execution on the core.
#[inline(always)]
pub fn wait_forever() -> ! {
    loop {
        asm::wfe()
    }
}


================================================
FILE: 02_runtime_init/src/bsp/raspberrypi/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! BSP Processor code.

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Used by `arch` code to find the early boot core.
#[no_mangle]
#[link_section = ".text._start_arguments"]
pub static BOOT_CORE_ID: u64 = 0;


================================================
FILE: 02_runtime_init/src/bsp/raspberrypi/kernel.ld
================================================
/* SPDX-License-Identifier: MIT OR Apache-2.0
 *
 * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
 */

__rpi_phys_dram_start_addr = 0;

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;


ENTRY(__rpi_phys_binary_load_addr)

/* Flags:
 *     4 == R
 *     5 == RX
 *     6 == RW
 *
 * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
 * It doesn't mean all of them need actually be loaded.
 */
PHDRS
{
    segment_boot_core_stack PT_LOAD FLAGS(6);
    segment_code            PT_LOAD FLAGS(5);
    segment_data            PT_LOAD FLAGS(6);
}

SECTIONS
{
    . =  __rpi_phys_dram_start_addr;

    /***********************************************************************************************
    * Boot Core Stack
    ***********************************************************************************************/
    .boot_core_stack (NOLOAD) :
    {
                                             /*   ^             */
                                             /*   | stack       */
        . += __rpi_phys_binary_load_addr;    /*   | growth      */
                                             /*   | direction   */
        __boot_core_stack_end_exclusive = .; /*   |             */
    } :segment_boot_core_stack

    /***********************************************************************************************
    * Code + RO Data + Global Offset Table
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
        *(.text._start_rust)      /* The Rust entry point */
        *(.text*)                 /* Everything else */
    } :segment_code

    .rodata : ALIGN(8) { *(.rodata*) } :segment_code

    /***********************************************************************************************
    * Data + BSS
    ***********************************************************************************************/
    .data : { *(.data*) } :segment_data

    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
    .bss (NOLOAD) : ALIGN(16)
    {
        __bss_start = .;
        *(.bss*);
        . = ALIGN(16);
        __bss_end_exclusive = .;
    } :segment_data

    /***********************************************************************************************
    * Misc
    ***********************************************************************************************/
    .got : { *(.got*) }
    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")

    /DISCARD/ : { *(.comment*) }
}


================================================
FILE: 02_runtime_init/src/bsp/raspberrypi.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Top-level BSP file for the Raspberry Pi 3 and 4.

pub mod cpu;


================================================
FILE: 02_runtime_init/src/bsp.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Conditional reexporting of Board Support Packages.

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
mod raspberrypi;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;


================================================
FILE: 02_runtime_init/src/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Boot code.

#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/cpu/boot.rs"]
mod arch_boot;


================================================
FILE: 02_runtime_init/src/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>

//! Processor code.

#[cfg(target_arch = "aarch64")]
#[path = "_arch/aarch64/cpu.rs"]
mod arch_cpu;

mod boot;

//--------------------------------------------------------------------------------------------------
// Architectural Public Reexports
//--------------------------------------------------------------------------------------------------
pub use arch_cpu::wait_forever;


================================================
FILE: 02_runtime_init/src/main.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

// Rust embedded logo for `make doc`.
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png"
)]

//! The `kernel` binary.
//!
//! # Code organization and architecture
//!
//! The code is divided into different *modules*, each representing a typical **subsystem** of the
//! `kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example,
//! `src/memory.rs` contains code that is concerned with all things memory management.
//!
//! ## Visibility of processor architecture code
//!
//! Some of the `kernel`'s subsystems depend on low-level code that is specific to the target
//! processor architecture. For each supported processor architecture, there exists a subfolder in
//! `src/_arch`, for example, `src/_arch/aarch64`.
//!
//! The architecture folders mirror the subsystem modules laid out in `src`. For example,
//! architectural code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go
//! into `src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in
//! `src/memory/mmu.rs` using the `path attribute`. Usually, the chosen module name is the generic
//! module's name prefixed with `arch_`.
//!
//! For example, this is the top of `src/memory/mmu.rs`:
//!
//! ```
//! #[cfg(target_arch = "aarch64")]
//! #[path = "../_arch/aarch64/memory/mmu.rs"]
//! mod arch_mmu;
//! ```
//!
//! Often times, items from the `arch_ module` will be publicly reexported by the parent module.
//! This way, each architecture specific module can provide its implementation of an item, while the
//! caller must not be concerned which architecture has been conditionally compiled.
//!
//! ## BSP code
//!
//! `BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains
//! target board specific definitions and functions. These are things such as the board's memory map
//! or instances of drivers for devices that are featured on the respective board.
//!
//! Just like processor architecture code, the `BSP` code's module structure tries to mirror the
//! `kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is
//! provided must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`.
//!
//! ## Kernel interfaces
//!
//! Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target
//! and board for which the kernel is compiled. For example, the `interrupt controller` hardware of
//! the `Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel`
//! code to play nicely with any of the two without much hassle.
//!
//! In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`,
//! `interface` traits are provided *whenever possible* and *where it makes sense*. They are defined
//! in the respective subsystem module and help to enforce the idiom of *program to an interface,
//! not an implementation*. For example, there will be a common IRQ handling interface which the two
//! different interrupt controller `drivers` of both Raspberrys will implement, and only export the
//! interface to the rest of the `kernel`.
//!
//! ```
//!         +-------------------+
//!         | Interface (Trait) |
//!         |                   |
//!         +--+-------------+--+
//!            ^             ^
//!            |             |
//!            |             |
//! +----------+--+       +--+----------+
//! | kernel code |       |  bsp code   |
//! |             |       |  arch code  |
//! +-------------+       +-------------+
//! ```
//!
//! # Summary
//!
//! For a logical `kernel` subsystem, corresponding code can be distributed over several physical
//! locations. Here is an example for the **memory** subsystem:
//!
//! - `src/memory.rs` and `src/memory/**/*`
//!   - Common code that is agnostic of target processor architecture and `BSP` characteristics.
//!     - Example: A function to zero a chunk of memory.
//!   - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code.
//!     - Example: An `MMU` interface that defines `MMU` function prototypes.
//! - `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*`
//!   - `BSP` specific code.
//!   - Example: The board's memory map (physical addresses of DRAM and MMIO devices).
//! - `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*`
//!   - Processor architecture specific code.
//!   - Example: Implementation of the `MMU` interface for the `__arch_name__` processor
//!     architecture.
//!
//! From a namespace perspective, **memory** subsystem code lives in:
//!
//! - `crate::memory::*`
//! - `crate::bsp::memory::*`
//!
//! # Boot flow
//!
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
//!     - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.
//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.

#![feature(asm_const)]
#![no_main]
#![no_std]

mod bsp;
mod cpu;
mod panic_wait;

/// Early init code.
///
/// # Safety
///
/// - Only a single core must be active and running this function.
unsafe fn kernel_init() -> ! {
    panic!()
}


================================================
FILE: 02_runtime_init/src/panic_wait.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! A panic handler that infinitely waits.

use crate::cpu;
use core::panic::PanicInfo;

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    cpu::wait_forever()
}


================================================
FILE: 03_hacky_hello_world/.vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 03_hacky_hello_world/Cargo.toml
================================================
[package]
name = "mingo"
version = "0.3.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2021"

[profile.release]
lto = true

[features]
default = []
bsp_rpi3 = []
bsp_rpi4 = []

[[bin]]
name = "kernel"
path = "src/main.rs"

##--------------------------------------------------------------------------------------------------
## Dependencies
##--------------------------------------------------------------------------------------------------

[dependencies]

# Platform specific dependencies
[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = { version = "9.x.x" }


================================================
FILE: 03_hacky_hello_world/Makefile
================================================
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

include ../common/docker.mk
include ../common/format.mk
include ../common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi3.
BSP ?= rpi3



##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi3)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE = raspi3
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a53
else ifeq ($(BSP),rpi4)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE =
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a72
endif

# Export for build.rs.
export LD_SCRIPT_PATH



##--------------------------------------------------------------------------------------------------
## Targets and Prerequisites
##--------------------------------------------------------------------------------------------------
KERNEL_MANIFEST      = Cargo.toml
KERNEL_LINKER_SCRIPT = kernel.ld
LAST_BUILD_CONFIG    = target/$(BSP).build_config

KERNEL_ELF      = target/$(TARGET)/release/kernel
# This parses cargo's dep-info file.
# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files
KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG)



##--------------------------------------------------------------------------------------------------
## Command building blocks
##--------------------------------------------------------------------------------------------------
RUSTFLAGS = $(RUSTC_MISC_ARGS)                   \
    -C link-arg=--library-path=$(LD_SCRIPT_PATH) \
    -C link-arg=--script=$(KERNEL_LINKER_SCRIPT)

RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \
    -D warnings                   \
    -D missing_docs

FEATURES      = --features bsp_$(BSP)
COMPILER_ARGS = --target=$(TARGET) \
    $(FEATURES)                    \
    --release

RUSTC_CMD   = cargo rustc $(COMPILER_ARGS)
DOC_CMD     = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD  = cargo clippy $(COMPILER_ARGS)
OBJCOPY_CMD = rust-objcopy \
    --strip-all            \
    -O binary

EXEC_QEMU          = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
EXEC_TEST_DISPATCH = ruby ../common/tests/dispatch.rb

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD            = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT   = $(DOCKER_CMD) -i
DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
DOCKER_TEST  = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)



##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all doc qemu clippy clean readelf objdump nm check

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Save the configuration as a file, so make understands if it changed.
##------------------------------------------------------------------------------
$(LAST_BUILD_CONFIG):
	@rm -f target/*.build_config
	@mkdir -p target
	@touch $(LAST_BUILD_CONFIG)

##------------------------------------------------------------------------------
## Compile the kernel ELF
##------------------------------------------------------------------------------
$(KERNEL_ELF): $(KERNEL_ELF_DEPS)
	$(call color_header, "Compiling kernel ELF - $(BSP)")
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
## Generate the stripped kernel binary
##------------------------------------------------------------------------------
$(KERNEL_BIN): $(KERNEL_ELF)
	$(call color_header, "Generating stripped binary")
	@$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN)
	$(call color_progress_prefix, "Name")
	@echo $(KERNEL_BIN)
	$(call color_progress_prefix, "Size")
	$(call disk_usage_KiB, $(KERNEL_BIN))

##------------------------------------------------------------------------------
## Generate the documentation
##------------------------------------------------------------------------------
doc:
	$(call color_header, "Generating docs")
	@$(DOC_CMD) --document-private-items --open

##------------------------------------------------------------------------------
## Run the kernel in QEMU
##------------------------------------------------------------------------------
ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

qemu:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

qemu: $(KERNEL_BIN)
	$(call color_header, "Launching QEMU")
	@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
endif

##------------------------------------------------------------------------------
## Run clippy
##------------------------------------------------------------------------------
clippy:
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)

##------------------------------------------------------------------------------
## Clean
##------------------------------------------------------------------------------
clean:
	rm -rf target $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Run readelf
##------------------------------------------------------------------------------
readelf: $(KERNEL_ELF)
	$(call color_header, "Launching readelf")
	@$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF)

##------------------------------------------------------------------------------
## Run objdump
##------------------------------------------------------------------------------
objdump: $(KERNEL_ELF)
	$(call color_header, "Launching objdump")
	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                --section .text   \
                --section .rodata \
                $(KERNEL_ELF) | rustfilt

##------------------------------------------------------------------------------
## Run nm
##------------------------------------------------------------------------------
nm: $(KERNEL_ELF)
	$(call color_header, "Launching nm")
	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt



##--------------------------------------------------------------------------------------------------
## Testing targets
##--------------------------------------------------------------------------------------------------
.PHONY: test test_boot

ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

test_boot test:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

##------------------------------------------------------------------------------
## Run boot test
##------------------------------------------------------------------------------
test_boot: $(KERNEL_BIN)
	$(call color_header, "Boot test - $(BSP)")
	@$(DOCKER_TEST) $(EXEC_TEST_DISPATCH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)

test: test_boot

endif


================================================
FILE: 03_hacky_hello_world/README.CN.md
================================================
# 教程 03 - Hacky Hello World

## tl;dr

- 介绍全局的`println!()`宏以便尽早启用"printf debugging"。
- 为了保持教程长度合理,打印函数目前 "滥用" 了 QEMU 属性,该属性允许我们在没有正确设置的情况下使用树莓派的`UART`。
- 在接下来的教程中将逐步使用真实硬件的`UART`。

## 值得注意的补充

- `src/console.rs`为控制台命令和通过`console::console()`对内核控制台的全局访问引入了接口`Traits`。
- `src/bsp/raspberrypi/console.rs` 实现QEMU仿真UART的接口。
- 紧急处理程序使用新的`println!()`以显示用户错误消息。
- 有一个新的Makefile目录`make test`,用于自动测试。它在`QEMU`中引导编译后的内核,并检查内核生成的预期输出字符串。
  - 在本教程中,它检查字符串`Stopping here`,该字符串由`panic!()`在`main.rs`的末尾。

## 测试一下

QEMU不再以汇编模式运行。从现在起,它将显示`console`的输出。

```console
$ make qemu
[...]

Hello from Rust!
Kernel panic!

Panic location:
      File 'src/main.rs', line 126, column 5

Stopping here.
```

## 相比之前的变化(diff)
请检查[英文版本](README.md#diff-to-previous),这是最新的。


================================================
FILE: 03_hacky_hello_world/README.ES.md
================================================
# Tutorial 03 - Hacky Hello World

## tl;dr

* Se añade la macro global `print!()` para habilitar la "depuración basada en printf" ("printf debugging") lo más pronto posible.
* Para mantener una duración razonable en este tutorial, las funciones de impresión por el momento "abusan" una propiedad de QEMU que nos permite hacer uso del `UART` de la Raspberry sin haberla configurado apropiadamente.
* El uso del hardware real de `UART` se habilitará paso por paso en los siguientes tutoriales.

## Adiciones notables

* `src/console.rs` introduce una interfaz con `Trait`s para comandos de consola.
* `src/bsp/raspberrypi/console.rs` implementa la interfaz para que QEMU pueda crear una emulación de UART.
* El *panic handler* (manejador de pánico) hace uso de la nueva macro `print!()` para mostrar mensajes de error del usuario.
* Hay un nuevo objetivo en el Makefile: `make test`, destinado a la automatización de pruebas. Este comando inicia el kernel (núcleo) compilado en `QEMU`, y busca una cadena de  texto específica en la salida que ha sido producida por el kernel (núcleo).
  * En este tutorial, se buscará la cadena `Stopping here`, que es creada por la macro `panic!()` al final del archivo `main.rs`.

## Pruébalo

QEMU ya no está siendo ejecutado en modo ensamblador. Desde ahora en adelante mostrará la salida de la `consola`.

```console
$ make qemu
[...]
Hello from Rust!

Kernel panic: Stopping here.
```

### Diccionario

* *Hacky:* Solución torpe o poco elegante para un problema.

* *Debugging:* Proceso para identificar y corregir errores de programación.

  * *printf debugging:* Usado para describir el trabajo de depuración (*debugging*) poniendo comandos que dan una salida en consola, como el de "printf", en diferentes lugares del programa; observando la información y tratando de deducir qué está mal en el programa basándose en la información que nos dan nuestros comandos.

* *Traits:* Un *trait* le hace saber al compilador de Rust acerca de una funcionalidad que tiene un tipo de dato particular y que puede compartir con otros tipos de datos.

  > NOTA: Los *traits* son similares a una característica que se le conoce comúnmente como *interfaces* en otros lenguajes, aunque con algunas diferencias.

  Si deseas aprender más acerca de esto, por favor lee este capítulo del libro de Rust: [Traits: Defining Shared Behavior - The Rust Programming Language](https://doc.rust-lang.org/book/ch10-02-traits.html)

## Diferencias con el archivo anterior

Please check [the english version](README.md#diff-to-previous), which is kept up-to-date.


================================================
FILE: 03_hacky_hello_world/README.md
================================================
# Tutorial 03 - Hacky Hello World

## tl;dr

- Introducing global `println!()` macros to enable "printf debugging" at the earliest.
- To keep tutorial length reasonable, printing functions for now "abuse" a QEMU property that lets
  us use the Raspberry's `UART` without setting it up properly.
- Using the real hardware `UART` is enabled step-by-step in following tutorials.

## Notable additions

- `src/console.rs` introduces interface `Traits` for console commands and global access to the
  kernel's console through `console::console()`.
- `src/bsp/raspberrypi/console.rs` implements the interface for QEMU's emulated UART.
- The panic handler makes use of the new `println!()` to display user error messages.
- There is a new Makefile target, `make test`, intended for automated testing. It boots the compiled
  kernel in `QEMU`, and checks for an expected output string produced by the kernel.
  - In this tutorial, it checks for the string `Stopping here`, which is emitted by the `panic!()`
    at the end of `main.rs`.

## Test it

QEMU is no longer running in assembly mode. It will from now on show the output of the `console`.

```console
$ make qemu
[...]

Hello from Rust!
Kernel panic!

Panic location:
      File 'src/main.rs', line 126, column 5

Stopping here.
```

## Diff to previous
```diff

diff -uNr 02_runtime_init/Cargo.toml 03_hacky_hello_world/Cargo.toml
--- 02_runtime_init/Cargo.toml
+++ 03_hacky_hello_world/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mingo"
-version = "0.2.0"
+version = "0.3.0"
 authors = ["Andre Richter <andre.o.richter@gmail.com>"]
 edition = "2021"


diff -uNr 02_runtime_init/Makefile 03_hacky_hello_world/Makefile
--- 02_runtime_init/Makefile
+++ 03_hacky_hello_world/Makefile
@@ -25,7 +25,7 @@
     KERNEL_BIN        = kernel8.img
     QEMU_BINARY       = qemu-system-aarch64
     QEMU_MACHINE_TYPE = raspi3
-    QEMU_RELEASE_ARGS = -d in_asm -display none
+    QEMU_RELEASE_ARGS = -serial stdio -display none
     OBJDUMP_BINARY    = aarch64-none-elf-objdump
     NM_BINARY         = aarch64-none-elf-nm
     READELF_BINARY    = aarch64-none-elf-readelf
@@ -36,7 +36,7 @@
     KERNEL_BIN        = kernel8.img
     QEMU_BINARY       = qemu-system-aarch64
     QEMU_MACHINE_TYPE =
-    QEMU_RELEASE_ARGS = -d in_asm -display none
+    QEMU_RELEASE_ARGS = -serial stdio -display none
     OBJDUMP_BINARY    = aarch64-none-elf-objdump
     NM_BINARY         = aarch64-none-elf-nm
     READELF_BINARY    = aarch64-none-elf-readelf
@@ -86,17 +86,20 @@
     --strip-all            \
     -O binary

-EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
+EXEC_QEMU          = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
+EXEC_TEST_DISPATCH = ruby ../common/tests/dispatch.rb

 ##------------------------------------------------------------------------------
 ## Dockerization
 ##------------------------------------------------------------------------------
-DOCKER_CMD          = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
-DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i
+DOCKER_CMD            = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
+DOCKER_CMD_INTERACT   = $(DOCKER_CMD) -i
+DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common

 # DOCKER_IMAGE defined in include file (see top of this file).
 DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
 DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
+DOCKER_TEST  = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)



@@ -191,3 +194,27 @@
 	$(call color_header, "Launching nm")
 	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt

+
+
+##--------------------------------------------------------------------------------------------------
+## Testing targets
+##--------------------------------------------------------------------------------------------------
+.PHONY: test test_boot
+
+ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.
+
+test_boot test:
+	$(call color_header, "$(QEMU_MISSING_STRING)")
+
+else # QEMU is supported.
+
+##------------------------------------------------------------------------------
+## Run boot test
+##------------------------------------------------------------------------------
+test_boot: $(KERNEL_BIN)
+	$(call color_header, "Boot test - $(BSP)")
+	@$(DOCKER_TEST) $(EXEC_TEST_DISPATCH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
+
+test: test_boot
+
+endif

diff -uNr 02_runtime_init/src/bsp/raspberrypi/console.rs 03_hacky_hello_world/src/bsp/raspberrypi/console.rs
--- 02_runtime_init/src/bsp/raspberrypi/console.rs
+++ 03_hacky_hello_world/src/bsp/raspberrypi/console.rs
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! BSP console facilities.
+
+use crate::console;
+use core::fmt;
+
+//--------------------------------------------------------------------------------------------------
+// Private Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// A mystical, magical device for generating QEMU output out of the void.
+struct QEMUOutput;
+
+//--------------------------------------------------------------------------------------------------
+// Private Code
+//--------------------------------------------------------------------------------------------------
+
+/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
+/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
+/// we get `write_fmt()` automatically.
+///
+/// See [`src/print.rs`].
+///
+/// [`src/print.rs`]: ../../print/index.html
+impl fmt::Write for QEMUOutput {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        for c in s.chars() {
+            unsafe {
+                core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8);
+            }
+        }
+
+        Ok(())
+    }
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return a reference to the console.
+pub fn console() -> impl console::interface::Write {
+    QEMUOutput {}
+}

diff -uNr 02_runtime_init/src/bsp/raspberrypi.rs 03_hacky_hello_world/src/bsp/raspberrypi.rs
--- 02_runtime_init/src/bsp/raspberrypi.rs
+++ 03_hacky_hello_world/src/bsp/raspberrypi.rs
@@ -4,4 +4,5 @@

 //! Top-level BSP file for the Raspberry Pi 3 and 4.

+pub mod console;
 pub mod cpu;

diff -uNr 02_runtime_init/src/console.rs 03_hacky_hello_world/src/console.rs
--- 02_runtime_init/src/console.rs
+++ 03_hacky_hello_world/src/console.rs
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! System console.
+
+use crate::bsp;
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// Console interfaces.
+pub mod interface {
+    /// Console write functions.
+    ///
+    /// `core::fmt::Write` is exactly what we need for now. Re-export it here because
+    /// implementing `console::Write` gives a better hint to the reader about the
+    /// intention.
+    pub use core::fmt::Write;
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return a reference to the console.
+///
+/// This is the global console used by all printing macros.
+pub fn console() -> impl interface::Write {
+    bsp::console::console()
+}

diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs
--- 02_runtime_init/src/main.rs
+++ 03_hacky_hello_world/src/main.rs
@@ -107,12 +107,16 @@
 //! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.

 #![feature(asm_const)]
+#![feature(format_args_nl)]
+#![feature(panic_info_message)]
 #![no_main]
 #![no_std]

 mod bsp;
+mod console;
 mod cpu;
 mod panic_wait;
+mod print;

 /// Early init code.
 ///
@@ -120,5 +124,7 @@
 ///
 /// - Only a single core must be active and running this function.
 unsafe fn kernel_init() -> ! {
-    panic!()
+    println!("Hello from Rust!");
+
+    panic!("Stopping here.")
 }

diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait.rs
--- 02_runtime_init/src/panic_wait.rs
+++ 03_hacky_hello_world/src/panic_wait.rs
@@ -4,14 +4,61 @@

 //! A panic handler that infinitely waits.

-use crate::cpu;
+use crate::{cpu, println};
 use core::panic::PanicInfo;

 //--------------------------------------------------------------------------------------------------
 // Private Code
 //--------------------------------------------------------------------------------------------------

+/// Stop immediately if called a second time.
+///
+/// # Note
+///
+/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
+///
+/// On `AArch64`, which is the only implemented architecture at the time of writing this,
+/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
+/// instructions. They are therefore safe to use even with MMU + caching deactivated.
+///
+/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
+/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
+fn panic_prevent_reenter() {
+    use core::sync::atomic::{AtomicBool, Ordering};
+
+    #[cfg(not(target_arch = "aarch64"))]
+    compile_error!("Add the target_arch to above's check if the following code is safe to use");
+
+    static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
+
+    if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
+        PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);
+
+        return;
+    }
+
+    cpu::wait_forever()
+}
+
 #[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
+fn panic(info: &PanicInfo) -> ! {
+    // Protect against panic infinite loops if any of the following code panics itself.
+    panic_prevent_reenter();
+
+    let (location, line, column) = match info.location() {
+        Some(loc) => (loc.file(), loc.line(), loc.column()),
+        _ => ("???", 0, 0),
+    };
+
+    println!(
+        "Kernel panic!\n\n\
+        Panic location:\n      File '{}', line {}, column {}\n\n\
+        {}",
+        location,
+        line,
+        column,
+        info.message().unwrap_or(&format_args!("")),
+    );
+
     cpu::wait_forever()
 }

diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
--- 02_runtime_init/src/print.rs
+++ 03_hacky_hello_world/src/print.rs
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! Printing.
+
+use crate::console;
+use core::fmt;
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+    use console::interface::Write;
+
+    console::console().write_fmt(args).unwrap();
+}
+
+/// Prints without a newline.
+///
+/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
+#[macro_export]
+macro_rules! print {
+    ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*)));
+}
+
+/// Prints with a newline.
+///
+/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
+#[macro_export]
+macro_rules! println {
+    () => ($crate::print!("\n"));
+    ($($arg:tt)*) => ({
+        $crate::print::_print(format_args_nl!($($arg)*));
+    })
+}

diff -uNr 02_runtime_init/tests/boot_test_string.rb 03_hacky_hello_world/tests/boot_test_string.rb
--- 02_runtime_init/tests/boot_test_string.rb
+++ 03_hacky_hello_world/tests/boot_test_string.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+EXPECTED_PRINT = 'Stopping here'

```


================================================
FILE: 03_hacky_hello_world/build.rs
================================================
use std::{env, fs, process};

fn main() {
    let ld_script_path = match env::var("LD_SCRIPT_PATH") {
        Ok(var) => var,
        _ => process::exit(0),
    };

    let files = fs::read_dir(ld_script_path).unwrap();
    files
        .filter_map(Result::ok)
        .filter(|d| {
            if let Some(e) = d.path().extension() {
                e == "ld"
            } else {
                false
            }
        })
        .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display()));
}


================================================
FILE: 03_hacky_hello_world/src/_arch/aarch64/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural boot code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::boot::arch_boot

use core::arch::global_asm;

// Assembly counterpart to this file.
global_asm!(
    include_str!("boot.s"),
    CONST_CORE_ID_MASK = const 0b11
);

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// The Rust entry of the `kernel` binary.
///
/// The function is called from the assembly `_start` function.
#[no_mangle]
pub unsafe fn _start_rust() -> ! {
    crate::kernel_init()
}


================================================
FILE: 03_hacky_hello_world/src/_arch/aarch64/cpu/boot.s
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>

//--------------------------------------------------------------------------------------------------
// Definitions
//--------------------------------------------------------------------------------------------------

// Load the address of a symbol into a register, PC-relative.
//
// The symbol must lie within +/- 4 GiB of the Program Counter.
//
// # Resources
//
// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
.macro ADR_REL register, symbol
	adrp	\register, \symbol
	add	\register, \register, #:lo12:\symbol
.endm

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
.section .text._start

//------------------------------------------------------------------------------
// fn _start()
//------------------------------------------------------------------------------
_start:
	// Only proceed on the boot core. Park it otherwise.
	mrs	x0, MPIDR_EL1
	and	x0, x0, {CONST_CORE_ID_MASK}
	ldr	x1, BOOT_CORE_ID      // provided by bsp/__board_name__/cpu.rs
	cmp	x0, x1
	b.ne	.L_parking_loop

	// If execution reaches here, it is the boot core.

	// Initialize DRAM.
	ADR_REL	x0, __bss_start
	ADR_REL x1, __bss_end_exclusive

.L_bss_init_loop:
	cmp	x0, x1
	b.eq	.L_prepare_rust
	stp	xzr, xzr, [x0], #16
	b	.L_bss_init_loop

	// Prepare the jump to Rust code.
.L_prepare_rust:
	// Set the stack pointer.
	ADR_REL	x0, __boot_core_stack_end_exclusive
	mov	sp, x0

	// Jump to Rust code.
	b	_start_rust

	// Infinitely wait for events (aka "park the core").
.L_parking_loop:
	wfe
	b	.L_parking_loop

.size	_start, . - _start
.type	_start, function
.global	_start


================================================
FILE: 03_hacky_hello_world/src/_arch/aarch64/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural processor code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::arch_cpu

use aarch64_cpu::asm;

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Pause execution on the core.
#[inline(always)]
pub fn wait_forever() -> ! {
    loop {
        asm::wfe()
    }
}


================================================
FILE: 03_hacky_hello_world/src/bsp/raspberrypi/console.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! BSP console facilities.

use crate::console;
use core::fmt;

//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------

/// A mystical, magical device for generating QEMU output out of the void.
struct QEMUOutput;

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
/// we get `write_fmt()` automatically.
///
/// See [`src/print.rs`].
///
/// [`src/print.rs`]: ../../print/index.html
impl fmt::Write for QEMUOutput {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            unsafe {
                core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8);
            }
        }

        Ok(())
    }
}

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Return a reference to the console.
pub fn console() -> impl console::interface::Write {
    QEMUOutput {}
}


================================================
FILE: 03_hacky_hello_world/src/bsp/raspberrypi/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! BSP Processor code.

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Used by `arch` code to find the early boot core.
#[no_mangle]
#[link_section = ".text._start_arguments"]
pub static BOOT_CORE_ID: u64 = 0;


================================================
FILE: 03_hacky_hello_world/src/bsp/raspberrypi/kernel.ld
================================================
/* SPDX-License-Identifier: MIT OR Apache-2.0
 *
 * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
 */

__rpi_phys_dram_start_addr = 0;

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;


ENTRY(__rpi_phys_binary_load_addr)

/* Flags:
 *     4 == R
 *     5 == RX
 *     6 == RW
 *
 * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
 * It doesn't mean all of them need actually be loaded.
 */
PHDRS
{
    segment_boot_core_stack PT_LOAD FLAGS(6);
    segment_code            PT_LOAD FLAGS(5);
    segment_data            PT_LOAD FLAGS(6);
}

SECTIONS
{
    . =  __rpi_phys_dram_start_addr;

    /***********************************************************************************************
    * Boot Core Stack
    ***********************************************************************************************/
    .boot_core_stack (NOLOAD) :
    {
                                             /*   ^             */
                                             /*   | stack       */
        . += __rpi_phys_binary_load_addr;    /*   | growth      */
                                             /*   | direction   */
        __boot_core_stack_end_exclusive = .; /*   |             */
    } :segment_boot_core_stack

    /***********************************************************************************************
    * Code + RO Data + Global Offset Table
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
        *(.text._start_rust)      /* The Rust entry point */
        *(.text*)                 /* Everything else */
    } :segment_code

    .rodata : ALIGN(8) { *(.rodata*) } :segment_code

    /***********************************************************************************************
    * Data + BSS
    ***********************************************************************************************/
    .data : { *(.data*) } :segment_data

    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
    .bss (NOLOAD) : ALIGN(16)
    {
        __bss_start = .;
        *(.bss*);
        . = ALIGN(16);
        __bss_end_exclusive = .;
    } :segment_data

    /***********************************************************************************************
    * Misc
    ***********************************************************************************************/
    .got : { *(.got*) }
    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")

    /DISCARD/ : { *(.comment*) }
}


================================================
FILE: 03_hacky_hello_world/src/bsp/raspberrypi.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Top-level BSP file for the Raspberry Pi 3 and 4.

pub mod console;
pub mod cpu;


================================================
FILE: 03_hacky_hello_world/src/bsp.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Conditional reexporting of Board Support Packages.

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
mod raspberrypi;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;


================================================
FILE: 03_hacky_hello_world/src/console.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! System console.

use crate::bsp;

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Console interfaces.
pub mod interface {
    /// Console write functions.
    ///
    /// `core::fmt::Write` is exactly what we need for now. Re-export it here because
    /// implementing `console::Write` gives a better hint to the reader about the
    /// intention.
    pub use core::fmt::Write;
}

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> impl interface::Write {
    bsp::console::console()
}


================================================
FILE: 03_hacky_hello_world/src/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Boot code.

#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/cpu/boot.rs"]
mod arch_boot;


================================================
FILE: 03_hacky_hello_world/src/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>

//! Processor code.

#[cfg(target_arch = "aarch64")]
#[path = "_arch/aarch64/cpu.rs"]
mod arch_cpu;

mod boot;

//--------------------------------------------------------------------------------------------------
// Architectural Public Reexports
//--------------------------------------------------------------------------------------------------
pub use arch_cpu::wait_forever;


================================================
FILE: 03_hacky_hello_world/src/main.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

// Rust embedded logo for `make doc`.
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png"
)]

//! The `kernel` binary.
//!
//! # Code organization and architecture
//!
//! The code is divided into different *modules*, each representing a typical **subsystem** of the
//! `kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example,
//! `src/memory.rs` contains code that is concerned with all things memory management.
//!
//! ## Visibility of processor architecture code
//!
//! Some of the `kernel`'s subsystems depend on low-level code that is specific to the target
//! processor architecture. For each supported processor architecture, there exists a subfolder in
//! `src/_arch`, for example, `src/_arch/aarch64`.
//!
//! The architecture folders mirror the subsystem modules laid out in `src`. For example,
//! architectural code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go
//! into `src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in
//! `src/memory/mmu.rs` using the `path attribute`. Usually, the chosen module name is the generic
//! module's name prefixed with `arch_`.
//!
//! For example, this is the top of `src/memory/mmu.rs`:
//!
//! ```
//! #[cfg(target_arch = "aarch64")]
//! #[path = "../_arch/aarch64/memory/mmu.rs"]
//! mod arch_mmu;
//! ```
//!
//! Often times, items from the `arch_ module` will be publicly reexported by the parent module.
//! This way, each architecture specific module can provide its implementation of an item, while the
//! caller must not be concerned which architecture has been conditionally compiled.
//!
//! ## BSP code
//!
//! `BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains
//! target board specific definitions and functions. These are things such as the board's memory map
//! or instances of drivers for devices that are featured on the respective board.
//!
//! Just like processor architecture code, the `BSP` code's module structure tries to mirror the
//! `kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is
//! provided must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`.
//!
//! ## Kernel interfaces
//!
//! Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target
//! and board for which the kernel is compiled. For example, the `interrupt controller` hardware of
//! the `Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel`
//! code to play nicely with any of the two without much hassle.
//!
//! In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`,
//! `interface` traits are provided *whenever possible* and *where it makes sense*. They are defined
//! in the respective subsystem module and help to enforce the idiom of *program to an interface,
//! not an implementation*. For example, there will be a common IRQ handling interface which the two
//! different interrupt controller `drivers` of both Raspberrys will implement, and only export the
//! interface to the rest of the `kernel`.
//!
//! ```
//!         +-------------------+
//!         | Interface (Trait) |
//!         |                   |
//!         +--+-------------+--+
//!            ^             ^
//!            |             |
//!            |             |
//! +----------+--+       +--+----------+
//! | kernel code |       |  bsp code   |
//! |             |       |  arch code  |
//! +-------------+       +-------------+
//! ```
//!
//! # Summary
//!
//! For a logical `kernel` subsystem, corresponding code can be distributed over several physical
//! locations. Here is an example for the **memory** subsystem:
//!
//! - `src/memory.rs` and `src/memory/**/*`
//!   - Common code that is agnostic of target processor architecture and `BSP` characteristics.
//!     - Example: A function to zero a chunk of memory.
//!   - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code.
//!     - Example: An `MMU` interface that defines `MMU` function prototypes.
//! - `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*`
//!   - `BSP` specific code.
//!   - Example: The board's memory map (physical addresses of DRAM and MMIO devices).
//! - `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*`
//!   - Processor architecture specific code.
//!   - Example: Implementation of the `MMU` interface for the `__arch_name__` processor
//!     architecture.
//!
//! From a namespace perspective, **memory** subsystem code lives in:
//!
//! - `crate::memory::*`
//! - `crate::bsp::memory::*`
//!
//! # Boot flow
//!
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
//!     - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.
//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.

#![feature(asm_const)]
#![feature(format_args_nl)]
#![feature(panic_info_message)]
#![no_main]
#![no_std]

mod bsp;
mod console;
mod cpu;
mod panic_wait;
mod print;

/// Early init code.
///
/// # Safety
///
/// - Only a single core must be active and running this function.
unsafe fn kernel_init() -> ! {
    println!("Hello from Rust!");

    panic!("Stopping here.")
}


================================================
FILE: 03_hacky_hello_world/src/panic_wait.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! A panic handler that infinitely waits.

use crate::{cpu, println};
use core::panic::PanicInfo;

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

/// Stop immediately if called a second time.
///
/// # Note
///
/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
///
/// On `AArch64`, which is the only implemented architecture at the time of writing this,
/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
/// instructions. They are therefore safe to use even with MMU + caching deactivated.
///
/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
fn panic_prevent_reenter() {
    use core::sync::atomic::{AtomicBool, Ordering};

    #[cfg(not(target_arch = "aarch64"))]
    compile_error!("Add the target_arch to above's check if the following code is safe to use");

    static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);

    if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
        PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);

        return;
    }

    cpu::wait_forever()
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    // Protect against panic infinite loops if any of the following code panics itself.
    panic_prevent_reenter();

    let (location, line, column) = match info.location() {
        Some(loc) => (loc.file(), loc.line(), loc.column()),
        _ => ("???", 0, 0),
    };

    println!(
        "Kernel panic!\n\n\
        Panic location:\n      File '{}', line {}, column {}\n\n\
        {}",
        location,
        line,
        column,
        info.message().unwrap_or(&format_args!("")),
    );

    cpu::wait_forever()
}


================================================
FILE: 03_hacky_hello_world/src/print.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Printing.

use crate::console;
use core::fmt;

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
    use console::interface::Write;

    console::console().write_fmt(args).unwrap();
}

/// Prints without a newline.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*)));
}

/// Prints with a newline.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::print::_print(format_args_nl!($($arg)*));
    })
}


================================================
FILE: 03_hacky_hello_world/tests/boot_test_string.rb
================================================
# frozen_string_literal: true

EXPECTED_PRINT = 'Stopping here'


================================================
FILE: 04_safe_globals/.vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 04_safe_globals/Cargo.toml
================================================
[package]
name = "mingo"
version = "0.4.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2021"

[profile.release]
lto = true

[features]
default = []
bsp_rpi3 = []
bsp_rpi4 = []

[[bin]]
name = "kernel"
path = "src/main.rs"

##--------------------------------------------------------------------------------------------------
## Dependencies
##--------------------------------------------------------------------------------------------------

[dependencies]

# Platform specific dependencies
[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = { version = "9.x.x" }


================================================
FILE: 04_safe_globals/Makefile
================================================
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

include ../common/docker.mk
include ../common/format.mk
include ../common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi3.
BSP ?= rpi3



##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi3)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE = raspi3
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a53
else ifeq ($(BSP),rpi4)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE =
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a72
endif

# Export for build.rs.
export LD_SCRIPT_PATH



##--------------------------------------------------------------------------------------------------
## Targets and Prerequisites
##--------------------------------------------------------------------------------------------------
KERNEL_MANIFEST      = Cargo.toml
KERNEL_LINKER_SCRIPT = kernel.ld
LAST_BUILD_CONFIG    = target/$(BSP).build_config

KERNEL_ELF      = target/$(TARGET)/release/kernel
# This parses cargo's dep-info file.
# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files
KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG)



##--------------------------------------------------------------------------------------------------
## Command building blocks
##--------------------------------------------------------------------------------------------------
RUSTFLAGS = $(RUSTC_MISC_ARGS)                   \
    -C link-arg=--library-path=$(LD_SCRIPT_PATH) \
    -C link-arg=--script=$(KERNEL_LINKER_SCRIPT)

RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \
    -D warnings                   \
    -D missing_docs

FEATURES      = --features bsp_$(BSP)
COMPILER_ARGS = --target=$(TARGET) \
    $(FEATURES)                    \
    --release

RUSTC_CMD   = cargo rustc $(COMPILER_ARGS)
DOC_CMD     = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD  = cargo clippy $(COMPILER_ARGS)
OBJCOPY_CMD = rust-objcopy \
    --strip-all            \
    -O binary

EXEC_QEMU          = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
EXEC_TEST_DISPATCH = ruby ../common/tests/dispatch.rb

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD            = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT   = $(DOCKER_CMD) -i
DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
DOCKER_TEST  = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)



##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all doc qemu clippy clean readelf objdump nm check

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Save the configuration as a file, so make understands if it changed.
##------------------------------------------------------------------------------
$(LAST_BUILD_CONFIG):
	@rm -f target/*.build_config
	@mkdir -p target
	@touch $(LAST_BUILD_CONFIG)

##------------------------------------------------------------------------------
## Compile the kernel ELF
##------------------------------------------------------------------------------
$(KERNEL_ELF): $(KERNEL_ELF_DEPS)
	$(call color_header, "Compiling kernel ELF - $(BSP)")
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
## Generate the stripped kernel binary
##------------------------------------------------------------------------------
$(KERNEL_BIN): $(KERNEL_ELF)
	$(call color_header, "Generating stripped binary")
	@$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN)
	$(call color_progress_prefix, "Name")
	@echo $(KERNEL_BIN)
	$(call color_progress_prefix, "Size")
	$(call disk_usage_KiB, $(KERNEL_BIN))

##------------------------------------------------------------------------------
## Generate the documentation
##------------------------------------------------------------------------------
doc:
	$(call color_header, "Generating docs")
	@$(DOC_CMD) --document-private-items --open

##------------------------------------------------------------------------------
## Run the kernel in QEMU
##------------------------------------------------------------------------------
ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

qemu:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

qemu: $(KERNEL_BIN)
	$(call color_header, "Launching QEMU")
	@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
endif

##------------------------------------------------------------------------------
## Run clippy
##------------------------------------------------------------------------------
clippy:
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)

##------------------------------------------------------------------------------
## Clean
##------------------------------------------------------------------------------
clean:
	rm -rf target $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Run readelf
##------------------------------------------------------------------------------
readelf: $(KERNEL_ELF)
	$(call color_header, "Launching readelf")
	@$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF)

##------------------------------------------------------------------------------
## Run objdump
##------------------------------------------------------------------------------
objdump: $(KERNEL_ELF)
	$(call color_header, "Launching objdump")
	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                --section .text   \
                --section .rodata \
                $(KERNEL_ELF) | rustfilt

##------------------------------------------------------------------------------
## Run nm
##------------------------------------------------------------------------------
nm: $(KERNEL_ELF)
	$(call color_header, "Launching nm")
	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt



##--------------------------------------------------------------------------------------------------
## Testing targets
##--------------------------------------------------------------------------------------------------
.PHONY: test test_boot

ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

test_boot test:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

##------------------------------------------------------------------------------
## Run boot test
##------------------------------------------------------------------------------
test_boot: $(KERNEL_BIN)
	$(call color_header, "Boot test - $(BSP)")
	@$(DOCKER_TEST) $(EXEC_TEST_DISPATCH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)

test: test_boot

endif


================================================
FILE: 04_safe_globals/README.CN.md
================================================
# 教程 04 - 全局安全

## tl;dr

- 引入了假的锁。
- 这是第一次展示原始操作系统同步,并支持安全访问全局数据结构。

## Rust中的全局可变

当我们引入全局可用的`print!`宏在 [教程03],我门有一点作弊。 调用
`core::fmt`的`write_fmt()`函数,接受`&mut self`的方法之所以有效,
是因为在每次调用时都会创建一个新的`QEMUOutput`实例。

如果我们想保留一些状态,例如关于写入字符数的统计数据,
我们需要创建`QEMUOutput`的一个全局实例 (在Rust中,使用`static`关键字).

然而`static QEMU_OUTPUT`不允许调用具有`&mut self`的函数。
为此,我们需要`static mut`,但是调用改变`static mut`状态的函数是不安全的。
这个是Rust编译器对此的推理,它无法再阻止核心/线程同时改变数据(它是全局的,所以每个人都可以从任何地方引用它,检查程序借用在这里帮不上忙)。


这个问题的解决方案是将全局封装到原始同步中。在我们的例子中,是一个*MUTual EXclusion*原语的变体。
`Mutex`是`synchronization.rs`中引入的一个特性,并由同一文件中的`NullLock`实现。
为了使代码更易于教学,它省略了用于防止并发访问的实际体系结构特定逻辑,因为只要内核仅在单个内核上执行并禁用中断,我们就不需要它。

`NullLock`侧重于展示Rust内部可变性的核心概念。请务必阅读它。
我们还建议您阅读这篇关于[Rust的引用类型的精确心智模型]文章

如果要将`NullLock`与一些真实的互斥实现进行比较,可以查看
[spin crate]或者[parking lot crate]。

[教程03]: ../03_hacky_hello_world
[内部可变性]: https://doc.rust-lang.org/std/cell/index.html
[Rust的引用类型的精确心智模型]: https://docs.rs/dtolnay/0.0.6/dtolnay/macro._02__reference_types.html
[spin crate]: https://github.com/mvdnes/spin-rs
[parking lot crate]: https://github.com/Amanieu/parking_lot

## 测试

```console
$ make qemu
[...]

[0] Hello from Rust!
[1] Chars written: 22
[2] Stopping here.
```

## 相比之前的变化(diff)
请检查[英文版本](README.md#diff-to-previous),这是最新的。


================================================
FILE: 04_safe_globals/README.md
================================================
# Tutorial 04 - Safe Globals

## tl;dr

- A pseudo-lock is introduced.
- It is a first showcase of OS synchronization primitives and enables safe access to a global data
  structure.

## Mutable globals in Rust

When we introduced the globally usable `print!` macros in [tutorial 03], we cheated a bit. Calling
`core::fmt`'s `write_fmt()` function, which takes an `&mut self`, was only working because on each
call, a new instance of `QEMUOutput` was created.

If we would want to preserve some state, e.g. statistics about the number of characters written, we
need to make a single global instance of `QEMUOutput` (in Rust, using the `static` keyword).

A `static QEMU_OUTPUT`, however, would not allow to call functions taking `&mut self`. For that, we
would need a `static mut`, but calling functions that mutate state on `static mut`s is unsafe. The
Rust compiler's reasoning for this is that it can then not prevent anymore that multiple
cores/threads are mutating the data concurrently (it is a global, so everyone can reference it from
anywhere. The borrow checker can't help here).

The solution to this problem is to wrap the global into a synchronization primitive. In our case, a
variant of a *MUTual EXclusion* primitive. `Mutex` is introduced as a trait in `synchronization.rs`,
and implemented by the `NullLock` in the same file. In order to make the code lean for teaching
purposes, it leaves out the actual architecture-specific logic for protection against concurrent
access, since we don't need it as long as the kernel only executes on a single core with interrupts
disabled.

The `NullLock` focuses on showcasing the Rust core concept of [interior mutability]. Make sure to
read up on it. I also recommend to read this article about an [accurate mental model for Rust's
reference types].

If you want to compare the `NullLock` to some real-world mutex implementations, you can check out
implemntations in the [spin crate] or the [parking lot crate].

[tutorial 03]: ../03_hacky_hello_world
[interior mutability]: https://doc.rust-lang.org/std/cell/index.html
[accurate mental model for Rust's reference types]: https://docs.rs/dtolnay/0.0.6/dtolnay/macro._02__reference_types.html
[spin crate]: https://github.com/mvdnes/spin-rs
[parking lot crate]: https://github.com/Amanieu/parking_lot

## Test it

```console
$ make qemu
[...]

[0] Hello from Rust!
[1] Chars written: 22
[2] Stopping here.
```

## Diff to previous
```diff

diff -uNr 03_hacky_hello_world/Cargo.toml 04_safe_globals/Cargo.toml
--- 03_hacky_hello_world/Cargo.toml
+++ 04_safe_globals/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mingo"
-version = "0.3.0"
+version = "0.4.0"
 authors = ["Andre Richter <andre.o.richter@gmail.com>"]
 edition = "2021"


diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/console.rs 04_safe_globals/src/bsp/raspberrypi/console.rs
--- 03_hacky_hello_world/src/bsp/raspberrypi/console.rs
+++ 04_safe_globals/src/bsp/raspberrypi/console.rs
@@ -4,7 +4,7 @@

 //! BSP console facilities.

-use crate::console;
+use crate::{console, synchronization, synchronization::NullLock};
 use core::fmt;

 //--------------------------------------------------------------------------------------------------
@@ -12,25 +12,64 @@
 //--------------------------------------------------------------------------------------------------

 /// A mystical, magical device for generating QEMU output out of the void.
-struct QEMUOutput;
+///
+/// The mutex protected part.
+struct QEMUOutputInner {
+    chars_written: usize,
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// The main struct.
+pub struct QEMUOutput {
+    inner: NullLock<QEMUOutputInner>,
+}
+
+//--------------------------------------------------------------------------------------------------
+// Global instances
+//--------------------------------------------------------------------------------------------------
+
+static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new();

 //--------------------------------------------------------------------------------------------------
 // Private Code
 //--------------------------------------------------------------------------------------------------

+impl QEMUOutputInner {
+    const fn new() -> QEMUOutputInner {
+        QEMUOutputInner { chars_written: 0 }
+    }
+
+    /// Send a character.
+    fn write_char(&mut self, c: char) {
+        unsafe {
+            core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8);
+        }
+
+        self.chars_written += 1;
+    }
+}
+
 /// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
 /// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
 /// we get `write_fmt()` automatically.
 ///
+/// The function takes an `&mut self`, so it must be implemented for the inner struct.
+///
 /// See [`src/print.rs`].
 ///
 /// [`src/print.rs`]: ../../print/index.html
-impl fmt::Write for QEMUOutput {
+impl fmt::Write for QEMUOutputInner {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         for c in s.chars() {
-            unsafe {
-                core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8);
+            // Convert newline to carrige return + newline.
+            if c == '\n' {
+                self.write_char('\r')
             }
+
+            self.write_char(c);
         }

         Ok(())
@@ -41,7 +80,39 @@
 // Public Code
 //--------------------------------------------------------------------------------------------------

+impl QEMUOutput {
+    /// Create a new instance.
+    pub const fn new() -> QEMUOutput {
+        QEMUOutput {
+            inner: NullLock::new(QEMUOutputInner::new()),
+        }
+    }
+}
+
 /// Return a reference to the console.
-pub fn console() -> impl console::interface::Write {
-    QEMUOutput {}
+pub fn console() -> &'static dyn console::interface::All {
+    &QEMU_OUTPUT
 }
+
+//------------------------------------------------------------------------------
+// OS Interface Code
+//------------------------------------------------------------------------------
+use synchronization::interface::Mutex;
+
+/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to
+/// serialize access.
+impl console::interface::Write for QEMUOutput {
+    fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
+        // Fully qualified syntax for the call to `core::fmt::Write::write_fmt()` to increase
+        // readability.
+        self.inner.lock(|inner| fmt::Write::write_fmt(inner, args))
+    }
+}
+
+impl console::interface::Statistics for QEMUOutput {
+    fn chars_written(&self) -> usize {
+        self.inner.lock(|inner| inner.chars_written)
+    }
+}
+
+impl console::interface::All for QEMUOutput {}

diff -uNr 03_hacky_hello_world/src/console.rs 04_safe_globals/src/console.rs
--- 03_hacky_hello_world/src/console.rs
+++ 04_safe_globals/src/console.rs
@@ -12,12 +12,24 @@

 /// Console interfaces.
 pub mod interface {
+    use core::fmt;
+
     /// Console write functions.
-    ///
-    /// `core::fmt::Write` is exactly what we need for now. Re-export it here because
-    /// implementing `console::Write` gives a better hint to the reader about the
-    /// intention.
-    pub use core::fmt::Write;
+    pub trait Write {
+        /// Write a Rust format string.
+        fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
+    }
+
+    /// Console statistics.
+    pub trait Statistics {
+        /// Return the number of characters written.
+        fn chars_written(&self) -> usize {
+            0
+        }
+    }
+
+    /// Trait alias for a full-fledged console.
+    pub trait All: Write + Statistics {}
 }

 //--------------------------------------------------------------------------------------------------
@@ -27,6 +39,6 @@
 /// Return a reference to the console.
 ///
 /// This is the global console used by all printing macros.
-pub fn console() -> impl interface::Write {
+pub fn console() -> &'static dyn interface::All {
     bsp::console::console()
 }

diff -uNr 03_hacky_hello_world/src/main.rs 04_safe_globals/src/main.rs
--- 03_hacky_hello_world/src/main.rs
+++ 04_safe_globals/src/main.rs
@@ -109,6 +109,7 @@
 #![feature(asm_const)]
 #![feature(format_args_nl)]
 #![feature(panic_info_message)]
+#![feature(trait_alias)]
 #![no_main]
 #![no_std]

@@ -117,6 +118,7 @@
 mod cpu;
 mod panic_wait;
 mod print;
+mod synchronization;

 /// Early init code.
 ///
@@ -124,7 +126,12 @@
 ///
 /// - Only a single core must be active and running this function.
 unsafe fn kernel_init() -> ! {
-    println!("Hello from Rust!");
+    use console::console;

-    panic!("Stopping here.")
+    println!("[0] Hello from Rust!");
+
+    println!("[1] Chars written: {}", console().chars_written());
+
+    println!("[2] Stopping here.");
+    cpu::wait_forever()
 }

diff -uNr 03_hacky_hello_world/src/print.rs 04_safe_globals/src/print.rs
--- 03_hacky_hello_world/src/print.rs
+++ 04_safe_globals/src/print.rs
@@ -13,8 +13,6 @@

 #[doc(hidden)]
 pub fn _print(args: fmt::Arguments) {
-    use console::interface::Write;
-
     console::console().write_fmt(args).unwrap();
 }


diff -uNr 03_hacky_hello_world/src/synchronization.rs 04_safe_globals/src/synchronization.rs
--- 03_hacky_hello_world/src/synchronization.rs
+++ 04_safe_globals/src/synchronization.rs
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0
+//
+// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>
+
+//! Synchronization primitives.
+//!
+//! # Resources
+//!
+//!   - <https://doc.rust-lang.org/book/ch16-04-extensible-concurrency-sync-and-send.html>
+//!   - <https://stackoverflow.com/questions/59428096/understanding-the-send-trait>
+//!   - <https://doc.rust-lang.org/std/cell/index.html>
+
+use core::cell::UnsafeCell;
+
+//--------------------------------------------------------------------------------------------------
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+/// Synchronization interfaces.
+pub mod interface {
+
+    /// Any object implementing this trait guarantees exclusive access to the data wrapped within
+    /// the Mutex for the duration of the provided closure.
+    pub trait Mutex {
+        /// The type of the data that is wrapped by this mutex.
+        type Data;
+
+        /// Locks the mutex and grants the closure temporary mutable access to the wrapped data.
+        fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
+    }
+}
+
+/// A pseudo-lock for teaching purposes.
+///
+/// In contrast to a real Mutex implementation, does not protect against concurrent access from
+/// other cores to the contained data. This part is preserved for later lessons.
+///
+/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is
+/// executing single-threaded, aka only running on a single core with interrupts disabled.
+pub struct NullLock<T>
+where
+    T: ?Sized,
+{
+    data: UnsafeCell<T>,
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {}
+unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}
+
+impl<T> NullLock<T> {
+    /// Create an instance.
+    pub const fn new(data: T) -> Self {
+        Self {
+            data: UnsafeCell::new(data),
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+// OS Interface Code
+//------------------------------------------------------------------------------
+
+impl<T> interface::Mutex for NullLock<T> {
+    type Data = T;
+
+    fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
+        // In a real lock, there would be code encapsulating this line that ensures that this
+        // mutable reference will ever only be given out once at a time.
+        let data = unsafe { &mut *self.data.get() };
+
+        f(data)
+    }
+}

```


================================================
FILE: 04_safe_globals/build.rs
================================================
use std::{env, fs, process};

fn main() {
    let ld_script_path = match env::var("LD_SCRIPT_PATH") {
        Ok(var) => var,
        _ => process::exit(0),
    };

    let files = fs::read_dir(ld_script_path).unwrap();
    files
        .filter_map(Result::ok)
        .filter(|d| {
            if let Some(e) = d.path().extension() {
                e == "ld"
            } else {
                false
            }
        })
        .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display()));
}


================================================
FILE: 04_safe_globals/src/_arch/aarch64/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural boot code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::boot::arch_boot

use core::arch::global_asm;

// Assembly counterpart to this file.
global_asm!(
    include_str!("boot.s"),
    CONST_CORE_ID_MASK = const 0b11
);

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// The Rust entry of the `kernel` binary.
///
/// The function is called from the assembly `_start` function.
#[no_mangle]
pub unsafe fn _start_rust() -> ! {
    crate::kernel_init()
}


================================================
FILE: 04_safe_globals/src/_arch/aarch64/cpu/boot.s
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>

//--------------------------------------------------------------------------------------------------
// Definitions
//--------------------------------------------------------------------------------------------------

// Load the address of a symbol into a register, PC-relative.
//
// The symbol must lie within +/- 4 GiB of the Program Counter.
//
// # Resources
//
// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html
.macro ADR_REL register, symbol
	adrp	\register, \symbol
	add	\register, \register, #:lo12:\symbol
.endm

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
.section .text._start

//------------------------------------------------------------------------------
// fn _start()
//------------------------------------------------------------------------------
_start:
	// Only proceed on the boot core. Park it otherwise.
	mrs	x0, MPIDR_EL1
	and	x0, x0, {CONST_CORE_ID_MASK}
	ldr	x1, BOOT_CORE_ID      // provided by bsp/__board_name__/cpu.rs
	cmp	x0, x1
	b.ne	.L_parking_loop

	// If execution reaches here, it is the boot core.

	// Initialize DRAM.
	ADR_REL	x0, __bss_start
	ADR_REL x1, __bss_end_exclusive

.L_bss_init_loop:
	cmp	x0, x1
	b.eq	.L_prepare_rust
	stp	xzr, xzr, [x0], #16
	b	.L_bss_init_loop

	// Prepare the jump to Rust code.
.L_prepare_rust:
	// Set the stack pointer.
	ADR_REL	x0, __boot_core_stack_end_exclusive
	mov	sp, x0

	// Jump to Rust code.
	b	_start_rust

	// Infinitely wait for events (aka "park the core").
.L_parking_loop:
	wfe
	b	.L_parking_loop

.size	_start, . - _start
.type	_start, function
.global	_start


================================================
FILE: 04_safe_globals/src/_arch/aarch64/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Architectural processor code.
//!
//! # Orientation
//!
//! Since arch modules are imported into generic modules using the path attribute, the path of this
//! file is:
//!
//! crate::cpu::arch_cpu

use aarch64_cpu::asm;

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Pause execution on the core.
#[inline(always)]
pub fn wait_forever() -> ! {
    loop {
        asm::wfe()
    }
}


================================================
FILE: 04_safe_globals/src/bsp/raspberrypi/console.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! BSP console facilities.

use crate::{console, synchronization, synchronization::NullLock};
use core::fmt;

//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------

/// A mystical, magical device for generating QEMU output out of the void.
///
/// The mutex protected part.
struct QEMUOutputInner {
    chars_written: usize,
}

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// The main struct.
pub struct QEMUOutput {
    inner: NullLock<QEMUOutputInner>,
}

//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------

static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new();

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

impl QEMUOutputInner {
    const fn new() -> QEMUOutputInner {
        QEMUOutputInner { chars_written: 0 }
    }

    /// Send a character.
    fn write_char(&mut self, c: char) {
        unsafe {
            core::ptr::write_volatile(0x3F20_1000 as *mut u8, c as u8);
        }

        self.chars_written += 1;
    }
}

/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
/// we get `write_fmt()` automatically.
///
/// The function takes an `&mut self`, so it must be implemented for the inner struct.
///
/// See [`src/print.rs`].
///
/// [`src/print.rs`]: ../../print/index.html
impl fmt::Write for QEMUOutputInner {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            // Convert newline to carrige return + newline.
            if c == '\n' {
                self.write_char('\r')
            }

            self.write_char(c);
        }

        Ok(())
    }
}

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

impl QEMUOutput {
    /// Create a new instance.
    pub const fn new() -> QEMUOutput {
        QEMUOutput {
            inner: NullLock::new(QEMUOutputInner::new()),
        }
    }
}

/// Return a reference to the console.
pub fn console() -> &'static dyn console::interface::All {
    &QEMU_OUTPUT
}

//------------------------------------------------------------------------------
// OS Interface Code
//------------------------------------------------------------------------------
use synchronization::interface::Mutex;

/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to
/// serialize access.
impl console::interface::Write for QEMUOutput {
    fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
        // Fully qualified syntax for the call to `core::fmt::Write::write_fmt()` to increase
        // readability.
        self.inner.lock(|inner| fmt::Write::write_fmt(inner, args))
    }
}

impl console::interface::Statistics for QEMUOutput {
    fn chars_written(&self) -> usize {
        self.inner.lock(|inner| inner.chars_written)
    }
}

impl console::interface::All for QEMUOutput {}


================================================
FILE: 04_safe_globals/src/bsp/raspberrypi/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! BSP Processor code.

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Used by `arch` code to find the early boot core.
#[no_mangle]
#[link_section = ".text._start_arguments"]
pub static BOOT_CORE_ID: u64 = 0;


================================================
FILE: 04_safe_globals/src/bsp/raspberrypi/kernel.ld
================================================
/* SPDX-License-Identifier: MIT OR Apache-2.0
 *
 * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
 */

__rpi_phys_dram_start_addr = 0;

/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
__rpi_phys_binary_load_addr = 0x80000;


ENTRY(__rpi_phys_binary_load_addr)

/* Flags:
 *     4 == R
 *     5 == RX
 *     6 == RW
 *
 * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
 * It doesn't mean all of them need actually be loaded.
 */
PHDRS
{
    segment_boot_core_stack PT_LOAD FLAGS(6);
    segment_code            PT_LOAD FLAGS(5);
    segment_data            PT_LOAD FLAGS(6);
}

SECTIONS
{
    . =  __rpi_phys_dram_start_addr;

    /***********************************************************************************************
    * Boot Core Stack
    ***********************************************************************************************/
    .boot_core_stack (NOLOAD) :
    {
                                             /*   ^             */
                                             /*   | stack       */
        . += __rpi_phys_binary_load_addr;    /*   | growth      */
                                             /*   | direction   */
        __boot_core_stack_end_exclusive = .; /*   |             */
    } :segment_boot_core_stack

    /***********************************************************************************************
    * Code + RO Data + Global Offset Table
    ***********************************************************************************************/
    .text :
    {
        KEEP(*(.text._start))
        *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
        *(.text._start_rust)      /* The Rust entry point */
        *(.text*)                 /* Everything else */
    } :segment_code

    .rodata : ALIGN(8) { *(.rodata*) } :segment_code

    /***********************************************************************************************
    * Data + BSS
    ***********************************************************************************************/
    .data : { *(.data*) } :segment_data

    /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
    .bss (NOLOAD) : ALIGN(16)
    {
        __bss_start = .;
        *(.bss*);
        . = ALIGN(16);
        __bss_end_exclusive = .;
    } :segment_data

    /***********************************************************************************************
    * Misc
    ***********************************************************************************************/
    .got : { *(.got*) }
    ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")

    /DISCARD/ : { *(.comment*) }
}


================================================
FILE: 04_safe_globals/src/bsp/raspberrypi.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Top-level BSP file for the Raspberry Pi 3 and 4.

pub mod console;
pub mod cpu;


================================================
FILE: 04_safe_globals/src/bsp.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Conditional reexporting of Board Support Packages.

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
mod raspberrypi;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
pub use raspberrypi::*;


================================================
FILE: 04_safe_globals/src/console.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! System console.

use crate::bsp;

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Console interfaces.
pub mod interface {
    use core::fmt;

    /// Console write functions.
    pub trait Write {
        /// Write a Rust format string.
        fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    }

    /// Console statistics.
    pub trait Statistics {
        /// Return the number of characters written.
        fn chars_written(&self) -> usize {
            0
        }
    }

    /// Trait alias for a full-fledged console.
    pub trait All: Write + Statistics {}
}

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
    bsp::console::console()
}


================================================
FILE: 04_safe_globals/src/cpu/boot.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>

//! Boot code.

#[cfg(target_arch = "aarch64")]
#[path = "../_arch/aarch64/cpu/boot.rs"]
mod arch_boot;


================================================
FILE: 04_safe_globals/src/cpu.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>

//! Processor code.

#[cfg(target_arch = "aarch64")]
#[path = "_arch/aarch64/cpu.rs"]
mod arch_cpu;

mod boot;

//--------------------------------------------------------------------------------------------------
// Architectural Public Reexports
//--------------------------------------------------------------------------------------------------
pub use arch_cpu::wait_forever;


================================================
FILE: 04_safe_globals/src/main.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

// Rust embedded logo for `make doc`.
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/rust-embedded/wg/master/assets/logo/ewg-logo-blue-white-on-transparent.png"
)]

//! The `kernel` binary.
//!
//! # Code organization and architecture
//!
//! The code is divided into different *modules*, each representing a typical **subsystem** of the
//! `kernel`. Top-level module files of subsystems reside directly in the `src` folder. For example,
//! `src/memory.rs` contains code that is concerned with all things memory management.
//!
//! ## Visibility of processor architecture code
//!
//! Some of the `kernel`'s subsystems depend on low-level code that is specific to the target
//! processor architecture. For each supported processor architecture, there exists a subfolder in
//! `src/_arch`, for example, `src/_arch/aarch64`.
//!
//! The architecture folders mirror the subsystem modules laid out in `src`. For example,
//! architectural code that belongs to the `kernel`'s MMU subsystem (`src/memory/mmu.rs`) would go
//! into `src/_arch/aarch64/memory/mmu.rs`. The latter file is loaded as a module in
//! `src/memory/mmu.rs` using the `path attribute`. Usually, the chosen module name is the generic
//! module's name prefixed with `arch_`.
//!
//! For example, this is the top of `src/memory/mmu.rs`:
//!
//! ```
//! #[cfg(target_arch = "aarch64")]
//! #[path = "../_arch/aarch64/memory/mmu.rs"]
//! mod arch_mmu;
//! ```
//!
//! Often times, items from the `arch_ module` will be publicly reexported by the parent module.
//! This way, each architecture specific module can provide its implementation of an item, while the
//! caller must not be concerned which architecture has been conditionally compiled.
//!
//! ## BSP code
//!
//! `BSP` stands for Board Support Package. `BSP` code is organized under `src/bsp.rs` and contains
//! target board specific definitions and functions. These are things such as the board's memory map
//! or instances of drivers for devices that are featured on the respective board.
//!
//! Just like processor architecture code, the `BSP` code's module structure tries to mirror the
//! `kernel`'s subsystem modules, but there is no reexporting this time. That means whatever is
//! provided must be called starting from the `bsp` namespace, e.g. `bsp::driver::driver_manager()`.
//!
//! ## Kernel interfaces
//!
//! Both `arch` and `bsp` contain code that is conditionally compiled depending on the actual target
//! and board for which the kernel is compiled. For example, the `interrupt controller` hardware of
//! the `Raspberry Pi 3` and the `Raspberry Pi 4` is different, but we want the rest of the `kernel`
//! code to play nicely with any of the two without much hassle.
//!
//! In order to provide a clean abstraction between `arch`, `bsp` and `generic kernel code`,
//! `interface` traits are provided *whenever possible* and *where it makes sense*. They are defined
//! in the respective subsystem module and help to enforce the idiom of *program to an interface,
//! not an implementation*. For example, there will be a common IRQ handling interface which the two
//! different interrupt controller `drivers` of both Raspberrys will implement, and only export the
//! interface to the rest of the `kernel`.
//!
//! ```
//!         +-------------------+
//!         | Interface (Trait) |
//!         |                   |
//!         +--+-------------+--+
//!            ^             ^
//!            |             |
//!            |             |
//! +----------+--+       +--+----------+
//! | kernel code |       |  bsp code   |
//! |             |       |  arch code  |
//! +-------------+       +-------------+
//! ```
//!
//! # Summary
//!
//! For a logical `kernel` subsystem, corresponding code can be distributed over several physical
//! locations. Here is an example for the **memory** subsystem:
//!
//! - `src/memory.rs` and `src/memory/**/*`
//!   - Common code that is agnostic of target processor architecture and `BSP` characteristics.
//!     - Example: A function to zero a chunk of memory.
//!   - Interfaces for the memory subsystem that are implemented by `arch` or `BSP` code.
//!     - Example: An `MMU` interface that defines `MMU` function prototypes.
//! - `src/bsp/__board_name__/memory.rs` and `src/bsp/__board_name__/memory/**/*`
//!   - `BSP` specific code.
//!   - Example: The board's memory map (physical addresses of DRAM and MMIO devices).
//! - `src/_arch/__arch_name__/memory.rs` and `src/_arch/__arch_name__/memory/**/*`
//!   - Processor architecture specific code.
//!   - Example: Implementation of the `MMU` interface for the `__arch_name__` processor
//!     architecture.
//!
//! From a namespace perspective, **memory** subsystem code lives in:
//!
//! - `crate::memory::*`
//! - `crate::bsp::memory::*`
//!
//! # Boot flow
//!
//! 1. The kernel's entry point is the function `cpu::boot::arch_boot::_start()`.
//!     - It is implemented in `src/_arch/__arch_name__/cpu/boot.s`.
//! 2. Once finished with architectural setup, the arch code calls `kernel_init()`.

#![feature(asm_const)]
#![feature(format_args_nl)]
#![feature(panic_info_message)]
#![feature(trait_alias)]
#![no_main]
#![no_std]

mod bsp;
mod console;
mod cpu;
mod panic_wait;
mod print;
mod synchronization;

/// Early init code.
///
/// # Safety
///
/// - Only a single core must be active and running this function.
unsafe fn kernel_init() -> ! {
    use console::console;

    println!("[0] Hello from Rust!");

    println!("[1] Chars written: {}", console().chars_written());

    println!("[2] Stopping here.");
    cpu::wait_forever()
}


================================================
FILE: 04_safe_globals/src/panic_wait.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! A panic handler that infinitely waits.

use crate::{cpu, println};
use core::panic::PanicInfo;

//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------

/// Stop immediately if called a second time.
///
/// # Note
///
/// Using atomics here relieves us from needing to use `unsafe` for the static variable.
///
/// On `AArch64`, which is the only implemented architecture at the time of writing this,
/// [`AtomicBool::load`] and [`AtomicBool::store`] are lowered to ordinary load and store
/// instructions. They are therefore safe to use even with MMU + caching deactivated.
///
/// [`AtomicBool::load`]: core::sync::atomic::AtomicBool::load
/// [`AtomicBool::store`]: core::sync::atomic::AtomicBool::store
fn panic_prevent_reenter() {
    use core::sync::atomic::{AtomicBool, Ordering};

    #[cfg(not(target_arch = "aarch64"))]
    compile_error!("Add the target_arch to above's check if the following code is safe to use");

    static PANIC_IN_PROGRESS: AtomicBool = AtomicBool::new(false);

    if !PANIC_IN_PROGRESS.load(Ordering::Relaxed) {
        PANIC_IN_PROGRESS.store(true, Ordering::Relaxed);

        return;
    }

    cpu::wait_forever()
}

#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
    // Protect against panic infinite loops if any of the following code panics itself.
    panic_prevent_reenter();

    let (location, line, column) = match info.location() {
        Some(loc) => (loc.file(), loc.line(), loc.column()),
        _ => ("???", 0, 0),
    };

    println!(
        "Kernel panic!\n\n\
        Panic location:\n      File '{}', line {}, column {}\n\n\
        {}",
        location,
        line,
        column,
        info.message().unwrap_or(&format_args!("")),
    );

    cpu::wait_forever()
}


================================================
FILE: 04_safe_globals/src/print.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

//! Printing.

use crate::console;
use core::fmt;

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
    console::console().write_fmt(args).unwrap();
}

/// Prints without a newline.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*)));
}

/// Prints with a newline.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({
        $crate::print::_print(format_args_nl!($($arg)*));
    })
}


================================================
FILE: 04_safe_globals/src/synchronization.rs
================================================
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>

//! Synchronization primitives.
//!
//! # Resources
//!
//!   - <https://doc.rust-lang.org/book/ch16-04-extensible-concurrency-sync-and-send.html>
//!   - <https://stackoverflow.com/questions/59428096/understanding-the-send-trait>
//!   - <https://doc.rust-lang.org/std/cell/index.html>

use core::cell::UnsafeCell;

//--------------------------------------------------------------------------------------------------
// Public Definitions
//--------------------------------------------------------------------------------------------------

/// Synchronization interfaces.
pub mod interface {

    /// Any object implementing this trait guarantees exclusive access to the data wrapped within
    /// the Mutex for the duration of the provided closure.
    pub trait Mutex {
        /// The type of the data that is wrapped by this mutex.
        type Data;

        /// Locks the mutex and grants the closure temporary mutable access to the wrapped data.
        fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
    }
}

/// A pseudo-lock for teaching purposes.
///
/// In contrast to a real Mutex implementation, does not protect against concurrent access from
/// other cores to the contained data. This part is preserved for later lessons.
///
/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is
/// executing single-threaded, aka only running on a single core with interrupts disabled.
pub struct NullLock<T>
where
    T: ?Sized,
{
    data: UnsafeCell<T>,
}

//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------

unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {}
unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}

impl<T> NullLock<T> {
    /// Create an instance.
    pub const fn new(data: T) -> Self {
        Self {
            data: UnsafeCell::new(data),
        }
    }
}

//------------------------------------------------------------------------------
// OS Interface Code
//------------------------------------------------------------------------------

impl<T> interface::Mutex for NullLock<T> {
    type Data = T;

    fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
        // In a real lock, there would be code encapsulating this line that ensures that this
        // mutable reference will ever only be given out once at a time.
        let data = unsafe { &mut *self.data.get() };

        f(data)
    }
}


================================================
FILE: 04_safe_globals/tests/boot_test_string.rb
================================================
# frozen_string_literal: true

EXPECTED_PRINT = 'Stopping here'


================================================
FILE: 05_drivers_gpio_uart/.vscode/settings.json
================================================
{
    "editor.formatOnSave": true,
    "editor.rulers": [100],
    "rust-analyzer.cargo.target": "aarch64-unknown-none-softfloat",
    "rust-analyzer.cargo.features": ["bsp_rpi3"],
    "rust-analyzer.checkOnSave.allTargets": false,
    "rust-analyzer.checkOnSave.extraArgs": ["--bins"],
    "rust-analyzer.lens.debug": false,
    "rust-analyzer.lens.run": false
}


================================================
FILE: 05_drivers_gpio_uart/Cargo.toml
================================================
[package]
name = "mingo"
version = "0.5.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2021"

[profile.release]
lto = true

[features]
default = []
bsp_rpi3 = ["tock-registers"]
bsp_rpi4 = ["tock-registers"]

[[bin]]
name = "kernel"
path = "src/main.rs"

##--------------------------------------------------------------------------------------------------
## Dependencies
##--------------------------------------------------------------------------------------------------

[dependencies]

# Optional dependencies
tock-registers = { version = "0.8.x", default-features = false, features = ["register_types"], optional = true }

# Platform specific dependencies
[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = { version = "9.x.x" }


================================================
FILE: 05_drivers_gpio_uart/Makefile
================================================
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>

include ../common/docker.mk
include ../common/format.mk
include ../common/operating_system.mk

##--------------------------------------------------------------------------------------------------
## Optional, user-provided configuration values
##--------------------------------------------------------------------------------------------------

# Default to the RPi3.
BSP ?= rpi3

# Default to a serial device name that is common in Linux.
DEV_SERIAL ?= /dev/ttyUSB0



##--------------------------------------------------------------------------------------------------
## BSP-specific configuration values
##--------------------------------------------------------------------------------------------------
QEMU_MISSING_STRING = "This board is not yet supported for QEMU."

ifeq ($(BSP),rpi3)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE = raspi3
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a53
else ifeq ($(BSP),rpi4)
    TARGET            = aarch64-unknown-none-softfloat
    KERNEL_BIN        = kernel8.img
    QEMU_BINARY       = qemu-system-aarch64
    QEMU_MACHINE_TYPE =
    QEMU_RELEASE_ARGS = -serial stdio -display none
    OBJDUMP_BINARY    = aarch64-none-elf-objdump
    NM_BINARY         = aarch64-none-elf-nm
    READELF_BINARY    = aarch64-none-elf-readelf
    LD_SCRIPT_PATH    = $(shell pwd)/src/bsp/raspberrypi
    RUSTC_MISC_ARGS   = -C target-cpu=cortex-a72
endif

# Export for build.rs.
export LD_SCRIPT_PATH



##--------------------------------------------------------------------------------------------------
## Targets and Prerequisites
##--------------------------------------------------------------------------------------------------
KERNEL_MANIFEST      = Cargo.toml
KERNEL_LINKER_SCRIPT = kernel.ld
LAST_BUILD_CONFIG    = target/$(BSP).build_config

KERNEL_ELF      = target/$(TARGET)/release/kernel
# This parses cargo's dep-info file.
# https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files
KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG)



##--------------------------------------------------------------------------------------------------
## Command building blocks
##--------------------------------------------------------------------------------------------------
RUSTFLAGS = $(RUSTC_MISC_ARGS)                   \
    -C link-arg=--library-path=$(LD_SCRIPT_PATH) \
    -C link-arg=--script=$(KERNEL_LINKER_SCRIPT)

RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \
    -D warnings                   \
    -D missing_docs

FEATURES      = --features bsp_$(BSP)
COMPILER_ARGS = --target=$(TARGET) \
    $(FEATURES)                    \
    --release

RUSTC_CMD   = cargo rustc $(COMPILER_ARGS)
DOC_CMD     = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD  = cargo clippy $(COMPILER_ARGS)
OBJCOPY_CMD = rust-objcopy \
    --strip-all            \
    -O binary

EXEC_QEMU          = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE)
EXEC_TEST_DISPATCH = ruby ../common/tests/dispatch.rb
EXEC_MINITERM      = ruby ../common/serial/miniterm.rb

##------------------------------------------------------------------------------
## Dockerization
##------------------------------------------------------------------------------
DOCKER_CMD            = docker run -t --rm -v $(shell pwd):/work/tutorial -w /work/tutorial
DOCKER_CMD_INTERACT   = $(DOCKER_CMD) -i
DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common
DOCKER_ARG_DEV        = --privileged -v /dev:/dev

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU  = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
DOCKER_TEST  = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)

# Dockerize commands, which require USB device passthrough, only on Linux.
ifeq ($(shell uname -s),Linux)
    DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV)

    DOCKER_MINITERM = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)
endif



##--------------------------------------------------------------------------------------------------
## Targets
##--------------------------------------------------------------------------------------------------
.PHONY: all doc qemu miniterm clippy clean readelf objdump nm check

all: $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Save the configuration as a file, so make understands if it changed.
##------------------------------------------------------------------------------
$(LAST_BUILD_CONFIG):
	@rm -f target/*.build_config
	@mkdir -p target
	@touch $(LAST_BUILD_CONFIG)

##------------------------------------------------------------------------------
## Compile the kernel ELF
##------------------------------------------------------------------------------
$(KERNEL_ELF): $(KERNEL_ELF_DEPS)
	$(call color_header, "Compiling kernel ELF - $(BSP)")
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
## Generate the stripped kernel binary
##------------------------------------------------------------------------------
$(KERNEL_BIN): $(KERNEL_ELF)
	$(call color_header, "Generating stripped binary")
	@$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN)
	$(call color_progress_prefix, "Name")
	@echo $(KERNEL_BIN)
	$(call color_progress_prefix, "Size")
	$(call disk_usage_KiB, $(KERNEL_BIN))

##------------------------------------------------------------------------------
## Generate the documentation
##-----------------------------------------------------------------------------
doc:
	$(call color_header, "Generating docs")
	@$(DOC_CMD) --document-private-items --open

##------------------------------------------------------------------------------
## Run the kernel in QEMU
##------------------------------------------------------------------------------
ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

qemu:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

qemu: $(KERNEL_BIN)
	$(call color_header, "Launching QEMU")
	@$(DOCKER_QEMU) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)

endif

##------------------------------------------------------------------------------
## Connect to the target's serial
##------------------------------------------------------------------------------
miniterm:
	@$(DOCKER_MINITERM) $(EXEC_MINITERM) $(DEV_SERIAL)

##------------------------------------------------------------------------------
## Run clippy
##------------------------------------------------------------------------------
clippy:
	@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(CLIPPY_CMD)

##------------------------------------------------------------------------------
## Clean
##------------------------------------------------------------------------------
clean:
	rm -rf target $(KERNEL_BIN)

##------------------------------------------------------------------------------
## Run readelf
##------------------------------------------------------------------------------
readelf: $(KERNEL_ELF)
	$(call color_header, "Launching readelf")
	@$(DOCKER_TOOLS) $(READELF_BINARY) --headers $(KERNEL_ELF)

##------------------------------------------------------------------------------
## Run objdump
##------------------------------------------------------------------------------
objdump: $(KERNEL_ELF)
	$(call color_header, "Launching objdump")
	@$(DOCKER_TOOLS) $(OBJDUMP_BINARY) --disassemble --demangle \
                --section .text   \
                --section .rodata \
                $(KERNEL_ELF) | rustfilt

##------------------------------------------------------------------------------
## Run nm
##------------------------------------------------------------------------------
nm: $(KERNEL_ELF)
	$(call color_header, "Launching nm")
	@$(DOCKER_TOOLS) $(NM_BINARY) --demangle --print-size $(KERNEL_ELF) | sort | rustfilt



##--------------------------------------------------------------------------------------------------
## Testing targets
##--------------------------------------------------------------------------------------------------
.PHONY: test test_boot

ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

test_boot test:
	$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

##------------------------------------------------------------------------------
## Run boot test
##-----------------------------------------------------------------------------
Download .txt
gitextract_d1imolyg/

├── .editorconfig
├── .githooks/
│   └── pre-commit
├── .github/
│   ├── FUNDING.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── build_rpi3.yml
│       ├── build_rpi4.yml
│       ├── sanity.yml
│       ├── test_integration.yml
│       ├── test_unit.yml
│       └── test_xtra.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .rubocop.yml
├── .ruby-version
├── .rustfmt.toml
├── .vscode/
│   └── settings.json
├── 00_before_we_start/
│   ├── README.CN.md
│   ├── README.ES.md
│   └── README.md
├── 01_wait_forever/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   └── src/
│       ├── _arch/
│       │   └── aarch64/
│       │       └── cpu/
│       │           ├── boot.rs
│       │           └── boot.s
│       ├── bsp/
│       │   ├── raspberrypi/
│       │   │   └── kernel.ld
│       │   └── raspberrypi.rs
│       ├── bsp.rs
│       ├── cpu/
│       │   └── boot.rs
│       ├── cpu.rs
│       ├── main.rs
│       └── panic_wait.rs
├── 02_runtime_init/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   └── src/
│       ├── _arch/
│       │   └── aarch64/
│       │       ├── cpu/
│       │       │   ├── boot.rs
│       │       │   └── boot.s
│       │       └── cpu.rs
│       ├── bsp/
│       │   ├── raspberrypi/
│       │   │   ├── cpu.rs
│       │   │   └── kernel.ld
│       │   └── raspberrypi.rs
│       ├── bsp.rs
│       ├── cpu/
│       │   └── boot.rs
│       ├── cpu.rs
│       ├── main.rs
│       └── panic_wait.rs
├── 03_hacky_hello_world/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.ES.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   └── kernel.ld
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   └── print.rs
│   └── tests/
│       └── boot_test_string.rb
├── 04_safe_globals/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   └── kernel.ld
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   └── tests/
│       └── boot_test_string.rb
├── 05_drivers_gpio_uart/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── console.rs
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   └── tests/
│       └── boot_test_string.rb
├── 06_uart_chainloader/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── demo_payload_rpi3.img
│   ├── demo_payload_rpi4.img
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       └── cpu.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   └── synchronization.rs
│   ├── tests/
│   │   └── chainboot_test.rb
│   └── update.sh
├── 07_timestamps/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 08_hw_debug_JTAG/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 09_privilege_level/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 10_virtual_mem_part1_identity_mapping/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.CN.md
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       ├── memory/
│   │   │       │   ├── mmu/
│   │   │       │   │   └── translation_table.rs
│   │   │       │   └── mmu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   ├── memory/
│   │   │   │   │   └── mmu.rs
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── common.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── memory/
│   │   │   ├── mmu/
│   │   │   │   └── translation_table.rs
│   │   │   └── mmu.rs
│   │   ├── memory.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 11_exceptions_part1_groundwork/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── build.rs
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       ├── exception/
│   │   │       │   └── asynchronous.rs
│   │   │       ├── exception.rs
│   │   │       ├── exception.s
│   │   │       ├── memory/
│   │   │       │   ├── mmu/
│   │   │       │   │   └── translation_table.rs
│   │   │       │   └── mmu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   ├── memory/
│   │   │   │   │   └── mmu.rs
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── common.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── exception/
│   │   │   └── asynchronous.rs
│   │   ├── exception.rs
│   │   ├── main.rs
│   │   ├── memory/
│   │   │   ├── mmu/
│   │   │   │   └── translation_table.rs
│   │   │   └── mmu.rs
│   │   ├── memory.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   └── tests/
│       └── boot_test_string.rb
├── 12_integrated_testing/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   └── boot.s
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   └── boot.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   └── translation_table.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 13_exceptions_part2_peripheral_IRQs/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   └── translation_table.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 14_virtual_mem_part2_mmio_remap/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   └── libraries/
│       ├── test-macros/
│       │   ├── Cargo.toml
│       │   └── src/
│       │       └── lib.rs
│       └── test-types/
│           ├── Cargo.toml
│           └── src/
│               └── lib.rs
├── 15_virtual_mem_part3_precomputed_tables/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── libraries/
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 16_virtual_mem_part4_higher_half_kernel/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── libraries/
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 17_kernel_symbols/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 18_backtrace/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── null_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 19_kernel_heap/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── buffer_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── heap_alloc.rs
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── 20_timer_callbacks/
│   ├── .cargo/
│   │   └── config.toml
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── kernel/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── src/
│   │   │   ├── _arch/
│   │   │   │   └── aarch64/
│   │   │   │       ├── backtrace.rs
│   │   │   │       ├── cpu/
│   │   │   │       │   ├── boot.rs
│   │   │   │       │   ├── boot.s
│   │   │   │       │   └── smp.rs
│   │   │   │       ├── cpu.rs
│   │   │   │       ├── exception/
│   │   │   │       │   └── asynchronous.rs
│   │   │   │       ├── exception.rs
│   │   │   │       ├── exception.s
│   │   │   │       ├── memory/
│   │   │   │       │   ├── mmu/
│   │   │   │       │   │   └── translation_table.rs
│   │   │   │       │   └── mmu.rs
│   │   │   │       └── time.rs
│   │   │   ├── backtrace.rs
│   │   │   ├── bsp/
│   │   │   │   ├── device_driver/
│   │   │   │   │   ├── arm/
│   │   │   │   │   │   ├── gicv2/
│   │   │   │   │   │   │   ├── gicc.rs
│   │   │   │   │   │   │   └── gicd.rs
│   │   │   │   │   │   └── gicv2.rs
│   │   │   │   │   ├── arm.rs
│   │   │   │   │   ├── bcm/
│   │   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller/
│   │   │   │   │   │   │   ├── local_ic.rs
│   │   │   │   │   │   │   └── peripheral_ic.rs
│   │   │   │   │   │   ├── bcm2xxx_interrupt_controller.rs
│   │   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   │   ├── bcm.rs
│   │   │   │   │   └── common.rs
│   │   │   │   ├── device_driver.rs
│   │   │   │   ├── raspberrypi/
│   │   │   │   │   ├── cpu.rs
│   │   │   │   │   ├── driver.rs
│   │   │   │   │   ├── exception/
│   │   │   │   │   │   └── asynchronous.rs
│   │   │   │   │   ├── exception.rs
│   │   │   │   │   ├── kernel.ld
│   │   │   │   │   ├── kernel_virt_addr_space_size.ld
│   │   │   │   │   ├── memory/
│   │   │   │   │   │   └── mmu.rs
│   │   │   │   │   └── memory.rs
│   │   │   │   └── raspberrypi.rs
│   │   │   ├── bsp.rs
│   │   │   ├── common.rs
│   │   │   ├── console/
│   │   │   │   └── buffer_console.rs
│   │   │   ├── console.rs
│   │   │   ├── cpu/
│   │   │   │   ├── boot.rs
│   │   │   │   └── smp.rs
│   │   │   ├── cpu.rs
│   │   │   ├── driver.rs
│   │   │   ├── exception/
│   │   │   │   ├── asynchronous/
│   │   │   │   │   └── null_irq_manager.rs
│   │   │   │   └── asynchronous.rs
│   │   │   ├── exception.rs
│   │   │   ├── lib.rs
│   │   │   ├── main.rs
│   │   │   ├── memory/
│   │   │   │   ├── heap_alloc.rs
│   │   │   │   ├── mmu/
│   │   │   │   │   ├── mapping_record.rs
│   │   │   │   │   ├── page_alloc.rs
│   │   │   │   │   ├── translation_table.rs
│   │   │   │   │   └── types.rs
│   │   │   │   └── mmu.rs
│   │   │   ├── memory.rs
│   │   │   ├── panic_wait.rs
│   │   │   ├── print.rs
│   │   │   ├── state.rs
│   │   │   ├── symbols.rs
│   │   │   ├── synchronization.rs
│   │   │   └── time.rs
│   │   └── tests/
│   │       ├── 00_console_sanity.rb
│   │       ├── 00_console_sanity.rs
│   │       ├── 01_timer_sanity.rs
│   │       ├── 02_exception_sync_page_fault.rs
│   │       ├── 03_exception_restore_sanity.rb
│   │       ├── 03_exception_restore_sanity.rs
│   │       ├── 04_exception_irq_sanity.rs
│   │       ├── 05_backtrace_sanity.rb
│   │       ├── 05_backtrace_sanity.rs
│   │       ├── 06_backtrace_invalid_frame.rb
│   │       ├── 06_backtrace_invalid_frame.rs
│   │       ├── 07_backtrace_invalid_link.rb
│   │       ├── 07_backtrace_invalid_link.rs
│   │       ├── boot_test_string.rb
│   │       ├── panic_exit_success/
│   │       │   └── mod.rs
│   │       └── panic_wait_forever/
│   │           └── mod.rs
│   ├── kernel_symbols/
│   │   ├── Cargo.toml
│   │   ├── build.rs
│   │   ├── kernel_symbols.ld
│   │   └── src/
│   │       └── main.rs
│   ├── kernel_symbols.mk
│   ├── libraries/
│   │   ├── debug-symbol-types/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   ├── test-macros/
│   │   │   ├── Cargo.toml
│   │   │   └── src/
│   │   │       └── lib.rs
│   │   └── test-types/
│   │       ├── Cargo.toml
│   │       └── src/
│   │           └── lib.rs
│   └── tools/
│       ├── kernel_symbols_tool/
│       │   ├── cmds.rb
│       │   ├── kernel_elf.rb
│       │   └── main.rb
│       └── translation_table_tool/
│           ├── arch.rb
│           ├── bsp.rb
│           ├── generic.rb
│           ├── kernel_elf.rb
│           └── main.rb
├── Gemfile
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.CN.md
├── README.ES.md
├── README.md
├── SPONSORING.md
├── X1_JTAG_boot/
│   ├── .vscode/
│   │   └── settings.json
│   ├── Cargo.toml
│   ├── Makefile
│   ├── README.md
│   ├── build.rs
│   ├── jtag_boot_rpi3.img
│   ├── jtag_boot_rpi4.img
│   ├── src/
│   │   ├── _arch/
│   │   │   └── aarch64/
│   │   │       ├── cpu/
│   │   │       │   ├── boot.rs
│   │   │       │   └── boot.s
│   │   │       ├── cpu.rs
│   │   │       └── time.rs
│   │   ├── bsp/
│   │   │   ├── device_driver/
│   │   │   │   ├── bcm/
│   │   │   │   │   ├── bcm2xxx_gpio.rs
│   │   │   │   │   └── bcm2xxx_pl011_uart.rs
│   │   │   │   ├── bcm.rs
│   │   │   │   └── common.rs
│   │   │   ├── device_driver.rs
│   │   │   ├── raspberrypi/
│   │   │   │   ├── cpu.rs
│   │   │   │   ├── driver.rs
│   │   │   │   ├── kernel.ld
│   │   │   │   └── memory.rs
│   │   │   └── raspberrypi.rs
│   │   ├── bsp.rs
│   │   ├── console/
│   │   │   └── null_console.rs
│   │   ├── console.rs
│   │   ├── cpu/
│   │   │   └── boot.rs
│   │   ├── cpu.rs
│   │   ├── driver.rs
│   │   ├── main.rs
│   │   ├── panic_wait.rs
│   │   ├── print.rs
│   │   ├── synchronization.rs
│   │   └── time.rs
│   ├── tests/
│   │   └── boot_test_string.rb
│   └── update.sh
├── common/
│   ├── docker.mk
│   ├── format.mk
│   ├── operating_system.mk
│   ├── serial/
│   │   ├── minipush/
│   │   │   └── progressbar_patch.rb
│   │   ├── minipush.rb
│   │   └── miniterm.rb
│   └── tests/
│       ├── boot_test.rb
│       ├── console_io_test.rb
│       ├── dispatch.rb
│       ├── exit_code_test.rb
│       └── test.rb
├── contributor_setup.sh
├── devtool_completion.bash
├── doc/
│   ├── 09_wiring_jtag.fzz
│   ├── 09_wiring_jtag.xcf
│   ├── 14_BCM_driver.drawio
│   ├── 14_GICv2_driver.drawio
│   ├── 14_header.drawio
│   ├── demo_PS1.txt
│   ├── source_section_divider.txt
│   └── wiring.fzz
├── docker/
│   ├── README.md
│   └── rustembedded-osdev-utils/
│       ├── Dockerfile
│       ├── Makefile
│       ├── auto
│       ├── rpi3.cfg
│       └── rpi4.cfg
├── rust-toolchain.toml
└── utils/
    ├── devtool/
    │   └── copyright.rb
    ├── devtool.rb
    ├── diff_tut_folders.bash
    └── update_copyright.rb
Download .txt
Showing preview only (523K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (6228 symbols across 724 files)

FILE: 01_wait_forever/build.rs
  function main (line 3) | fn main() {

FILE: 01_wait_forever/src/panic_wait.rs
  function panic (line 14) | fn panic(_info: &PanicInfo) -> ! {

FILE: 02_runtime_init/build.rs
  function main (line 3) | fn main() {

FILE: 02_runtime_init/src/_arch/aarch64/cpu.rs
  function wait_forever (line 22) | pub fn wait_forever() -> ! {

FILE: 02_runtime_init/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 02_runtime_init/src/main.rs
  function kernel_init (line 122) | unsafe fn kernel_init() -> ! {

FILE: 02_runtime_init/src/panic_wait.rs
  function panic (line 15) | fn panic(_info: &PanicInfo) -> ! {

FILE: 03_hacky_hello_world/build.rs
  function main (line 3) | fn main() {

FILE: 03_hacky_hello_world/src/_arch/aarch64/cpu.rs
  function wait_forever (line 22) | pub fn wait_forever() -> ! {

FILE: 03_hacky_hello_world/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 03_hacky_hello_world/src/bsp/raspberrypi/console.rs
  type QEMUOutput (line 15) | struct QEMUOutput;
    method write_str (line 29) | fn write_str(&mut self, s: &str) -> fmt::Result {
  function console (line 45) | pub fn console() -> impl console::interface::Write {

FILE: 03_hacky_hello_world/src/console.rs
  function console (line 30) | pub fn console() -> impl interface::Write {

FILE: 03_hacky_hello_world/src/main.rs
  function kernel_init (line 126) | unsafe fn kernel_init() -> ! {

FILE: 03_hacky_hello_world/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 03_hacky_hello_world/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 04_safe_globals/build.rs
  function main (line 3) | fn main() {

FILE: 04_safe_globals/src/_arch/aarch64/cpu.rs
  function wait_forever (line 22) | pub fn wait_forever() -> ! {

FILE: 04_safe_globals/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 04_safe_globals/src/bsp/raspberrypi/console.rs
  type QEMUOutputInner (line 17) | struct QEMUOutputInner {
    method new (line 41) | const fn new() -> QEMUOutputInner {
    method write_char (line 46) | fn write_char(&mut self, c: char) {
    method write_str (line 65) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type QEMUOutput (line 26) | pub struct QEMUOutput {
    method new (line 85) | pub const fn new() -> QEMUOutput {
    method write_fmt (line 105) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method chars_written (line 113) | fn chars_written(&self) -> usize {
  function console (line 93) | pub fn console() -> &'static dyn console::interface::All {

FILE: 04_safe_globals/src/console.rs
  type Write (line 18) | pub trait Write {
    method write_fmt (line 20) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
  type Statistics (line 24) | pub trait Statistics {
    method chars_written (line 26) | fn chars_written(&self) -> usize {
  type All (line 32) | pub trait All: Write + Statistics {}
  function console (line 42) | pub fn console() -> &'static dyn interface::All {

FILE: 04_safe_globals/src/main.rs
  function kernel_init (line 128) | unsafe fn kernel_init() -> ! {

FILE: 04_safe_globals/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 04_safe_globals/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 04_safe_globals/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 05_drivers_gpio_uart/build.rs
  function main (line 3) | fn main() {

FILE: 05_drivers_gpio_uart/src/_arch/aarch64/cpu.rs
  function spin_for_cycles (line 25) | pub fn spin_for_cycles(n: usize) {
  function wait_forever (line 33) | pub fn wait_forever() -> ! {

FILE: 05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 169) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 180) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 200) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 207) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 214) | pub fn map_pl011_uart(&self) {
    method compatible (line 225) | fn compatible(&self) -> &'static str {

FILE: 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 05_drivers_gpio_uart/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 05_drivers_gpio_uart/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs
  function console (line 14) | pub fn console() -> &'static dyn console::interface::All {

FILE: 05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
  constant GPIO_OFFSET (line 15) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 16) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 23) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 24) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 25) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant START (line 33) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 34) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 35) | pub const PL011_UART_START: usize = START + UART_OFFSET;

FILE: 05_drivers_gpio_uart/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 05_drivers_gpio_uart/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 05_drivers_gpio_uart/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 05_drivers_gpio_uart/src/main.rs
  function kernel_init (line 131) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 146) | fn kernel_main() -> ! {

FILE: 05_drivers_gpio_uart/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 05_drivers_gpio_uart/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 05_drivers_gpio_uart/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 06_uart_chainloader/build.rs
  function main (line 3) | fn main() {

FILE: 06_uart_chainloader/src/_arch/aarch64/cpu.rs
  function spin_for_cycles (line 25) | pub fn spin_for_cycles(n: usize) {
  function wait_forever (line 33) | pub fn wait_forever() -> ! {

FILE: 06_uart_chainloader/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 169) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 180) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 200) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 207) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 214) | pub fn map_pl011_uart(&self) {
    method compatible (line 225) | fn compatible(&self) -> &'static str {

FILE: 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char (line 278) | fn read_char(&mut self, blocking_mode: BlockingMode) -> Option<char> {
    method write_str (line 312) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 326) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 333) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 346) | fn compatible(&self) -> &'static str {
    method init (line 350) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 360) | fn write_char(&self, c: char) {
    method write_fmt (line 364) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 370) | fn flush(&self) {
    method read_char (line 377) | fn read_char(&self) -> char {
    method clear_rx (line 382) | fn clear_rx(&self) {
    method chars_written (line 393) | fn chars_written(&self) -> usize {
    method chars_read (line 397) | fn chars_read(&self) -> usize {

FILE: 06_uart_chainloader/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 06_uart_chainloader/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 06_uart_chainloader/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 06_uart_chainloader/src/bsp/raspberrypi/memory.rs
  constant BOARD_DEFAULT_LOAD_ADDRESS (line 14) | pub const BOARD_DEFAULT_LOAD_ADDRESS: usize =        0x8_0000;
  constant GPIO_OFFSET (line 16) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 17) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 24) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 25) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 26) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant START (line 34) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 35) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 36) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  function board_default_load_addr (line 46) | pub fn board_default_load_addr() -> *const u64 {

FILE: 06_uart_chainloader/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 06_uart_chainloader/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 06_uart_chainloader/src/driver.rs
  constant NUM_DRIVERS (line 13) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 15) | struct DriverManagerInner {
    method new (line 69) | pub const fn new() -> Self {
  type DeviceDriver (line 27) | pub trait DeviceDriver {
    method compatible (line 29) | fn compatible(&self) -> &'static str;
    method init (line 36) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 43) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 47) | pub struct DeviceDriverDescriptor {
    method new (line 83) | pub fn new(
  type DriverManager (line 53) | pub struct DriverManager {
    method new (line 101) | pub const fn new() -> Self {
    method register_driver (line 108) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 116) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 131) | pub unsafe fn init_drivers(&self) {
  function driver_manager (line 95) | pub fn driver_manager() -> &'static DriverManager {

FILE: 06_uart_chainloader/src/main.rs
  function kernel_init (line 131) | unsafe fn kernel_init() -> ! {
  constant MINILOAD_LOGO (line 145) | const MINILOAD_LOGO: &str = r#"
  function kernel_main (line 153) | fn kernel_main() -> ! {

FILE: 06_uart_chainloader/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 06_uart_chainloader/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 06_uart_chainloader/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 06_uart_chainloader/tests/chainboot_test.rb
  class PowerTargetRequestTest (line 15) | class PowerTargetRequestTest < SubtestBase
    method initialize (line 18) | def initialize(qemu_cmd, pty_main)
    method name (line 24) | def name
    method run (line 28) | def run(qemu_out, _qemu_in)
  class ChainbootTest (line 39) | class ChainbootTest < BootTest
    method initialize (line 42) | def initialize(qemu_cmd, payload_path)
    method setup (line 53) | def setup
    method finish (line 66) | def finish

FILE: 07_timestamps/build.rs
  function main (line 3) | fn main() {

FILE: 07_timestamps/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {

FILE: 07_timestamps/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 07_timestamps/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 07_timestamps/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 07_timestamps/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 07_timestamps/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 71) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 07_timestamps/src/bsp/raspberrypi/memory.rs
  constant GPIO_OFFSET (line 15) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 16) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 23) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 24) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 25) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant START (line 33) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 34) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 35) | pub const PL011_UART_START: usize = START + UART_OFFSET;

FILE: 07_timestamps/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 07_timestamps/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 07_timestamps/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 07_timestamps/src/main.rs
  function kernel_init (line 135) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 150) | fn kernel_main() -> ! {

FILE: 07_timestamps/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 07_timestamps/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 07_timestamps/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 07_timestamps/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 08_hw_debug_JTAG/build.rs
  function main (line 3) | fn main() {

FILE: 08_hw_debug_JTAG/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {

FILE: 08_hw_debug_JTAG/src/_arch/aarch64/cpu/boot.rs
  function _start_rust (line 30) | pub unsafe fn _start_rust() -> ! {

FILE: 08_hw_debug_JTAG/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 08_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 08_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 08_hw_debug_JTAG/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 08_hw_debug_JTAG/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 08_hw_debug_JTAG/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 08_hw_debug_JTAG/src/bsp/raspberrypi/memory.rs
  constant GPIO_OFFSET (line 15) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 16) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 23) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 24) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 25) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant START (line 33) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 34) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 35) | pub const PL011_UART_START: usize = START + UART_OFFSET;

FILE: 08_hw_debug_JTAG/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 08_hw_debug_JTAG/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 08_hw_debug_JTAG/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 08_hw_debug_JTAG/src/main.rs
  function kernel_init (line 135) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 150) | fn kernel_main() -> ! {

FILE: 08_hw_debug_JTAG/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 08_hw_debug_JTAG/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 08_hw_debug_JTAG/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 08_hw_debug_JTAG/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 09_privilege_level/build.rs
  function main (line 3) | fn main() {

FILE: 09_privilege_level/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {

FILE: 09_privilege_level/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 09_privilege_level/src/_arch/aarch64/exception.rs
  function current_privilege_level (line 23) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {

FILE: 09_privilege_level/src/_arch/aarch64/exception/asynchronous.rs
  type DaifField (line 21) | trait DaifField {
    method daif_field (line 22) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 35) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 41) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 47) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 53) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 25) | struct Debug;
  type SError (line 26) | struct SError;
  type IRQ (line 27) | struct IRQ;
  type FIQ (line 28) | struct FIQ;
  function is_masked (line 58) | fn is_masked<T>() -> bool
  function print_state (line 71) | pub fn print_state() {

FILE: 09_privilege_level/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 09_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 09_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 09_privilege_level/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 09_privilege_level/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 09_privilege_level/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 09_privilege_level/src/bsp/raspberrypi/memory.rs
  constant GPIO_OFFSET (line 15) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 16) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 23) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 24) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 25) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant START (line 33) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 34) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 35) | pub const PL011_UART_START: usize = START + UART_OFFSET;

FILE: 09_privilege_level/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 09_privilege_level/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 09_privilege_level/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 09_privilege_level/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {

FILE: 09_privilege_level/src/main.rs
  function kernel_init (line 136) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 151) | fn kernel_main() -> ! {

FILE: 09_privilege_level/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 09_privilege_level/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 09_privilege_level/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 09_privilege_level/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 10_virtual_mem_part1_identity_mapping/build.rs
  function main (line 3) | fn main() {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception.rs
  function current_privilege_level (line 23) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/exception/asynchronous.rs
  type DaifField (line 21) | trait DaifField {
    method daif_field (line 22) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 35) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 41) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 47) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 53) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 25) | struct Debug;
  type SError (line 26) | struct SError;
  type IRQ (line 27) | struct IRQ;
  type FIQ (line 28) | struct FIQ;
  function is_masked (line 58) | fn is_masked<T>() -> bool
  function print_state (line 71) | pub fn print_state() {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 76) | fn set_up_mair(&self) {
    method configure_translation_control (line 89) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 122) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError> {
    method is_enabled (line 162) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 64) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 112) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 110) | struct TableDescriptor {
    method new_zeroed (line 168) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 173) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: usize) -> Se...
  type PageDescriptor (line 119) | struct PageDescriptor {
    method new_zeroed (line 228) | pub const fn new_zeroed() -> Self {
    method from_output_addr (line 233) | pub fn from_output_addr(phys_output_addr: usize, attribute_fields: &At...
  type StartAddr (line 123) | trait StartAddr {
    method phys_start_addr_u64 (line 124) | fn phys_start_addr_u64(&self) -> u64;
    method phys_start_addr_usize (line 125) | fn phys_start_addr_usize(&self) -> usize;
    method phys_start_addr_u64 (line 155) | fn phys_start_addr_u64(&self) -> u64 {
    method phys_start_addr_usize (line 159) | fn phys_start_addr_usize(&self) -> usize {
  constant NUM_LVL2_TABLES (line 128) | const NUM_LVL2_TABLES: usize = bsp::memory::mmu::KernelAddrSpace::SIZE >...
  type FixedSizeTranslationTable (line 138) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  type KernelTranslationTable (line 147) | pub type KernelTranslationTable = FixedSizeTranslationTable<NUM_LVL2_TAB...
  function from (line 191) | fn from(attribute_fields: AttributeFields) -> Self {
  function new (line 255) | pub const fn new() -> Self {
  function populate_tt_entries (line 270) | pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
  function phys_base_address (line 289) | pub fn phys_base_address(&self) -> u64 {

FILE: 10_virtual_mem_part1_identity_mapping/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory.rs
  constant END_INCLUSIVE (line 66) | pub const END_INCLUSIVE:       usize = 0xFFFF_FFFF;
  constant GPIO_OFFSET (line 68) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 69) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 76) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 77) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 78) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 79) | pub const END_INCLUSIVE:    usize =         0x4000_FFFF;
  constant START (line 87) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 88) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 89) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 90) | pub const END_INCLUSIVE:    usize =         0xFF84_FFFF;
  function code_start (line 104) | fn code_start() -> usize {
  function code_end_exclusive (line 113) | fn code_end_exclusive() -> usize {

FILE: 10_virtual_mem_part1_identity_mapping/src/bsp/raspberrypi/memory/mmu.rs
  type KernelAddrSpace (line 16) | pub type KernelAddrSpace = AddressSpace<{ memory_map::END_INCLUSIVE + 1 }>;
  constant NUM_MEM_RANGES (line 18) | const NUM_MEM_RANGES: usize = 3;
  function code_range_inclusive (line 64) | fn code_range_inclusive() -> RangeInclusive<usize> {
  function remapped_mmio_range_inclusive (line 70) | fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
  function mmio_range_inclusive (line 75) | fn mmio_range_inclusive() -> RangeInclusive<usize> {
  function virt_mem_layout (line 84) | pub fn virt_mem_layout() -> &'static KernelVirtualLayout<NUM_MEM_RANGES> {

FILE: 10_virtual_mem_part1_identity_mapping/src/common.rs
  function size_human_readable_ceil (line 8) | pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static s...

FILE: 10_virtual_mem_part1_identity_mapping/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 10_virtual_mem_part1_identity_mapping/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 10_virtual_mem_part1_identity_mapping/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 10_virtual_mem_part1_identity_mapping/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {

FILE: 10_virtual_mem_part1_identity_mapping/src/main.rs
  function kernel_init (line 144) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 165) | fn kernel_main() -> ! {

FILE: 10_virtual_mem_part1_identity_mapping/src/memory/mmu.rs
  type MMUEnableError (line 38) | pub enum MMUEnableError {
    method fmt (line 125) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MMU (line 48) | pub trait MMU {
    method enable_mmu_and_caching (line 55) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError>;
    method is_enabled (line 58) | fn is_enabled(&self) -> bool;
  type TranslationGranule (line 63) | pub struct TranslationGranule<const GRANULE_SIZE: usize>;
  type AddressSpace (line 66) | pub struct AddressSpace<const AS_SIZE: usize>;
  type Translation (line 72) | pub enum Translation {
  type MemAttributes (line 80) | pub enum MemAttributes {
  type AccessPermissions (line 88) | pub enum AccessPermissions {
  type AttributeFields (line 96) | pub struct AttributeFields {
  type TranslationDescriptor (line 104) | pub struct TranslationDescriptor {
    method fmt (line 176) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type KernelVirtualLayout (line 112) | pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
  constant SIZE (line 135) | pub const SIZE: usize = Self::size_checked();
  constant SHIFT (line 138) | pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 140) | const fn size_checked() -> usize {
  constant SIZE (line 149) | pub const SIZE: usize = Self::size_checked();
  constant SIZE_SHIFT (line 152) | pub const SIZE_SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 154) | const fn size_checked() -> usize {
  method default (line 165) | fn default() -> AttributeFields {
  function new (line 211) | pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL...
  function virt_addr_properties (line 223) | pub fn virt_addr_properties(
  function print_layout (line 246) | pub fn print_layout(&self) {

FILE: 10_virtual_mem_part1_identity_mapping/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 10_virtual_mem_part1_identity_mapping/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 10_virtual_mem_part1_identity_mapping/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 10_virtual_mem_part1_identity_mapping/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 11_exceptions_part1_groundwork/build.rs
  function main (line 3) | fn main() {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/exception.rs
  type SpsrEL1 (line 30) | struct SpsrEL1(InMemoryRegister<u64, SPSR_EL1::Register>);
    method fmt (line 160) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type EsrEL1 (line 31) | struct EsrEL1(InMemoryRegister<u64, ESR_EL1::Register>);
    method exception_class (line 192) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fmt (line 200) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type ExceptionContext (line 35) | struct ExceptionContext {
    method exception_class (line 221) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fault_address_valid (line 226) | fn fault_address_valid(&self) -> bool {
    method fmt (line 247) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function default_exception_handler (line 57) | fn default_exception_handler(exc: &ExceptionContext) {
  function current_el0_synchronous (line 70) | extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
  function current_el0_irq (line 75) | extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
  function current_el0_serror (line 80) | extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
  function current_elx_synchronous (line 89) | extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
  function current_elx_irq (line 106) | extern "C" fn current_elx_irq(e: &mut ExceptionContext) {
  function current_elx_serror (line 111) | extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
  function lower_aarch64_synchronous (line 120) | extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext) {
  function lower_aarch64_irq (line 125) | extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext) {
  function lower_aarch64_serror (line 130) | extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext) {
  function lower_aarch32_synchronous (line 139) | extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext) {
  function lower_aarch32_irq (line 144) | extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext) {
  function lower_aarch32_serror (line 149) | extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext) {
  function current_privilege_level (line 278) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
  function handling_init (line 296) | pub unsafe fn handling_init() {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/exception/asynchronous.rs
  type DaifField (line 21) | trait DaifField {
    method daif_field (line 22) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 35) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 41) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 47) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 53) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 25) | struct Debug;
  type SError (line 26) | struct SError;
  type IRQ (line 27) | struct IRQ;
  type FIQ (line 28) | struct FIQ;
  function is_masked (line 58) | fn is_masked<T>() -> bool
  function print_state (line 71) | pub fn print_state() {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 76) | fn set_up_mair(&self) {
    method configure_translation_control (line 89) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 122) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError> {
    method is_enabled (line 162) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 64) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 112) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 110) | struct TableDescriptor {
    method new_zeroed (line 168) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 173) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: usize) -> Se...
  type PageDescriptor (line 119) | struct PageDescriptor {
    method new_zeroed (line 228) | pub const fn new_zeroed() -> Self {
    method from_output_addr (line 233) | pub fn from_output_addr(phys_output_addr: usize, attribute_fields: &At...
  type StartAddr (line 123) | trait StartAddr {
    method phys_start_addr_u64 (line 124) | fn phys_start_addr_u64(&self) -> u64;
    method phys_start_addr_usize (line 125) | fn phys_start_addr_usize(&self) -> usize;
    method phys_start_addr_u64 (line 155) | fn phys_start_addr_u64(&self) -> u64 {
    method phys_start_addr_usize (line 159) | fn phys_start_addr_usize(&self) -> usize {
  constant NUM_LVL2_TABLES (line 128) | const NUM_LVL2_TABLES: usize = bsp::memory::mmu::KernelAddrSpace::SIZE >...
  type FixedSizeTranslationTable (line 138) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  type KernelTranslationTable (line 147) | pub type KernelTranslationTable = FixedSizeTranslationTable<NUM_LVL2_TAB...
  function from (line 191) | fn from(attribute_fields: AttributeFields) -> Self {
  function new (line 255) | pub const fn new() -> Self {
  function populate_tt_entries (line 270) | pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
  function phys_base_address (line 289) | pub fn phys_base_address(&self) -> u64 {

FILE: 11_exceptions_part1_groundwork/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 11_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 11_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 11_exceptions_part1_groundwork/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 11_exceptions_part1_groundwork/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 11_exceptions_part1_groundwork/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {

FILE: 11_exceptions_part1_groundwork/src/bsp/raspberrypi/memory.rs
  constant END_INCLUSIVE (line 66) | pub const END_INCLUSIVE:       usize = 0xFFFF_FFFF;
  constant GPIO_OFFSET (line 68) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 69) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 76) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 77) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 78) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 79) | pub const END_INCLUSIVE:    usize =         0x4000_FFFF;
  constant START (line 87) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 88) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 89) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 90) | pub const END_INCLUSIVE:    usize =         0xFF84_FFFF;
  function code_start (line 104) | fn code_start() -> usize {
  function code_end_exclusive (line 113) | fn code_end_exclusive() -> usize {

FILE: 11_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs
  type KernelAddrSpace (line 16) | pub type KernelAddrSpace = AddressSpace<{ memory_map::END_INCLUSIVE + 1 }>;
  constant NUM_MEM_RANGES (line 18) | const NUM_MEM_RANGES: usize = 2;
  function code_range_inclusive (line 54) | fn code_range_inclusive() -> RangeInclusive<usize> {
  function mmio_range_inclusive (line 60) | fn mmio_range_inclusive() -> RangeInclusive<usize> {
  function virt_mem_layout (line 69) | pub fn virt_mem_layout() -> &'static KernelVirtualLayout<NUM_MEM_RANGES> {

FILE: 11_exceptions_part1_groundwork/src/common.rs
  function size_human_readable_ceil (line 8) | pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static s...

FILE: 11_exceptions_part1_groundwork/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 11_exceptions_part1_groundwork/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 11_exceptions_part1_groundwork/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 11_exceptions_part1_groundwork/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {

FILE: 11_exceptions_part1_groundwork/src/main.rs
  function kernel_init (line 144) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 167) | fn kernel_main() -> ! {

FILE: 11_exceptions_part1_groundwork/src/memory/mmu.rs
  type MMUEnableError (line 38) | pub enum MMUEnableError {
    method fmt (line 125) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MMU (line 48) | pub trait MMU {
    method enable_mmu_and_caching (line 55) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError>;
    method is_enabled (line 58) | fn is_enabled(&self) -> bool;
  type TranslationGranule (line 63) | pub struct TranslationGranule<const GRANULE_SIZE: usize>;
  type AddressSpace (line 66) | pub struct AddressSpace<const AS_SIZE: usize>;
  type Translation (line 72) | pub enum Translation {
  type MemAttributes (line 80) | pub enum MemAttributes {
  type AccessPermissions (line 88) | pub enum AccessPermissions {
  type AttributeFields (line 96) | pub struct AttributeFields {
  type TranslationDescriptor (line 104) | pub struct TranslationDescriptor {
    method fmt (line 176) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type KernelVirtualLayout (line 112) | pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
  constant SIZE (line 135) | pub const SIZE: usize = Self::size_checked();
  constant SHIFT (line 138) | pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 140) | const fn size_checked() -> usize {
  constant SIZE (line 149) | pub const SIZE: usize = Self::size_checked();
  constant SIZE_SHIFT (line 152) | pub const SIZE_SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 154) | const fn size_checked() -> usize {
  method default (line 165) | fn default() -> AttributeFields {
  function new (line 211) | pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL...
  function virt_addr_properties (line 223) | pub fn virt_addr_properties(
  function print_layout (line 246) | pub fn print_layout(&self) {

FILE: 11_exceptions_part1_groundwork/src/panic_wait.rs
  function panic_prevent_reenter (line 26) | fn panic_prevent_reenter() {
  function panic (line 44) | fn panic(info: &PanicInfo) -> ! {

FILE: 11_exceptions_part1_groundwork/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 11_exceptions_part1_groundwork/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 11_exceptions_part1_groundwork/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 12_integrated_testing/kernel/build.rs
  function main (line 3) | fn main() {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {
  constant QEMU_EXIT_HANDLE (line 37) | const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
  function qemu_exit_failure (line 41) | pub fn qemu_exit_failure() -> ! {
  function qemu_exit_success (line 47) | pub fn qemu_exit_success() -> ! {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/exception.rs
  type SpsrEL1 (line 30) | struct SpsrEL1(InMemoryRegister<u64, SPSR_EL1::Register>);
    method fmt (line 159) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type EsrEL1 (line 31) | struct EsrEL1(InMemoryRegister<u64, ESR_EL1::Register>);
    method exception_class (line 191) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method iss (line 197) | fn iss(&self) -> u64 {
    method fmt (line 205) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type ExceptionContext (line 35) | struct ExceptionContext {
    method exception_class (line 226) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fault_address_valid (line 231) | fn fault_address_valid(&self) -> bool {
    method fmt (line 252) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function default_exception_handler (line 57) | fn default_exception_handler(exc: &ExceptionContext) {
  function current_el0_synchronous (line 70) | extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
  function current_el0_irq (line 75) | extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
  function current_el0_serror (line 80) | extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
  function current_elx_synchronous (line 89) | extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
  function current_elx_irq (line 105) | extern "C" fn current_elx_irq(e: &mut ExceptionContext) {
  function current_elx_serror (line 110) | extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
  function lower_aarch64_synchronous (line 119) | extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext) {
  function lower_aarch64_irq (line 124) | extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext) {
  function lower_aarch64_serror (line 129) | extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext) {
  function lower_aarch32_synchronous (line 138) | extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext) {
  function lower_aarch32_irq (line 143) | extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext) {
  function lower_aarch32_serror (line 148) | extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext) {
  function current_privilege_level (line 283) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
  function handling_init (line 301) | pub unsafe fn handling_init() {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/exception/asynchronous.rs
  type DaifField (line 21) | trait DaifField {
    method daif_field (line 22) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 35) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 41) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 47) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 53) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 25) | struct Debug;
  type SError (line 26) | struct SError;
  type IRQ (line 27) | struct IRQ;
  type FIQ (line 28) | struct FIQ;
  function is_masked (line 58) | fn is_masked<T>() -> bool
  function print_state (line 71) | pub fn print_state() {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 76) | fn set_up_mair(&self) {
    method configure_translation_control (line 89) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 122) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError> {
    method is_enabled (line 162) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 64) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 112) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
  function kernel_tables_in_bss (line 179) | fn kernel_tables_in_bss() {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 110) | struct TableDescriptor {
    method new_zeroed (line 168) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 173) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: usize) -> Se...
  type PageDescriptor (line 119) | struct PageDescriptor {
    method new_zeroed (line 228) | pub const fn new_zeroed() -> Self {
    method from_output_addr (line 233) | pub fn from_output_addr(phys_output_addr: usize, attribute_fields: &At...
  type StartAddr (line 123) | trait StartAddr {
    method phys_start_addr_u64 (line 124) | fn phys_start_addr_u64(&self) -> u64;
    method phys_start_addr_usize (line 125) | fn phys_start_addr_usize(&self) -> usize;
    method phys_start_addr_u64 (line 155) | fn phys_start_addr_u64(&self) -> u64 {
    method phys_start_addr_usize (line 159) | fn phys_start_addr_usize(&self) -> usize {
  constant NUM_LVL2_TABLES (line 128) | const NUM_LVL2_TABLES: usize = bsp::memory::mmu::KernelAddrSpace::SIZE >...
  type FixedSizeTranslationTable (line 138) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  type KernelTranslationTable (line 147) | pub type KernelTranslationTable = FixedSizeTranslationTable<NUM_LVL2_TAB...
  function from (line 191) | fn from(attribute_fields: AttributeFields) -> Self {
  function new (line 255) | pub const fn new() -> Self {
  function populate_tt_entries (line 270) | pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
  function phys_base_address (line 289) | pub fn phys_base_address(&self) -> u64 {
  function size_of_tabledescriptor_equals_64_bit (line 305) | fn size_of_tabledescriptor_equals_64_bit() {
  function size_of_pagedescriptor_equals_64_bit (line 314) | fn size_of_pagedescriptor_equals_64_bit() {

FILE: 12_integrated_testing/kernel/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    method compatible (line 219) | fn compatible(&self) -> &'static str {

FILE: 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 162) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 165) | enum BlockingMode {
  type PL011UartInner (line 170) | struct PL011UartInner {
    method new (line 195) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 220) | pub fn init(&mut self) {
    method write_char (line 257) | fn write_char(&mut self, c: char) {
    method flush (line 270) | fn flush(&self) {
    method read_char_converting (line 278) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 317) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 181) | pub struct PL011Uart {
    constant COMPATIBLE (line 331) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 338) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method compatible (line 351) | fn compatible(&self) -> &'static str {
    method init (line 355) | unsafe fn init(&self) -> Result<(), &'static str> {
    method write_char (line 365) | fn write_char(&self, c: char) {
    method write_fmt (line 369) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 375) | fn flush(&self) {
    method read_char (line 382) | fn read_char(&self) -> char {
    method clear_rx (line 387) | fn clear_rx(&self) {
    method chars_written (line 398) | fn chars_written(&self) -> usize {
    method chars_read (line 402) | fn chars_read(&self) -> usize {

FILE: 12_integrated_testing/kernel/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  function new (line 24) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 33) | type Target = T;
  function deref (line 35) | fn deref(&self) -> &Self::Target {

FILE: 12_integrated_testing/kernel/src/bsp/raspberrypi.rs
  function board_name (line 16) | pub fn board_name() -> &'static str {

FILE: 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 24) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 31) | fn post_init_gpio() -> Result<(), &'static str> {
  function driver_uart (line 36) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 44) | fn driver_gpio() -> Result<(), &'static str> {
  function init (line 60) | pub unsafe fn init() -> Result<(), &'static str> {
  function qemu_bring_up_console (line 76) | pub fn qemu_bring_up_console() {

FILE: 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs
  constant END_INCLUSIVE (line 66) | pub const END_INCLUSIVE:       usize = 0xFFFF_FFFF;
  constant GPIO_OFFSET (line 68) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 69) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 76) | pub const START:            usize =         0x3F00_0000;
  constant GPIO_START (line 77) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 78) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 79) | pub const END_INCLUSIVE:    usize =         0x4000_FFFF;
  constant START (line 87) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 88) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 89) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 90) | pub const END_INCLUSIVE:    usize =         0xFF84_FFFF;
  function code_start (line 104) | fn code_start() -> usize {
  function code_end_exclusive (line 113) | fn code_end_exclusive() -> usize {

FILE: 12_integrated_testing/kernel/src/bsp/raspberrypi/memory/mmu.rs
  type KernelAddrSpace (line 16) | pub type KernelAddrSpace = AddressSpace<{ memory_map::END_INCLUSIVE + 1 }>;
  constant NUM_MEM_RANGES (line 18) | const NUM_MEM_RANGES: usize = 2;
  function code_range_inclusive (line 54) | fn code_range_inclusive() -> RangeInclusive<usize> {
  function mmio_range_inclusive (line 60) | fn mmio_range_inclusive() -> RangeInclusive<usize> {
  function virt_mem_layout (line 69) | pub fn virt_mem_layout() -> &'static KernelVirtualLayout<NUM_MEM_RANGES> {
  function virt_mem_layout_sections_are_64KiB_aligned (line 84) | fn virt_mem_layout_sections_are_64KiB_aligned() {
  function virt_mem_layout_has_no_overlaps (line 99) | fn virt_mem_layout_has_no_overlaps() {

FILE: 12_integrated_testing/kernel/src/common.rs
  function size_human_readable_ceil (line 8) | pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static s...

FILE: 12_integrated_testing/kernel/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 12_integrated_testing/kernel/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 12_integrated_testing/kernel/src/driver.rs
  constant NUM_DRIVERS (line 16) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 18) | struct DriverManagerInner {
    method new (line 72) | pub const fn new() -> Self {
  type DeviceDriver (line 30) | pub trait DeviceDriver {
    method compatible (line 32) | fn compatible(&self) -> &'static str;
    method init (line 39) | unsafe fn init(&self) -> Result<(), &'static str> {
  type DeviceDriverPostInitCallback (line 46) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 50) | pub struct DeviceDriverDescriptor {
    method new (line 86) | pub fn new(
  type DriverManager (line 56) | pub struct DriverManager {
    method new (line 104) | pub const fn new() -> Self {
    method register_driver (line 111) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor) {
    method for_each_descriptor (line 119) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDes...
    method init_drivers (line 134) | pub unsafe fn init_drivers(&self) {
    method enumerate (line 159) | pub fn enumerate(&self) {
  function driver_manager (line 98) | pub fn driver_manager() -> &'static DriverManager {

FILE: 12_integrated_testing/kernel/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {
  function test_runner_executes_in_kernel_mode (line 43) | fn test_runner_executes_in_kernel_mode() {

FILE: 12_integrated_testing/kernel/src/lib.rs
  function version (line 148) | pub fn version() -> &'static str {
  function kernel_init (line 158) | fn kernel_init() -> !;
  function test_runner (line 166) | pub fn test_runner(tests: &[&test_types::UnitTest]) {
  function kernel_init (line 184) | unsafe fn kernel_init() -> ! {

FILE: 12_integrated_testing/kernel/src/main.rs
  function kernel_init (line 28) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 51) | fn kernel_main() -> ! {

FILE: 12_integrated_testing/kernel/src/memory/mmu.rs
  type MMUEnableError (line 38) | pub enum MMUEnableError {
    method fmt (line 124) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MMU (line 48) | pub trait MMU {
    method enable_mmu_and_caching (line 55) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError>;
    method is_enabled (line 58) | fn is_enabled(&self) -> bool;
  type TranslationGranule (line 63) | pub struct TranslationGranule<const GRANULE_SIZE: usize>;
  type AddressSpace (line 66) | pub struct AddressSpace<const AS_SIZE: usize>;
  type Translation (line 71) | pub enum Translation {
  type MemAttributes (line 79) | pub enum MemAttributes {
  type AccessPermissions (line 87) | pub enum AccessPermissions {
  type AttributeFields (line 95) | pub struct AttributeFields {
  type TranslationDescriptor (line 103) | pub struct TranslationDescriptor {
    method fmt (line 175) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type KernelVirtualLayout (line 111) | pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
  constant SIZE (line 134) | pub const SIZE: usize = Self::size_checked();
  constant SHIFT (line 137) | pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 139) | const fn size_checked() -> usize {
  constant SIZE (line 148) | pub const SIZE: usize = Self::size_checked();
  constant SIZE_SHIFT (line 151) | pub const SIZE_SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 153) | const fn size_checked() -> usize {
  method default (line 164) | fn default() -> AttributeFields {
  function new (line 210) | pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL...
  function virt_addr_properties (line 222) | pub fn virt_addr_properties(
  function print_layout (line 245) | pub fn print_layout(&self) {
  function inner (line 254) | pub fn inner(&self) -> &[TranslationDescriptor; NUM_SPECIAL_RANGES] {

FILE: 12_integrated_testing/kernel/src/panic_wait.rs
  function _panic_exit (line 19) | fn _panic_exit() -> ! {
  function panic_prevent_reenter (line 43) | fn panic_prevent_reenter() {
  function panic (line 61) | fn panic(info: &PanicInfo) -> ! {

FILE: 12_integrated_testing/kernel/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 12_integrated_testing/kernel/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type NullLock (line 40) | pub struct NullLock<T>
  function new (line 56) | pub const fn new(data: T) -> Self {
  type Data (line 68) | type Data = T;
  function lock (line 70) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {

FILE: 12_integrated_testing/kernel/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 12_integrated_testing/kernel/tests/00_console_sanity.rb
  class TxRxHandshakeTest (line 10) | class TxRxHandshakeTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, qemu_in)
  class TxStatisticsTest (line 22) | class TxStatisticsTest < SubtestBase
    method name (line 23) | def name
    method run (line 27) | def run(qemu_out, _qemu_in)
  class RxStatisticsTest (line 33) | class RxStatisticsTest < SubtestBase
    method name (line 34) | def name
    method run (line 38) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 46) | def subtest_collection

FILE: 12_integrated_testing/kernel/tests/00_console_sanity.rs
  function kernel_init (line 17) | unsafe fn kernel_init() -> ! {

FILE: 12_integrated_testing/kernel/tests/01_timer_sanity.rs
  function kernel_init (line 18) | unsafe fn kernel_init() -> ! {
  function timer_is_counting (line 31) | fn timer_is_counting() {
  function timer_resolution_is_sufficient (line 37) | fn timer_resolution_is_sufficient() {
  function spin_accuracy_check_1_second (line 44) | fn spin_accuracy_check_1_second() {

FILE: 12_integrated_testing/kernel/tests/02_exception_sync_page_fault.rs
  function kernel_init (line 23) | unsafe fn kernel_init() -> ! {

FILE: 12_integrated_testing/kernel/tests/03_exception_restore_sanity.rb
  class ExceptionRestoreTest (line 10) | class ExceptionRestoreTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 23) | def subtest_collection

FILE: 12_integrated_testing/kernel/tests/03_exception_restore_sanity.rs
  function nested_system_call (line 18) | fn nested_system_call() {
  function kernel_init (line 32) | unsafe fn kernel_init() -> ! {

FILE: 12_integrated_testing/kernel/tests/panic_exit_success/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 12_integrated_testing/kernel/tests/panic_wait_forever/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 12_integrated_testing/libraries/test-macros/src/lib.rs
  function kernel_test (line 11) | pub fn kernel_test(_attr: TokenStream, input: TokenStream) -> TokenStream {

FILE: 12_integrated_testing/libraries/test-types/src/lib.rs
  type UnitTest (line 10) | pub struct UnitTest {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/build.rs
  function main (line 3) | fn main() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {
  constant QEMU_EXIT_HANDLE (line 37) | const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
  function qemu_exit_failure (line 41) | pub fn qemu_exit_failure() -> ! {
  function qemu_exit_success (line 47) | pub fn qemu_exit_success() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/cpu/smp.rs
  function core_id (line 23) | pub fn core_id<T>() -> T

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/exception.rs
  type SpsrEL1 (line 31) | struct SpsrEL1(InMemoryRegister<u64, SPSR_EL1::Register>);
    method fmt (line 161) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type EsrEL1 (line 32) | struct EsrEL1(InMemoryRegister<u64, ESR_EL1::Register>);
    method exception_class (line 193) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method iss (line 199) | fn iss(&self) -> u64 {
    method fmt (line 207) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type ExceptionContext (line 36) | struct ExceptionContext {
    method exception_class (line 228) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fault_address_valid (line 233) | fn fault_address_valid(&self) -> bool {
    method fmt (line 254) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function default_exception_handler (line 58) | fn default_exception_handler(exc: &ExceptionContext) {
  function current_el0_synchronous (line 71) | extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
  function current_el0_irq (line 76) | extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
  function current_el0_serror (line 81) | extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
  function current_elx_synchronous (line 90) | extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
  function current_elx_irq (line 106) | extern "C" fn current_elx_irq(_e: &mut ExceptionContext) {
  function current_elx_serror (line 112) | extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
  function lower_aarch64_synchronous (line 121) | extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext) {
  function lower_aarch64_irq (line 126) | extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext) {
  function lower_aarch64_serror (line 131) | extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext) {
  function lower_aarch32_synchronous (line 140) | extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext) {
  function lower_aarch32_irq (line 145) | extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext) {
  function lower_aarch32_serror (line 150) | extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext) {
  function current_privilege_level (line 285) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
  function handling_init (line 303) | pub unsafe fn handling_init() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/exception/asynchronous.rs
  constant IRQ (line 23) | pub const IRQ: u8 = 0b0010;
  type DaifField (line 26) | trait DaifField {
    method daif_field (line 27) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 40) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 46) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 52) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 58) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 30) | struct Debug;
  type SError (line 31) | struct SError;
  type IRQ (line 32) | struct IRQ;
  type FIQ (line 33) | struct FIQ;
  function is_masked (line 63) | fn is_masked<T>() -> bool
  function is_local_irq_masked (line 75) | pub fn is_local_irq_masked() -> bool {
  function local_irq_unmask (line 87) | pub fn local_irq_unmask() {
  function local_irq_mask (line 99) | pub fn local_irq_mask() {
  function local_irq_mask_save (line 111) | pub fn local_irq_mask_save() -> u64 {
  function local_irq_restore (line 124) | pub fn local_irq_restore(saved: u64) {
  function print_state (line 130) | pub fn print_state() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 76) | fn set_up_mair(&self) {
    method configure_translation_control (line 89) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 122) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError> {
    method is_enabled (line 162) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 64) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 112) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {
  function kernel_tables_in_bss (line 179) | fn kernel_tables_in_bss() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 110) | struct TableDescriptor {
    method new_zeroed (line 168) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 173) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: usize) -> Se...
  type PageDescriptor (line 119) | struct PageDescriptor {
    method new_zeroed (line 228) | pub const fn new_zeroed() -> Self {
    method from_output_addr (line 233) | pub fn from_output_addr(phys_output_addr: usize, attribute_fields: &At...
  type StartAddr (line 123) | trait StartAddr {
    method phys_start_addr_u64 (line 124) | fn phys_start_addr_u64(&self) -> u64;
    method phys_start_addr_usize (line 125) | fn phys_start_addr_usize(&self) -> usize;
    method phys_start_addr_u64 (line 155) | fn phys_start_addr_u64(&self) -> u64 {
    method phys_start_addr_usize (line 159) | fn phys_start_addr_usize(&self) -> usize {
  constant NUM_LVL2_TABLES (line 128) | const NUM_LVL2_TABLES: usize = bsp::memory::mmu::KernelAddrSpace::SIZE >...
  type FixedSizeTranslationTable (line 138) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  type KernelTranslationTable (line 147) | pub type KernelTranslationTable = FixedSizeTranslationTable<NUM_LVL2_TAB...
  function from (line 191) | fn from(attribute_fields: AttributeFields) -> Self {
  function new (line 255) | pub const fn new() -> Self {
  function populate_tt_entries (line 270) | pub unsafe fn populate_tt_entries(&mut self) -> Result<(), &'static str> {
  function phys_base_address (line 289) | pub fn phys_base_address(&self) -> u64 {
  function size_of_tabledescriptor_equals_64_bit (line 305) | fn size_of_tabledescriptor_equals_64_bit() {
  function size_of_pagedescriptor_equals_64_bit (line 314) | fn size_of_pagedescriptor_equals_64_bit() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs
  type HandlerTable (line 92) | type HandlerTable = [Option<exception::asynchronous::IRQHandlerDescripto...
  type IRQNumber (line 100) | pub type IRQNumber = BoundedUsize<{ GICv2::MAX_IRQ_NUMBER }>;
  type GICv2 (line 103) | pub struct GICv2 {
    constant MAX_IRQ_NUMBER (line 119) | const MAX_IRQ_NUMBER: usize = 300;
    constant COMPATIBLE (line 121) | pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Con...
    method new (line 128) | pub const unsafe fn new(gicd_mmio_start_addr: usize, gicc_mmio_start_a...
    type IRQNumberType (line 143) | type IRQNumberType = IRQNumber;
    method compatible (line 145) | fn compatible(&self) -> &'static str {
    method init (line 149) | unsafe fn init(&self) -> Result<(), &'static str> {
    type IRQNumberType (line 162) | type IRQNumberType = IRQNumber;
    method register_handler (line 164) | fn register_handler(
    method enable (line 181) | fn enable(&self, irq_number: &Self::IRQNumberType) {
    method handle_pending_irqs (line 185) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 213) | fn print_handler(&self) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2/gicc.rs
  type Registers (line 55) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GICC (line 62) | pub struct GICC {
    method new (line 76) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method priority_accept_all (line 93) | pub fn priority_accept_all(&self) {
    method enable (line 103) | pub fn enable(&self) {
    method pending_irq_number (line 116) | pub fn pending_irq_number<'irq_context>(
    method mark_comleted (line 134) | pub fn mark_comleted<'irq_context>(

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs
  type SharedRegisters (line 71) | type SharedRegisters = MMIODerefWrapper<SharedRegisterBlock>;
    method num_irqs (line 96) | fn num_irqs(&mut self) -> usize {
    method implemented_itargets_slice (line 105) | fn implemented_itargets_slice(&mut self) -> &[ReadWrite<u32, ITARGETSR...
  type BankedRegisters (line 74) | type BankedRegisters = MMIODerefWrapper<BankedRegisterBlock>;
  type GICD (line 81) | pub struct GICD {
    method new (line 131) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method local_gic_target_mask (line 144) | fn local_gic_target_mask(&self) -> u32 {
    method boot_core_init (line 149) | pub fn boot_core_init(&self) {
    method enable (line 173) | pub fn enable(&self, irq_num: &super::IRQNumber) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 109) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 111) | struct GPIOInner {
    method new (line 134) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method disable_pud_14_15_bcm2837 (line 142) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 163) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 174) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 120) | pub struct GPIO {
    constant COMPATIBLE (line 194) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 201) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method map_pl011_uart (line 208) | pub fn map_pl011_uart(&self) {
    type IRQNumberType (line 219) | type IRQNumberType = IRQNumber;
    method compatible (line 221) | fn compatible(&self) -> &'static str {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs
  type PendingIRQs (line 21) | struct PendingIRQs {
    method new (line 50) | pub fn new(bitmask: u64) -> Self {
  type LocalIRQ (line 29) | pub type LocalIRQ = BoundedUsize<{ InterruptController::MAX_LOCAL_IRQ_NU...
  type PeripheralIRQ (line 30) | pub type PeripheralIRQ = BoundedUsize<{ InterruptController::MAX_PERIPHE...
  type IRQNumber (line 35) | pub enum IRQNumber {
    method fmt (line 74) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type InterruptController (line 41) | pub struct InterruptController {
    constant MAX_LOCAL_IRQ_NUMBER (line 84) | const MAX_LOCAL_IRQ_NUMBER: usize = 3;
    constant MAX_PERIPHERAL_IRQ_NUMBER (line 85) | const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63;
    constant COMPATIBLE (line 87) | pub const COMPATIBLE: &'static str = "BCM Interrupt Controller";
    method new (line 94) | pub const unsafe fn new(periph_mmio_start_addr: usize) -> Self {
    type IRQNumberType (line 106) | type IRQNumberType = IRQNumber;
    method compatible (line 108) | fn compatible(&self) -> &'static str {
    type IRQNumberType (line 114) | type IRQNumberType = IRQNumber;
    method register_handler (line 116) | fn register_handler(
    method enable (line 134) | fn enable(&self, irq: &Self::IRQNumberType) {
    method handle_pending_irqs (line 141) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 149) | fn print_handler(&self) {
  type Item (line 56) | type Item = usize;
  method next (line 58) | fn next(&mut self) -> Option<Self::Item> {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs
  type WriteOnlyRegisters (line 48) | type WriteOnlyRegisters = MMIODerefWrapper<WORegisterBlock>;
  type ReadOnlyRegisters (line 51) | type ReadOnlyRegisters = MMIODerefWrapper<RORegisterBlock>;
  type HandlerTable (line 53) | type HandlerTable = [Option<exception::asynchronous::IRQHandlerDescripto...
  type PeripheralIC (line 61) | pub struct PeripheralIC {
    method new (line 82) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method pending_irqs (line 91) | fn pending_irqs(&self) -> PendingIRQs {
    type IRQNumberType (line 105) | type IRQNumberType = PeripheralIRQ;
    method register_handler (line 107) | fn register_handler(
    method enable (line 124) | fn enable(&self, irq: &Self::IRQNumberType) {
    method handle_pending_irqs (line 140) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 157) | fn print_handler(&self) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 214) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 217) | enum BlockingMode {
  type PL011UartInner (line 222) | struct PL011UartInner {
    method new (line 247) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    method init (line 272) | pub fn init(&mut self) {
    method write_char (line 317) | fn write_char(&mut self, c: char) {
    method flush (line 330) | fn flush(&self) {
    method read_char_converting (line 338) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 377) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 233) | pub struct PL011Uart {
    constant COMPATIBLE (line 391) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 398) | pub const unsafe fn new(mmio_start_addr: usize) -> Self {
    type IRQNumberType (line 411) | type IRQNumberType = IRQNumber;
    method compatible (line 413) | fn compatible(&self) -> &'static str {
    method init (line 417) | unsafe fn init(&self) -> Result<(), &'static str> {
    method register_and_enable_irq_handler (line 423) | fn register_and_enable_irq_handler(
    method write_char (line 441) | fn write_char(&self, c: char) {
    method write_fmt (line 445) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 451) | fn flush(&self) {
    method read_char (line 458) | fn read_char(&self) -> char {
    method clear_rx (line 463) | fn clear_rx(&self) {
    method chars_written (line 474) | fn chars_written(&self) -> usize {
    method chars_read (line 478) | fn chars_read(&self) -> usize {
    method handle (line 486) | fn handle(&self) -> Result<(), &'static str> {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 13) | pub struct MMIODerefWrapper<T> {
  type BoundedUsize (line 20) | pub struct BoundedUsize<const MAX_INCLUSIVE: usize>(usize);
  function new (line 28) | pub const unsafe fn new(start_addr: usize) -> Self {
  type Target (line 37) | type Target = T;
  function deref (line 39) | fn deref(&self) -> &Self::Target {
  constant MAX_INCLUSIVE (line 45) | pub const MAX_INCLUSIVE: usize = MAX_INCLUSIVE;
  function new (line 48) | pub const fn new(number: usize) -> Self {
  function get (line 55) | pub const fn get(self) -> usize {
  function fmt (line 61) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi.rs
  function board_name (line 17) | pub fn board_name() -> &'static str {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/driver.rs
  function post_init_uart (line 36) | fn post_init_uart() -> Result<(), &'static str> {
  function post_init_gpio (line 43) | fn post_init_gpio() -> Result<(), &'static str> {
  function post_init_interrupt_controller (line 49) | fn post_init_interrupt_controller() -> Result<(), &'static str> {
  function driver_uart (line 55) | fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 66) | fn driver_gpio() -> Result<(), &'static str> {
  function driver_interrupt_controller (line 74) | fn driver_interrupt_controller() -> Result<(), &'static str> {
  function init (line 94) | pub unsafe fn init() -> Result<(), &'static str> {
  function qemu_bring_up_console (line 111) | pub fn qemu_bring_up_console() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/exception/asynchronous.rs
  constant PL011_UART (line 20) | pub const PL011_UART: IRQNumber = IRQNumber::Peripheral(PeripheralIRQ::n...
  constant PL011_UART (line 27) | pub const PL011_UART: IRQNumber = IRQNumber::new(153);

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory.rs
  constant END_INCLUSIVE (line 66) | pub const END_INCLUSIVE:       usize = 0xFFFF_FFFF;
  constant GPIO_OFFSET (line 68) | pub const GPIO_OFFSET:         usize = 0x0020_0000;
  constant UART_OFFSET (line 69) | pub const UART_OFFSET:         usize = 0x0020_1000;
  constant START (line 76) | pub const START:               usize =         0x3F00_0000;
  constant PERIPHERAL_IC_START (line 77) | pub const PERIPHERAL_IC_START: usize = START + 0x0000_B200;
  constant GPIO_START (line 78) | pub const GPIO_START:          usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 79) | pub const PL011_UART_START:    usize = START + UART_OFFSET;
  constant END_INCLUSIVE (line 80) | pub const END_INCLUSIVE:       usize =         0x4000_FFFF;
  constant START (line 88) | pub const START:            usize =         0xFE00_0000;
  constant GPIO_START (line 89) | pub const GPIO_START:       usize = START + GPIO_OFFSET;
  constant PL011_UART_START (line 90) | pub const PL011_UART_START: usize = START + UART_OFFSET;
  constant GICD_START (line 91) | pub const GICD_START:       usize =         0xFF84_1000;
  constant GICC_START (line 92) | pub const GICC_START:       usize =         0xFF84_2000;
  constant END_INCLUSIVE (line 93) | pub const END_INCLUSIVE:    usize =         0xFF84_FFFF;
  function code_start (line 107) | fn code_start() -> usize {
  function code_end_exclusive (line 116) | fn code_end_exclusive() -> usize {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory/mmu.rs
  type KernelAddrSpace (line 16) | pub type KernelAddrSpace = AddressSpace<{ memory_map::END_INCLUSIVE + 1 }>;
  constant NUM_MEM_RANGES (line 18) | const NUM_MEM_RANGES: usize = 2;
  function code_range_inclusive (line 54) | fn code_range_inclusive() -> RangeInclusive<usize> {
  function mmio_range_inclusive (line 60) | fn mmio_range_inclusive() -> RangeInclusive<usize> {
  function virt_mem_layout (line 69) | pub fn virt_mem_layout() -> &'static KernelVirtualLayout<NUM_MEM_RANGES> {
  function virt_mem_layout_sections_are_64KiB_aligned (line 84) | fn virt_mem_layout_sections_are_64KiB_aligned() {
  function virt_mem_layout_has_no_overlaps (line 99) | fn virt_mem_layout_has_no_overlaps() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/common.rs
  function size_human_readable_ceil (line 8) | pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static s...

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/driver.rs
  constant NUM_DRIVERS (line 17) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 19) | struct DriverManagerInner<T>
  type DeviceDriver (line 34) | pub trait DeviceDriver {
    method compatible (line 39) | fn compatible(&self) -> &'static str;
    method init (line 46) | unsafe fn init(&self) -> Result<(), &'static str> {
    method register_and_enable_irq_handler (line 54) | fn register_and_enable_irq_handler(
  type DeviceDriverPostInitCallback (line 68) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 72) | pub struct DeviceDriverDescriptor<T>
  type DriverManager (line 82) | pub struct DriverManager<T>
  function new (line 104) | pub const fn new() -> Self {
  function new (line 118) | pub fn new(
  function driver_manager (line 132) | pub fn driver_manager() -> &'static DriverManager<exception::asynchronou...
  function new (line 141) | pub const fn new() -> Self {
  function register_driver (line 148) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor<T>) {
  function for_each_descriptor (line 156) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDescr...
  function init_drivers_and_irqs (line 171) | pub unsafe fn init_drivers_and_irqs(&self) {
  function enumerate (line 213) | pub fn enumerate(&self) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {
  function test_runner_executes_in_kernel_mode (line 43) | fn test_runner_executes_in_kernel_mode() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs
  type IRQNumber (line 28) | pub type IRQNumber = bsp::exception::asynchronous::IRQNumber;
  type IRQHandlerDescriptor (line 32) | pub struct IRQHandlerDescriptor<T>
  type IRQContext (line 54) | pub struct IRQContext<'irq_context> {
  type IRQHandler (line 62) | pub trait IRQHandler {
    method handle (line 64) | fn handle(&self) -> Result<(), &'static str>;
  type IRQManager (line 71) | pub trait IRQManager {
    method register_handler (line 76) | fn register_handler(
    method enable (line 82) | fn enable(&self, irq_number: &Self::IRQNumberType);
    method handle_pending_irqs (line 92) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 98) | fn print_handler(&self) {}
  function new (line 120) | pub const fn new(
  function number (line 133) | pub const fn number(&self) -> T {
  function name (line 138) | pub const fn name(&self) -> &'static str {
  function handler (line 143) | pub const fn handler(&self) -> &'static (dyn interface::IRQHandler + Syn...
  function new (line 160) | pub unsafe fn new() -> Self {
  function exec_with_irq_masked (line 170) | pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
  function register_irq_manager (line 179) | pub fn register_irq_manager(
  function irq_manager (line 188) | pub fn irq_manager() -> &'static dyn interface::IRQManager<IRQNumberType...

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous/null_irq_manager.rs
  type NullIRQManager (line 13) | pub struct NullIRQManager;
    type IRQNumberType (line 26) | type IRQNumberType = super::IRQNumber;
    method register_handler (line 28) | fn register_handler(
    method enable (line 35) | fn enable(&self, _irq_number: &Self::IRQNumberType) {
    method handle_pending_irqs (line 39) | fn handle_pending_irqs<'irq_context>(&'irq_context self, _ic: &IRQCont...

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs
  function version (line 149) | pub fn version() -> &'static str {
  function kernel_init (line 159) | fn kernel_init() -> !;
  function test_runner (line 167) | pub fn test_runner(tests: &[&test_types::UnitTest]) {
  function kernel_init (line 185) | unsafe fn kernel_init() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/main.rs
  function kernel_init (line 28) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 56) | fn kernel_main() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/memory/mmu.rs
  type MMUEnableError (line 38) | pub enum MMUEnableError {
    method fmt (line 124) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MMU (line 48) | pub trait MMU {
    method enable_mmu_and_caching (line 55) | unsafe fn enable_mmu_and_caching(&self) -> Result<(), MMUEnableError>;
    method is_enabled (line 58) | fn is_enabled(&self) -> bool;
  type TranslationGranule (line 63) | pub struct TranslationGranule<const GRANULE_SIZE: usize>;
  type AddressSpace (line 66) | pub struct AddressSpace<const AS_SIZE: usize>;
  type Translation (line 71) | pub enum Translation {
  type MemAttributes (line 79) | pub enum MemAttributes {
  type AccessPermissions (line 87) | pub enum AccessPermissions {
  type AttributeFields (line 95) | pub struct AttributeFields {
  type TranslationDescriptor (line 103) | pub struct TranslationDescriptor {
    method fmt (line 175) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type KernelVirtualLayout (line 111) | pub struct KernelVirtualLayout<const NUM_SPECIAL_RANGES: usize> {
  constant SIZE (line 134) | pub const SIZE: usize = Self::size_checked();
  constant SHIFT (line 137) | pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 139) | const fn size_checked() -> usize {
  constant SIZE (line 148) | pub const SIZE: usize = Self::size_checked();
  constant SIZE_SHIFT (line 151) | pub const SIZE_SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 153) | const fn size_checked() -> usize {
  method default (line 164) | fn default() -> AttributeFields {
  function new (line 210) | pub const fn new(max: usize, layout: [TranslationDescriptor; NUM_SPECIAL...
  function virt_addr_properties (line 222) | pub fn virt_addr_properties(
  function print_layout (line 245) | pub fn print_layout(&self) {
  function inner (line 254) | pub fn inner(&self) -> &[TranslationDescriptor; NUM_SPECIAL_RANGES] {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/panic_wait.rs
  function _panic_exit (line 19) | fn _panic_exit() -> ! {
  function panic_prevent_reenter (line 43) | fn panic_prevent_reenter() {
  function panic (line 61) | fn panic(info: &PanicInfo) -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/state.rs
  type State (line 15) | enum State {
  type StateManager (line 33) | pub struct StateManager(AtomicU8);
    constant INIT (line 51) | const INIT: u8 = 0;
    constant SINGLE_CORE_MAIN (line 52) | const SINGLE_CORE_MAIN: u8 = 1;
    constant MULTI_CORE_MAIN (line 53) | const MULTI_CORE_MAIN: u8 = 2;
    method new (line 56) | pub const fn new() -> Self {
    method state (line 61) | fn state(&self) -> State {
    method is_init (line 73) | pub fn is_init(&self) -> bool {
    method transition_to_single_core_main (line 78) | pub fn transition_to_single_core_main(&self) {
  function state_manager (line 46) | pub fn state_manager() -> &'static StateManager {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type ReadWriteEx (line 36) | pub trait ReadWriteEx {
    method write (line 41) | fn write<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
    method read (line 44) | fn read<'a, R>(&'a self, f: impl FnOnce(&'a Self::Data) -> R) -> R;
  type IRQSafeNullLock (line 55) | pub struct IRQSafeNullLock<T>
  type InitStateLock (line 65) | pub struct InitStateLock<T>
  function new (line 81) | pub const fn new(data: T) -> Self {
  function new (line 93) | pub const fn new(data: T) -> Self {
  type Data (line 106) | type Data = T;
  function lock (line 108) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
  type Data (line 119) | type Data = T;
  function write (line 121) | fn write<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
  function read (line 136) | fn read<'a, R>(&'a self, f: impl FnOnce(&'a Self::Data) -> R) -> R {
  function init_state_lock_is_transparent (line 154) | fn init_state_lock_is_transparent() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/00_console_sanity.rb
  class TxRxHandshakeTest (line 10) | class TxRxHandshakeTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, qemu_in)
  class TxStatisticsTest (line 22) | class TxStatisticsTest < SubtestBase
    method name (line 23) | def name
    method run (line 27) | def run(qemu_out, _qemu_in)
  class RxStatisticsTest (line 33) | class RxStatisticsTest < SubtestBase
    method name (line 34) | def name
    method run (line 38) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 46) | def subtest_collection

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/00_console_sanity.rs
  function kernel_init (line 17) | unsafe fn kernel_init() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/01_timer_sanity.rs
  function kernel_init (line 18) | unsafe fn kernel_init() -> ! {
  function timer_is_counting (line 31) | fn timer_is_counting() {
  function timer_resolution_is_sufficient (line 37) | fn timer_resolution_is_sufficient() {
  function spin_accuracy_check_1_second (line 44) | fn spin_accuracy_check_1_second() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/02_exception_sync_page_fault.rs
  function kernel_init (line 23) | unsafe fn kernel_init() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/03_exception_restore_sanity.rb
  class ExceptionRestoreTest (line 10) | class ExceptionRestoreTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 23) | def subtest_collection

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/03_exception_restore_sanity.rs
  function nested_system_call (line 18) | fn nested_system_call() {
  function kernel_init (line 32) | unsafe fn kernel_init() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs
  function kernel_init (line 17) | unsafe fn kernel_init() -> ! {
  function local_irq_mask_works (line 30) | fn local_irq_mask_works() {
  function local_irq_unmask_works (line 43) | fn local_irq_unmask_works() {
  function local_irq_mask_save_works (line 54) | fn local_irq_mask_save_works() {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/panic_exit_success/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/kernel/tests/panic_wait_forever/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 13_exceptions_part2_peripheral_IRQs/libraries/test-macros/src/lib.rs
  function kernel_test (line 11) | pub fn kernel_test(_attr: TokenStream, input: TokenStream) -> TokenStream {

FILE: 13_exceptions_part2_peripheral_IRQs/libraries/test-types/src/lib.rs
  type UnitTest (line 10) | pub struct UnitTest {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/build.rs
  function main (line 3) | fn main() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {
  constant QEMU_EXIT_HANDLE (line 37) | const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
  function qemu_exit_failure (line 41) | pub fn qemu_exit_failure() -> ! {
  function qemu_exit_success (line 47) | pub fn qemu_exit_success() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 36) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 78) | pub unsafe extern "C" fn _start_rust(phys_boot_core_stack_end_exclusive_...

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/cpu/smp.rs
  function core_id (line 23) | pub fn core_id<T>() -> T

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/exception.rs
  type SpsrEL1 (line 31) | struct SpsrEL1(InMemoryRegister<u64, SPSR_EL1::Register>);
    method fmt (line 161) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type EsrEL1 (line 32) | struct EsrEL1(InMemoryRegister<u64, ESR_EL1::Register>);
    method exception_class (line 193) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method iss (line 199) | fn iss(&self) -> u64 {
    method fmt (line 207) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type ExceptionContext (line 36) | struct ExceptionContext {
    method exception_class (line 228) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fault_address_valid (line 233) | fn fault_address_valid(&self) -> bool {
    method fmt (line 254) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function default_exception_handler (line 58) | fn default_exception_handler(exc: &ExceptionContext) {
  function current_el0_synchronous (line 71) | extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
  function current_el0_irq (line 76) | extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
  function current_el0_serror (line 81) | extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
  function current_elx_synchronous (line 90) | extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
  function current_elx_irq (line 106) | extern "C" fn current_elx_irq(_e: &mut ExceptionContext) {
  function current_elx_serror (line 112) | extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
  function lower_aarch64_synchronous (line 121) | extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext) {
  function lower_aarch64_irq (line 126) | extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext) {
  function lower_aarch64_serror (line 131) | extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext) {
  function lower_aarch32_synchronous (line 140) | extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext) {
  function lower_aarch32_irq (line 145) | extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext) {
  function lower_aarch32_serror (line 150) | extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext) {
  function current_privilege_level (line 285) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
  function handling_init (line 303) | pub unsafe fn handling_init() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/exception/asynchronous.rs
  constant IRQ (line 23) | pub const IRQ: u8 = 0b0010;
  type DaifField (line 26) | trait DaifField {
    method daif_field (line 27) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 40) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 46) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 52) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 58) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 30) | struct Debug;
  type SError (line 31) | struct SError;
  type IRQ (line 32) | struct IRQ;
  type FIQ (line 33) | struct FIQ;
  function is_masked (line 63) | fn is_masked<T>() -> bool
  function is_local_irq_masked (line 75) | pub fn is_local_irq_masked() -> bool {
  function local_irq_unmask (line 87) | pub fn local_irq_unmask() {
  function local_irq_mask (line 99) | pub fn local_irq_mask() {
  function local_irq_mask_save (line 111) | pub fn local_irq_mask_save() -> u64 {
  function local_irq_restore (line 124) | pub fn local_irq_restore(saved: u64) {
  function print_state (line 130) | pub fn print_state() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 69) | fn set_up_mair(&self) {
    method configure_translation_control (line 82) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 115) | unsafe fn enable_mmu_and_caching(
    method is_enabled (line 153) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 57) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 105) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 114) | struct TableDescriptor {
    method new_zeroed (line 165) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 170) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: Address<Phys...
  type PageDescriptor (line 123) | struct PageDescriptor {
    method new_zeroed (line 225) | pub const fn new_zeroed() -> Self {
    method from_output_page_addr (line 230) | pub fn from_output_page_addr(
    method is_valid (line 249) | fn is_valid(&self) -> bool {
  type StartAddr (line 127) | trait StartAddr {
    method phys_start_addr (line 128) | fn phys_start_addr(&self) -> Address<Physical>;
    method phys_start_addr (line 156) | fn phys_start_addr(&self) -> Address<Physical> {
  type FixedSizeTranslationTable (line 139) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  function from (line 188) | fn from(attribute_fields: AttributeFields) -> Self {
  type TableStartFromBottom (line 264) | type TableStartFromBottom = FixedSizeTranslationTable<{ Self::SIZE >> Gr...
  function new (line 270) | pub const fn new() -> Self {
  function lvl2_lvl3_index_from_page_addr (line 285) | fn lvl2_lvl3_index_from_page_addr(
  function set_page_descriptor_from_page_addr (line 304) | fn set_page_descriptor_from_page_addr(
  function init (line 328) | fn init(&mut self) {
  function phys_base_address (line 344) | fn phys_base_address(&self) -> Address<Physical> {
  function map_at (line 348) | unsafe fn map_at(
  type MinSizeTranslationTable (line 382) | pub type MinSizeTranslationTable = FixedSizeTranslationTable<1>;
  function size_of_tabledescriptor_equals_64_bit (line 391) | fn size_of_tabledescriptor_equals_64_bit() {
  function size_of_pagedescriptor_equals_64_bit (line 400) | fn size_of_pagedescriptor_equals_64_bit() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2.rs
  type HandlerTable (line 94) | type HandlerTable = [Option<exception::asynchronous::IRQHandlerDescripto...
  type IRQNumber (line 102) | pub type IRQNumber = BoundedUsize<{ GICv2::MAX_IRQ_NUMBER }>;
  type GICv2 (line 105) | pub struct GICv2 {
    constant MAX_IRQ_NUMBER (line 121) | const MAX_IRQ_NUMBER: usize = 300;
    constant COMPATIBLE (line 123) | pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Con...
    method new (line 130) | pub const unsafe fn new(
    type IRQNumberType (line 148) | type IRQNumberType = IRQNumber;
    method compatible (line 150) | fn compatible(&self) -> &'static str {
    method init (line 154) | unsafe fn init(&self) -> Result<(), &'static str> {
    type IRQNumberType (line 167) | type IRQNumberType = IRQNumber;
    method register_handler (line 169) | fn register_handler(
    method enable (line 186) | fn enable(&self, irq_number: &Self::IRQNumberType) {
    method handle_pending_irqs (line 190) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 218) | fn print_handler(&self) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2/gicc.rs
  type Registers (line 59) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GICC (line 66) | pub struct GICC {
    method new (line 80) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method priority_accept_all (line 97) | pub fn priority_accept_all(&self) {
    method enable (line 107) | pub fn enable(&self) {
    method pending_irq_number (line 120) | pub fn pending_irq_number<'irq_context>(
    method mark_comleted (line 138) | pub fn mark_comleted<'irq_context>(

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs
  type SharedRegisters (line 73) | type SharedRegisters = MMIODerefWrapper<SharedRegisterBlock>;
    method num_irqs (line 98) | fn num_irqs(&mut self) -> usize {
    method implemented_itargets_slice (line 107) | fn implemented_itargets_slice(&mut self) -> &[ReadWrite<u32, ITARGETSR...
  type BankedRegisters (line 76) | type BankedRegisters = MMIODerefWrapper<BankedRegisterBlock>;
  type GICD (line 83) | pub struct GICD {
    method new (line 133) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method local_gic_target_mask (line 146) | fn local_gic_target_mask(&self) -> u32 {
    method boot_core_init (line 151) | pub fn boot_core_init(&self) {
    method enable (line 175) | pub fn enable(&self, irq_num: &super::IRQNumber) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 113) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 115) | struct GPIOInner {
    method new (line 138) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method disable_pud_14_15_bcm2837 (line 146) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 167) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 178) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 124) | pub struct GPIO {
    constant COMPATIBLE (line 198) | pub const COMPATIBLE: &'static str = "BCM GPIO";
    method new (line 205) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method map_pl011_uart (line 212) | pub fn map_pl011_uart(&self) {
    type IRQNumberType (line 223) | type IRQNumberType = IRQNumber;
    method compatible (line 225) | fn compatible(&self) -> &'static str {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs
  type PendingIRQs (line 22) | struct PendingIRQs {
    method new (line 51) | pub fn new(bitmask: u64) -> Self {
  type LocalIRQ (line 30) | pub type LocalIRQ = BoundedUsize<{ InterruptController::MAX_LOCAL_IRQ_NU...
  type PeripheralIRQ (line 31) | pub type PeripheralIRQ = BoundedUsize<{ InterruptController::MAX_PERIPHE...
  type IRQNumber (line 36) | pub enum IRQNumber {
    method fmt (line 75) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type InterruptController (line 42) | pub struct InterruptController {
    constant MAX_LOCAL_IRQ_NUMBER (line 85) | const MAX_LOCAL_IRQ_NUMBER: usize = 3;
    constant MAX_PERIPHERAL_IRQ_NUMBER (line 86) | const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63;
    constant COMPATIBLE (line 88) | pub const COMPATIBLE: &'static str = "BCM Interrupt Controller";
    method new (line 95) | pub const unsafe fn new(periph_mmio_start_addr: Address<Virtual>) -> S...
    type IRQNumberType (line 107) | type IRQNumberType = IRQNumber;
    method compatible (line 109) | fn compatible(&self) -> &'static str {
    type IRQNumberType (line 115) | type IRQNumberType = IRQNumber;
    method register_handler (line 117) | fn register_handler(
    method enable (line 135) | fn enable(&self, irq: &Self::IRQNumberType) {
    method handle_pending_irqs (line 142) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 150) | fn print_handler(&self) {
  type Item (line 57) | type Item = usize;
  method next (line 59) | fn next(&mut self) -> Option<Self::Item> {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs
  type WriteOnlyRegisters (line 50) | type WriteOnlyRegisters = MMIODerefWrapper<WORegisterBlock>;
  type ReadOnlyRegisters (line 53) | type ReadOnlyRegisters = MMIODerefWrapper<RORegisterBlock>;
  type HandlerTable (line 55) | type HandlerTable = [Option<exception::asynchronous::IRQHandlerDescripto...
  type PeripheralIC (line 63) | pub struct PeripheralIC {
    method new (line 84) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method pending_irqs (line 93) | fn pending_irqs(&self) -> PendingIRQs {
    type IRQNumberType (line 107) | type IRQNumberType = PeripheralIRQ;
    method register_handler (line 109) | fn register_handler(
    method enable (line 126) | fn enable(&self, irq: &Self::IRQNumberType) {
    method handle_pending_irqs (line 142) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 159) | fn print_handler(&self) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
  type Registers (line 215) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type BlockingMode (line 218) | enum BlockingMode {
  type PL011UartInner (line 223) | struct PL011UartInner {
    method new (line 248) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method init (line 273) | pub fn init(&mut self) {
    method write_char (line 318) | fn write_char(&mut self, c: char) {
    method flush (line 331) | fn flush(&self) {
    method read_char_converting (line 339) | fn read_char_converting(&mut self, blocking_mode: BlockingMode) -> Opt...
    method write_str (line 378) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type PL011Uart (line 234) | pub struct PL011Uart {
    constant COMPATIBLE (line 392) | pub const COMPATIBLE: &'static str = "BCM PL011 UART";
    method new (line 399) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    type IRQNumberType (line 412) | type IRQNumberType = IRQNumber;
    method compatible (line 414) | fn compatible(&self) -> &'static str {
    method init (line 418) | unsafe fn init(&self) -> Result<(), &'static str> {
    method register_and_enable_irq_handler (line 424) | fn register_and_enable_irq_handler(
    method write_char (line 442) | fn write_char(&self, c: char) {
    method write_fmt (line 446) | fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result {
    method flush (line 452) | fn flush(&self) {
    method read_char (line 459) | fn read_char(&self) -> char {
    method clear_rx (line 464) | fn clear_rx(&self) {
    method chars_written (line 475) | fn chars_written(&self) -> usize {
    method chars_read (line 479) | fn chars_read(&self) -> usize {
    method handle (line 487) | fn handle(&self) -> Result<(), &'static str> {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/device_driver/common.rs
  type MMIODerefWrapper (line 14) | pub struct MMIODerefWrapper<T> {
  type BoundedUsize (line 21) | pub struct BoundedUsize<const MAX_INCLUSIVE: usize>(usize);
  function new (line 29) | pub const unsafe fn new(start_addr: Address<Virtual>) -> Self {
  type Target (line 38) | type Target = T;
  function deref (line 40) | fn deref(&self) -> &Self::Target {
  constant MAX_INCLUSIVE (line 46) | pub const MAX_INCLUSIVE: usize = MAX_INCLUSIVE;
  function new (line 49) | pub const fn new(number: usize) -> Self {
  function get (line 56) | pub const fn get(self) -> usize {
  function fmt (line 62) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi.rs
  function board_name (line 17) | pub fn board_name() -> &'static str {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi/driver.rs
  function instantiate_uart (line 39) | unsafe fn instantiate_uart() -> Result<(), &'static str> {
  function post_init_uart (line 50) | unsafe fn post_init_uart() -> Result<(), &'static str> {
  function instantiate_gpio (line 57) | unsafe fn instantiate_gpio() -> Result<(), &'static str> {
  function post_init_gpio (line 68) | unsafe fn post_init_gpio() -> Result<(), &'static str> {
  function instantiate_interrupt_controller (line 75) | unsafe fn instantiate_interrupt_controller() -> Result<(), &'static str> {
  function instantiate_interrupt_controller (line 90) | unsafe fn instantiate_interrupt_controller() -> Result<(), &'static str> {
  function post_init_interrupt_controller (line 103) | unsafe fn post_init_interrupt_controller() -> Result<(), &'static str> {
  function driver_uart (line 110) | unsafe fn driver_uart() -> Result<(), &'static str> {
  function driver_gpio (line 124) | unsafe fn driver_gpio() -> Result<(), &'static str> {
  function driver_interrupt_controller (line 138) | unsafe fn driver_interrupt_controller() -> Result<(), &'static str> {
  function init (line 160) | pub unsafe fn init() -> Result<(), &'static str> {
  function qemu_bring_up_console (line 177) | pub fn qemu_bring_up_console() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi/exception/asynchronous.rs
  constant PL011_UART (line 20) | pub const PL011_UART: IRQNumber = IRQNumber::Peripheral(PeripheralIRQ::n...
  constant PL011_UART (line 27) | pub const PL011_UART: IRQNumber = IRQNumber::new(153);

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi/memory.rs
  constant PERIPHERAL_IC_START (line 101) | pub const PERIPHERAL_IC_START: Address<Physical> = Address::new(0x3F00_B...
  constant PERIPHERAL_IC_SIZE (line 102) | pub const PERIPHERAL_IC_SIZE:  usize             =              0x24;
  constant GPIO_START (line 104) | pub const GPIO_START:          Address<Physical> = Address::new(0x3F20_0...
  constant GPIO_SIZE (line 105) | pub const GPIO_SIZE:           usize             =              0xA0;
  constant PL011_UART_START (line 107) | pub const PL011_UART_START:    Address<Physical> = Address::new(0x3F20_1...
  constant PL011_UART_SIZE (line 108) | pub const PL011_UART_SIZE:     usize             =              0x48;
  constant END (line 110) | pub const END:                 Address<Physical> = Address::new(0x4001_0...
  constant GPIO_START (line 118) | pub const GPIO_START:       Address<Physical> = Address::new(0xFE20_0000);
  constant GPIO_SIZE (line 119) | pub const GPIO_SIZE:        usize             =              0xA0;
  constant PL011_UART_START (line 121) | pub const PL011_UART_START: Address<Physical> = Address::new(0xFE20_1000);
  constant PL011_UART_SIZE (line 122) | pub const PL011_UART_SIZE:  usize             =              0x48;
  constant GICD_START (line 124) | pub const GICD_START:       Address<Physical> = Address::new(0xFF84_1000);
  constant GICD_SIZE (line 125) | pub const GICD_SIZE:        usize             =              0x824;
  constant GICC_START (line 127) | pub const GICC_START:       Address<Physical> = Address::new(0xFF84_2000);
  constant GICC_SIZE (line 128) | pub const GICC_SIZE:        usize             =              0x14;
  constant END (line 130) | pub const END:              Address<Physical> = Address::new(0xFF85_0000);
  constant END (line 133) | pub const END: Address<Physical> = mmio::END;
  function virt_code_start (line 146) | fn virt_code_start() -> PageAddress<Virtual> {
  function code_size (line 156) | fn code_size() -> usize {
  function virt_data_start (line 162) | fn virt_data_start() -> PageAddress<Virtual> {
  function data_size (line 172) | fn data_size() -> usize {
  function virt_mmio_remap_start (line 182) | fn virt_mmio_remap_start() -> PageAddress<Virtual> {
  function mmio_remap_size (line 192) | fn mmio_remap_size() -> usize {
  function virt_boot_core_stack_start (line 198) | fn virt_boot_core_stack_start() -> PageAddress<Virtual> {
  function boot_core_stack_size (line 204) | fn boot_core_stack_size() -> usize {
  function phys_addr_space_end_exclusive_addr (line 216) | pub fn phys_addr_space_end_exclusive_addr() -> PageAddress<Physical> {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/bsp/raspberrypi/memory/mmu.rs
  type KernelTranslationTable (line 22) | type KernelTranslationTable =
  type KernelGranule (line 31) | pub type KernelGranule = TranslationGranule<{ 64 * 1024 }>;
  type KernelVirtAddrSpace (line 34) | pub type KernelVirtAddrSpace = AddressSpace<{ 1024 * 1024 * 1024 }>;
  function size_to_num_pages (line 54) | const fn size_to_num_pages(size: usize) -> usize {
  function virt_code_region (line 62) | fn virt_code_region() -> MemoryRegion<Virtual> {
  function virt_data_region (line 72) | fn virt_data_region() -> MemoryRegion<Virtual> {
  function virt_boot_core_stack_region (line 82) | fn virt_boot_core_stack_region() -> MemoryRegion<Virtual> {
  function kernel_virt_to_phys_region (line 93) | fn kernel_virt_to_phys_region(virt_region: MemoryRegion<Virtual>) -> Mem...
  function kernel_translation_tables (line 110) | pub fn kernel_translation_tables() -> &'static InitStateLock<KernelTrans...
  function virt_mmio_remap_region (line 115) | pub fn virt_mmio_remap_region() -> MemoryRegion<Virtual> {
  function kernel_map_binary (line 129) | pub unsafe fn kernel_map_binary() -> Result<(), &'static str> {
  function virt_mem_layout_sections_are_64KiB_aligned (line 178) | fn virt_mem_layout_sections_are_64KiB_aligned() {
  function virt_mem_layout_has_no_overlaps (line 197) | fn virt_mem_layout_has_no_overlaps() {
  function kernel_tables_in_bss (line 213) | fn kernel_tables_in_bss() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/common.rs
  function is_aligned (line 9) | pub const fn is_aligned(value: usize, alignment: usize) -> bool {
  function align_down (line 17) | pub const fn align_down(value: usize, alignment: usize) -> usize {
  function align_up (line 25) | pub const fn align_up(value: usize, alignment: usize) -> usize {
  function size_human_readable_ceil (line 32) | pub const fn size_human_readable_ceil(size: usize) -> (usize, &'static s...

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/console.rs
  type Write (line 20) | pub trait Write {
    method write_char (line 22) | fn write_char(&self, c: char);
    method write_fmt (line 25) | fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result;
    method flush (line 28) | fn flush(&self);
  type Read (line 32) | pub trait Read {
    method read_char (line 34) | fn read_char(&self) -> char {
    method clear_rx (line 39) | fn clear_rx(&self);
  type Statistics (line 43) | pub trait Statistics {
    method chars_written (line 45) | fn chars_written(&self) -> usize {
    method chars_read (line 50) | fn chars_read(&self) -> usize {
  type All (line 56) | pub trait All: Write + Read + Statistics {}
  function register_console (line 72) | pub fn register_console(new_console: &'static (dyn interface::All + Sync...
  function console (line 79) | pub fn console() -> &'static dyn interface::All {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/console/null_console.rs
  type NullConsole (line 14) | pub struct NullConsole;
    method write_char (line 27) | fn write_char(&self, _c: char) {}
    method write_fmt (line 29) | fn write_fmt(&self, _args: fmt::Arguments) -> fmt::Result {
    method flush (line 33) | fn flush(&self) {}
    method clear_rx (line 37) | fn clear_rx(&self) {}

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/driver.rs
  constant NUM_DRIVERS (line 17) | const NUM_DRIVERS: usize = 5;
  type DriverManagerInner (line 19) | struct DriverManagerInner<T>
  type DeviceDriver (line 34) | pub trait DeviceDriver {
    method compatible (line 39) | fn compatible(&self) -> &'static str;
    method init (line 46) | unsafe fn init(&self) -> Result<(), &'static str> {
    method register_and_enable_irq_handler (line 54) | fn register_and_enable_irq_handler(
  type DeviceDriverPostInitCallback (line 68) | pub type DeviceDriverPostInitCallback = unsafe fn() -> Result<(), &'stat...
  type DeviceDriverDescriptor (line 72) | pub struct DeviceDriverDescriptor<T>
  type DriverManager (line 82) | pub struct DriverManager<T>
  function new (line 104) | pub const fn new() -> Self {
  function new (line 118) | pub fn new(
  function driver_manager (line 132) | pub fn driver_manager() -> &'static DriverManager<exception::asynchronou...
  function new (line 141) | pub const fn new() -> Self {
  function register_driver (line 148) | pub fn register_driver(&self, descriptor: DeviceDriverDescriptor<T>) {
  function for_each_descriptor (line 156) | fn for_each_descriptor<'a>(&'a self, f: impl FnMut(&'a DeviceDriverDescr...
  function init_drivers_and_irqs (line 171) | pub unsafe fn init_drivers_and_irqs(&self) {
  function enumerate (line 213) | pub fn enumerate(&self) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/exception.rs
  type PrivilegeLevel (line 25) | pub enum PrivilegeLevel {
  function test_runner_executes_in_kernel_mode (line 43) | fn test_runner_executes_in_kernel_mode() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous.rs
  type IRQNumber (line 28) | pub type IRQNumber = bsp::exception::asynchronous::IRQNumber;
  type IRQHandlerDescriptor (line 32) | pub struct IRQHandlerDescriptor<T>
  type IRQContext (line 54) | pub struct IRQContext<'irq_context> {
  type IRQHandler (line 62) | pub trait IRQHandler {
    method handle (line 64) | fn handle(&self) -> Result<(), &'static str>;
  type IRQManager (line 71) | pub trait IRQManager {
    method register_handler (line 76) | fn register_handler(
    method enable (line 82) | fn enable(&self, irq_number: &Self::IRQNumberType);
    method handle_pending_irqs (line 92) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 98) | fn print_handler(&self) {}
  function new (line 120) | pub const fn new(
  function number (line 133) | pub const fn number(&self) -> T {
  function name (line 138) | pub const fn name(&self) -> &'static str {
  function handler (line 143) | pub const fn handler(&self) -> &'static (dyn interface::IRQHandler + Syn...
  function new (line 160) | pub unsafe fn new() -> Self {
  function exec_with_irq_masked (line 170) | pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
  function register_irq_manager (line 179) | pub fn register_irq_manager(
  function irq_manager (line 188) | pub fn irq_manager() -> &'static dyn interface::IRQManager<IRQNumberType...

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/exception/asynchronous/null_irq_manager.rs
  type NullIRQManager (line 13) | pub struct NullIRQManager;
    type IRQNumberType (line 26) | type IRQNumberType = super::IRQNumber;
    method register_handler (line 28) | fn register_handler(
    method enable (line 35) | fn enable(&self, _irq_number: &Self::IRQNumberType) {
    method handle_pending_irqs (line 39) | fn handle_pending_irqs<'irq_context>(&'irq_context self, _ic: &IRQCont...

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/lib.rs
  function version (line 152) | pub fn version() -> &'static str {
  function kernel_init (line 162) | fn kernel_init() -> !;
  function test_runner (line 170) | pub fn test_runner(tests: &[&test_types::UnitTest]) {
  function kernel_init (line 188) | unsafe fn kernel_init() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/main.rs
  function kernel_init (line 28) | unsafe fn kernel_init() -> ! {
  function kernel_main (line 61) | fn kernel_main() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory.rs
  type AddressType (line 21) | pub trait AddressType: Copy + Clone + PartialOrd + PartialEq + Ord + Eq {}
  type Physical (line 25) | pub enum Physical {}
  type Virtual (line 29) | pub enum Virtual {}
  type Address (line 33) | pub struct Address<ATYPE: AddressType> {
  function new (line 47) | pub const fn new(value: usize) -> Self {
  function as_usize (line 55) | pub const fn as_usize(self) -> usize {
  function align_down_page (line 61) | pub const fn align_down_page(self) -> Self {
  function align_up_page (line 69) | pub const fn align_up_page(self) -> Self {
  function is_page_aligned (line 76) | pub const fn is_page_aligned(&self) -> bool {
  function offset_into_page (line 81) | pub const fn offset_into_page(&self) -> usize {
  type Output (line 87) | type Output = Self;
  function add (line 90) | fn add(self, rhs: usize) -> Self::Output {
  type Output (line 99) | type Output = Self;
  function sub (line 102) | fn sub(self, rhs: Address<ATYPE>) -> Self::Output {
  function fmt (line 112) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function fmt (line 125) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function address_type_method_sanity (line 150) | fn address_type_method_sanity() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu.rs
  type MMUEnableError (line 32) | pub enum MMUEnableError {
    method fmt (line 116) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type MMU (line 42) | pub trait MMU {
    method enable_mmu_and_caching (line 48) | unsafe fn enable_mmu_and_caching(
    method is_enabled (line 54) | fn is_enabled(&self) -> bool;
  type TranslationGranule (line 59) | pub struct TranslationGranule<const GRANULE_SIZE: usize>;
  type AddressSpace (line 62) | pub struct AddressSpace<const AS_SIZE: usize>;
  type AssociatedTranslationTable (line 65) | pub trait AssociatedTranslationTable {
  function kernel_init_mmio_va_allocator (line 81) | fn kernel_init_mmio_va_allocator() {
  function kernel_map_at_unchecked (line 95) | unsafe fn kernel_map_at_unchecked(
  constant SIZE (line 126) | pub const SIZE: usize = Self::size_checked();
  constant MASK (line 129) | pub const MASK: usize = Self::SIZE - 1;
  constant SHIFT (line 132) | pub const SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 134) | const fn size_checked() -> usize {
  constant SIZE (line 143) | pub const SIZE: usize = Self::size_checked();
  constant SIZE_SHIFT (line 146) | pub const SIZE_SHIFT: usize = Self::SIZE.trailing_zeros() as usize;
  function size_checked (line 148) | const fn size_checked() -> usize {
  function kernel_map_at (line 166) | pub unsafe fn kernel_map_at(
  function kernel_map_mmio (line 188) | pub unsafe fn kernel_map_mmio(
  function kernel_map_binary (line 232) | pub unsafe fn kernel_map_binary() -> Result<Address<Physical>, &'static ...
  function enable_mmu_and_caching (line 249) | pub unsafe fn enable_mmu_and_caching(
  function post_enable_init (line 256) | pub fn post_enable_init() {
  function kernel_print_mappings (line 261) | pub fn kernel_print_mappings() {
  function no_manual_mmio_map (line 277) | fn no_manual_mmio_map() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/mapping_record.rs
  type MappingRecordEntry (line 20) | struct MappingRecordEntry {
    method new (line 44) | pub fn new(
    method find_next_free_user (line 59) | fn find_next_free_user(&mut self) -> Result<&mut Option<&'static str>,...
    method add_user (line 67) | pub fn add_user(&mut self, user: &'static str) -> Result<(), &'static ...
  type MappingRecord (line 28) | struct MappingRecord {
    method new (line 75) | pub const fn new() -> Self {
    method size (line 79) | fn size(&self) -> usize {
    method sort (line 83) | fn sort(&mut self) {
    method find_next_free (line 92) | fn find_next_free(&mut self) -> Result<&mut Option<MappingRecordEntry>...
    method find_duplicate (line 100) | fn find_duplicate(
    method add (line 121) | pub fn add(
    method print (line 142) | pub fn print(&self) {
  function kernel_add (line 209) | pub fn kernel_add(
  function kernel_find_and_insert_mmio_duplicate (line 218) | pub fn kernel_find_and_insert_mmio_duplicate(
  function kernel_print (line 236) | pub fn kernel_print() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/page_alloc.rs
  type PageAllocator (line 20) | pub struct PageAllocator<ATYPE: AddressType> {
  function kernel_mmio_va_allocator (line 36) | pub fn kernel_mmio_va_allocator() -> &'static IRQSafeNullLock<PageAlloca...
  function new (line 42) | pub const fn new() -> Self {
  function init (line 47) | pub fn init(&mut self, pool: MemoryRegion<ATYPE>) {
  function alloc (line 57) | pub fn alloc(

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/translation_table.rs
  type TranslationTable (line 29) | pub trait TranslationTable {
    method init (line 36) | fn init(&mut self);
    method phys_base_address (line 39) | fn phys_base_address(&self) -> Address<Physical>;
    method map_at (line 50) | unsafe fn map_at(
  function translationtable_implementation_sanity (line 73) | fn translationtable_implementation_sanity() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/memory/mmu/types.rs
  type PageAddress (line 19) | pub struct PageAddress<ATYPE: AddressType> {
  type MemoryRegion (line 25) | pub struct MemoryRegion<ATYPE: AddressType> {
  type MemAttributes (line 33) | pub enum MemAttributes {
  type AccessPermissions (line 41) | pub enum AccessPermissions {
  type AttributeFields (line 49) | pub struct AttributeFields {
  type MMIODescriptor (line 57) | pub struct MMIODescriptor {
    method new (line 275) | pub const fn new(start_addr: Address<Physical>, size: usize) -> Self {
    method start_addr (line 286) | pub const fn start_addr(&self) -> Address<Physical> {
    method end_addr_exclusive (line 291) | pub fn end_addr_exclusive(&self) -> Address<Physical> {
  function into_inner (line 71) | pub fn into_inner(self) -> Address<ATYPE> {
  function checked_offset (line 79) | pub fn checked_offset(self, count: isize) -> Option<Self> {
  function from (line 100) | fn from(addr: usize) -> Self {
  function from (line 113) | fn from(addr: Address<ATYPE>) -> Self {
  method steps_between (line 121) | fn steps_between(start: &Self, end: &Self) -> Option<usize> {
  method forward_checked (line 133) | fn forward_checked(start: Self, count: usize) -> Option<Self> {
  method backward_checked (line 137) | fn backward_checked(start: Self, count: usize) -> Option<Self> {
  function new (line 147) | pub fn new(start: PageAddress<ATYPE>, end_exclusive: PageAddress<ATYPE>)...
  function as_range (line 156) | fn as_range(&self) -> Range<PageAddress<ATYPE>> {
  function start_page_addr (line 161) | pub fn start_page_addr(&self) -> PageAddress<ATYPE> {
  function start_addr (line 166) | pub fn start_addr(&self) -> Address<ATYPE> {
  function end_exclusive_page_addr (line 171) | pub fn end_exclusive_page_addr(&self) -> PageAddress<ATYPE> {
  function end_inclusive_page_addr (line 176) | pub fn end_inclusive_page_addr(&self) -> PageAddress<ATYPE> {
  function contains (line 181) | pub fn contains(&self, addr: Address<ATYPE>) -> bool {
  function overlaps (line 187) | pub fn overlaps(&self, other_region: &Self) -> bool {
  function num_pages (line 195) | pub fn num_pages(&self) -> usize {
  function size (line 200) | pub fn size(&self) -> usize {
  function take_first_n_pages (line 222) | pub fn take_first_n_pages(&mut self, num_pages: NonZeroUsize) -> Result<...
  type Item (line 246) | type Item = PageAddress<ATYPE>;
  type IntoIter (line 247) | type IntoIter = Range<Self::Item>;
  method into_iter (line 249) | fn into_iter(self) -> Self::IntoIter {
  function from (line 258) | fn from(desc: MMIODescriptor) -> Self {
  function pageaddress_type_method_sanity (line 308) | fn pageaddress_type_method_sanity() {
  function memoryregion_type_method_sanity (line 343) | fn memoryregion_type_method_sanity() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/panic_wait.rs
  function _panic_exit (line 19) | fn _panic_exit() -> ! {
  function panic_prevent_reenter (line 43) | fn panic_prevent_reenter() {
  function panic (line 61) | fn panic(info: &PanicInfo) -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/print.rs
  function _print (line 15) | pub fn _print(args: fmt::Arguments) {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/state.rs
  type State (line 15) | enum State {
  type StateManager (line 33) | pub struct StateManager(AtomicU8);
    constant INIT (line 51) | const INIT: u8 = 0;
    constant SINGLE_CORE_MAIN (line 52) | const SINGLE_CORE_MAIN: u8 = 1;
    constant MULTI_CORE_MAIN (line 53) | const MULTI_CORE_MAIN: u8 = 2;
    method new (line 56) | pub const fn new() -> Self {
    method state (line 61) | fn state(&self) -> State {
    method is_init (line 73) | pub fn is_init(&self) -> bool {
    method transition_to_single_core_main (line 78) | pub fn transition_to_single_core_main(&self) {
  function state_manager (line 46) | pub fn state_manager() -> &'static StateManager {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/synchronization.rs
  type Mutex (line 24) | pub trait Mutex {
    method lock (line 29) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
  type ReadWriteEx (line 36) | pub trait ReadWriteEx {
    method write (line 41) | fn write<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
    method read (line 44) | fn read<'a, R>(&'a self, f: impl FnOnce(&'a Self::Data) -> R) -> R;
  type IRQSafeNullLock (line 55) | pub struct IRQSafeNullLock<T>
  type InitStateLock (line 65) | pub struct InitStateLock<T>
  function new (line 81) | pub const fn new(data: T) -> Self {
  function new (line 93) | pub const fn new(data: T) -> Self {
  type Data (line 106) | type Data = T;
  function lock (line 108) | fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
  type Data (line 119) | type Data = T;
  function write (line 121) | fn write<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R {
  function read (line 136) | fn read<'a, R>(&'a self, f: impl FnOnce(&'a Self::Data) -> R) -> R {
  function init_state_lock_is_transparent (line 154) | fn init_state_lock_is_transparent() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/src/time.rs
  type TimeManager (line 18) | pub struct TimeManager;
    method new (line 37) | pub const fn new() -> Self {
    method resolution (line 42) | pub fn resolution(&self) -> Duration {
    method uptime (line 49) | pub fn uptime(&self) -> Duration {
    method spin_for (line 54) | pub fn spin_for(&self, duration: Duration) {
  function time_manager (line 31) | pub fn time_manager() -> &'static TimeManager {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rb
  class TxRxHandshakeTest (line 10) | class TxRxHandshakeTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, qemu_in)
  class TxStatisticsTest (line 22) | class TxStatisticsTest < SubtestBase
    method name (line 23) | def name
    method run (line 27) | def run(qemu_out, _qemu_in)
  class RxStatisticsTest (line 33) | class RxStatisticsTest < SubtestBase
    method name (line 34) | def name
    method run (line 38) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 46) | def subtest_collection

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/00_console_sanity.rs
  function kernel_init (line 17) | unsafe fn kernel_init() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/01_timer_sanity.rs
  function kernel_init (line 18) | unsafe fn kernel_init() -> ! {
  function timer_is_counting (line 42) | fn timer_is_counting() {
  function timer_resolution_is_sufficient (line 48) | fn timer_resolution_is_sufficient() {
  function spin_accuracy_check_1_second (line 55) | fn spin_accuracy_check_1_second() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/02_exception_sync_page_fault.rs
  function kernel_init (line 23) | unsafe fn kernel_init() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rb
  class ExceptionRestoreTest (line 10) | class ExceptionRestoreTest < SubtestBase
    method name (line 11) | def name
    method run (line 15) | def run(qemu_out, _qemu_in)
  function subtest_collection (line 23) | def subtest_collection

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/03_exception_restore_sanity.rs
  function nested_system_call (line 18) | fn nested_system_call() {
  function kernel_init (line 32) | unsafe fn kernel_init() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/04_exception_irq_sanity.rs
  function kernel_init (line 17) | unsafe fn kernel_init() -> ! {
  function local_irq_mask_works (line 41) | fn local_irq_mask_works() {
  function local_irq_unmask_works (line 54) | fn local_irq_unmask_works() {
  function local_irq_mask_save_works (line 65) | fn local_irq_mask_save_works() {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/panic_exit_success/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/kernel/tests/panic_wait_forever/mod.rs
  function _panic_exit (line 7) | fn _panic_exit() -> ! {

FILE: 14_virtual_mem_part2_mmio_remap/libraries/test-macros/src/lib.rs
  function kernel_test (line 11) | pub fn kernel_test(_attr: TokenStream, input: TokenStream) -> TokenStream {

FILE: 14_virtual_mem_part2_mmio_remap/libraries/test-types/src/lib.rs
  type UnitTest (line 10) | pub struct UnitTest {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/build.rs
  function main (line 3) | fn main() {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/cpu.rs
  function wait_forever (line 24) | pub fn wait_forever() -> ! {
  constant QEMU_EXIT_HANDLE (line 37) | const QEMU_EXIT_HANDLE: qemu_exit::AArch64 = qemu_exit::AArch64::new();
  function qemu_exit_failure (line 41) | pub fn qemu_exit_failure() -> ! {
  function qemu_exit_success (line 47) | pub fn qemu_exit_success() -> ! {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/cpu/boot.rs
  function prepare_el2_to_el1_transition (line 37) | unsafe fn prepare_el2_to_el1_transition(phys_boot_core_stack_end_exclusi...
  function _start_rust (line 79) | pub unsafe extern "C" fn _start_rust(

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/cpu/smp.rs
  function core_id (line 23) | pub fn core_id<T>() -> T

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/exception.rs
  type SpsrEL1 (line 31) | struct SpsrEL1(InMemoryRegister<u64, SPSR_EL1::Register>);
    method fmt (line 161) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type EsrEL1 (line 32) | struct EsrEL1(InMemoryRegister<u64, ESR_EL1::Register>);
    method exception_class (line 193) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method iss (line 199) | fn iss(&self) -> u64 {
    method fmt (line 207) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  type ExceptionContext (line 36) | struct ExceptionContext {
    method exception_class (line 228) | fn exception_class(&self) -> Option<ESR_EL1::EC::Value> {
    method fault_address_valid (line 233) | fn fault_address_valid(&self) -> bool {
    method fmt (line 254) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  function default_exception_handler (line 58) | fn default_exception_handler(exc: &ExceptionContext) {
  function current_el0_synchronous (line 71) | extern "C" fn current_el0_synchronous(_e: &mut ExceptionContext) {
  function current_el0_irq (line 76) | extern "C" fn current_el0_irq(_e: &mut ExceptionContext) {
  function current_el0_serror (line 81) | extern "C" fn current_el0_serror(_e: &mut ExceptionContext) {
  function current_elx_synchronous (line 90) | extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
  function current_elx_irq (line 106) | extern "C" fn current_elx_irq(_e: &mut ExceptionContext) {
  function current_elx_serror (line 112) | extern "C" fn current_elx_serror(e: &mut ExceptionContext) {
  function lower_aarch64_synchronous (line 121) | extern "C" fn lower_aarch64_synchronous(e: &mut ExceptionContext) {
  function lower_aarch64_irq (line 126) | extern "C" fn lower_aarch64_irq(e: &mut ExceptionContext) {
  function lower_aarch64_serror (line 131) | extern "C" fn lower_aarch64_serror(e: &mut ExceptionContext) {
  function lower_aarch32_synchronous (line 140) | extern "C" fn lower_aarch32_synchronous(e: &mut ExceptionContext) {
  function lower_aarch32_irq (line 145) | extern "C" fn lower_aarch32_irq(e: &mut ExceptionContext) {
  function lower_aarch32_serror (line 150) | extern "C" fn lower_aarch32_serror(e: &mut ExceptionContext) {
  function current_privilege_level (line 285) | pub fn current_privilege_level() -> (PrivilegeLevel, &'static str) {
  function handling_init (line 303) | pub unsafe fn handling_init() {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/exception/asynchronous.rs
  constant IRQ (line 23) | pub const IRQ: u8 = 0b0010;
  type DaifField (line 26) | trait DaifField {
    method daif_field (line 27) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
    method daif_field (line 40) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 46) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 52) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
    method daif_field (line 58) | fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register> {
  type Debug (line 30) | struct Debug;
  type SError (line 31) | struct SError;
  type IRQ (line 32) | struct IRQ;
  type FIQ (line 33) | struct FIQ;
  function is_masked (line 63) | fn is_masked<T>() -> bool
  function is_local_irq_masked (line 75) | pub fn is_local_irq_masked() -> bool {
  function local_irq_unmask (line 87) | pub fn local_irq_unmask() {
  function local_irq_mask (line 99) | pub fn local_irq_mask() {
  function local_irq_mask_save (line 111) | pub fn local_irq_mask_save() -> u64 {
  function local_irq_restore (line 124) | pub fn local_irq_restore(saved: u64) {
  function print_state (line 130) | pub fn print_state() {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/memory/mmu.rs
  type MemoryManagementUnit (line 29) | struct MemoryManagementUnit;
    method set_up_mair (line 69) | fn set_up_mair(&self) {
    method configure_translation_control (line 82) | fn configure_translation_control(&self) {
    method enable_mmu_and_caching (line 115) | unsafe fn enable_mmu_and_caching(
    method is_enabled (line 153) | fn is_enabled(&self) -> bool {
  type Granule512MiB (line 35) | pub type Granule512MiB = TranslationGranule<{ 512 * 1024 * 1024 }>;
  type Granule64KiB (line 36) | pub type Granule64KiB = TranslationGranule<{ 64 * 1024 }>;
  constant DEVICE (line 41) | pub const DEVICE: u64 = 0;
  constant NORMAL (line 42) | pub const NORMAL: u64 = 1;
  function arch_address_space_size_sanity_checks (line 57) | pub const fn arch_address_space_size_sanity_checks() {
  function mmu (line 105) | pub fn mmu() -> &'static impl memory::mmu::interface::MMU {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/memory/mmu/translation_table.rs
  type TableDescriptor (line 114) | struct TableDescriptor {
    method new_zeroed (line 164) | pub const fn new_zeroed() -> Self {
    method from_next_lvl_table_addr (line 169) | pub fn from_next_lvl_table_addr(phys_next_lvl_table_addr: Address<Phys...
  type PageDescriptor (line 123) | struct PageDescriptor {
    method new_zeroed (line 253) | pub const fn new_zeroed() -> Self {
    method from_output_page_addr (line 258) | pub fn from_output_page_addr(
    method is_valid (line 277) | fn is_valid(&self) -> bool {
    method output_page_addr (line 283) | fn output_page_addr(&self) -> PageAddress<Physical> {
    method try_attributes (line 291) | fn try_attributes(&self) -> Result<AttributeFields, &'static str> {
  type StartAddr (line 127) | trait StartAddr {
    method virt_start_addr (line 128) | fn virt_start_addr(&self) -> Address<Virtual>;
    method virt_start_addr (line 155) | fn virt_start_addr(&self) -> Address<Virtual> {
  type FixedSizeTranslationTable (line 139) | pub struct FixedSizeTranslationTable<const NUM_TABLES: usize> {
  function from (line 187) | fn from(attribute_fields: AttributeFields) -> Self {
  type Error (line 222) | type Error = &'static str;
  method try_from (line 224) | fn try_from(
  type TableStartFromBottom (line 305) | type TableStartFromBottom = FixedSizeTranslationTable<{ Self::SIZE >> Gr...
  function _new (line 311) | const fn _new(for_precompute: bool) -> Self {
  function new_for_precompute (line 324) | pub const fn new_for_precompute() -> Self {
  function new_for_runtime (line 329) | pub fn new_for_runtime() -> Self {
  function lvl2_lvl3_index_from_page_addr (line 335) | fn lvl2_lvl3_index_from_page_addr(
  function page_descriptor_from_page_addr (line 352) | fn page_descriptor_from_page_addr(
  function set_page_descriptor_from_page_addr (line 366) | fn set_page_descriptor_from_page_addr(
  function init (line 390) | fn init(&mut self) -> Result<(), &'static str> {
  function map_at (line 409) | unsafe fn map_at(
  function try_virt_page_addr_to_phys_page_addr (line 437) | fn try_virt_page_addr_to_phys_page_addr(
  function try_page_attributes (line 450) | fn try_page_attributes(
  function try_virt_addr_to_phys_addr (line 466) | fn try_virt_addr_to_phys_addr(
  type MinSizeTranslationTable (line 482) | pub type MinSizeTranslationTable = FixedSizeTranslationTable<1>;
  function size_of_tabledescriptor_equals_64_bit (line 491) | fn size_of_tabledescriptor_equals_64_bit() {
  function size_of_pagedescriptor_equals_64_bit (line 500) | fn size_of_pagedescriptor_equals_64_bit() {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/_arch/aarch64/time.rs
  constant NANOSEC_PER_SEC (line 27) | const NANOSEC_PER_SEC: NonZeroU64 = NonZeroU64::new(1_000_000_000).unwra...
  type GenericTimerCounterValue (line 30) | struct GenericTimerCounterValue(u64);
    constant MAX (line 55) | pub const MAX: Self = GenericTimerCounterValue(u64::MAX);
    type Error (line 96) | type Error = &'static str;
    method try_from (line 98) | fn try_from(duration: Duration) -> Result<Self, Self::Error> {
  function arch_timer_counter_frequency (line 45) | fn arch_timer_counter_frequency() -> NonZeroU32 {
  type Output (line 59) | type Output = Self;
  method add (line 61) | fn add(self, other: Self) -> Self {
  method from (line 67) | fn from(counter_value: GenericTimerCounterValue) -> Self {
  function max_duration (line 91) | fn max_duration() -> Duration {
  function read_cntpct (line 121) | fn read_cntpct() -> GenericTimerCounterValue {
  function resolution (line 134) | pub fn resolution() -> Duration {
  function uptime (line 141) | pub fn uptime() -> Duration {
  function spin_for (line 146) | pub fn spin_for(duration: Duration) {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2.rs
  type HandlerTable (line 94) | type HandlerTable = [Option<exception::asynchronous::IRQHandlerDescripto...
  type IRQNumber (line 102) | pub type IRQNumber = BoundedUsize<{ GICv2::MAX_IRQ_NUMBER }>;
  type GICv2 (line 105) | pub struct GICv2 {
    constant MAX_IRQ_NUMBER (line 121) | const MAX_IRQ_NUMBER: usize = 300;
    constant COMPATIBLE (line 123) | pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Con...
    method new (line 130) | pub const unsafe fn new(
    type IRQNumberType (line 148) | type IRQNumberType = IRQNumber;
    method compatible (line 150) | fn compatible(&self) -> &'static str {
    method init (line 154) | unsafe fn init(&self) -> Result<(), &'static str> {
    type IRQNumberType (line 167) | type IRQNumberType = IRQNumber;
    method register_handler (line 169) | fn register_handler(
    method enable (line 186) | fn enable(&self, irq_number: &Self::IRQNumberType) {
    method handle_pending_irqs (line 190) | fn handle_pending_irqs<'irq_context>(
    method print_handler (line 218) | fn print_handler(&self) {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2/gicc.rs
  type Registers (line 59) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GICC (line 66) | pub struct GICC {
    method new (line 80) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method priority_accept_all (line 97) | pub fn priority_accept_all(&self) {
    method enable (line 107) | pub fn enable(&self) {
    method pending_irq_number (line 120) | pub fn pending_irq_number<'irq_context>(
    method mark_comleted (line 138) | pub fn mark_comleted<'irq_context>(

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs
  type SharedRegisters (line 73) | type SharedRegisters = MMIODerefWrapper<SharedRegisterBlock>;
    method num_irqs (line 98) | fn num_irqs(&mut self) -> usize {
    method implemented_itargets_slice (line 107) | fn implemented_itargets_slice(&mut self) -> &[ReadWrite<u32, ITARGETSR...
  type BankedRegisters (line 76) | type BankedRegisters = MMIODerefWrapper<BankedRegisterBlock>;
  type GICD (line 83) | pub struct GICD {
    method new (line 133) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method local_gic_target_mask (line 146) | fn local_gic_target_mask(&self) -> u32 {
    method boot_core_init (line 151) | pub fn boot_core_init(&self) {
    method enable (line 175) | pub fn enable(&self, irq_num: &super::IRQNumber) {

FILE: 15_virtual_mem_part3_precomputed_tables/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
  type Registers (line 113) | type Registers = MMIODerefWrapper<RegisterBlock>;
  type GPIOInner (line 115) | struct GPIOInner {
    method new (line 138) | pub const unsafe fn new(mmio_start_addr: Address<Virtual>) -> Self {
    method disable_pud_14_15_bcm2837 (line 146) | fn disable_pud_14_15_bcm2837(&mut self) {
    method disable_pud_14_15_bcm2711 (line 167) | fn disable_pud_14_15_bcm2711(&mut self) {
    method map_pl011_uart (line 178) | pub fn map_pl011_uart(&mut self) {
  type GPIO (line 124) | pub struct GPIO {
    constant COMPATIBLE (line 198) | pub const COMPATIBLE: &
Condensed preview — 1175 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,489K chars).
[
  {
    "path": ".editorconfig",
    "chars": 429,
    "preview": "# editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nt"
  },
  {
    "path": ".githooks/pre-commit",
    "chars": 1331,
    "preview": "#!/usr/bin/env ruby\n# frozen_string_literal: true\n\n# SPDX-License-Identifier: MIT OR Apache-2.0\n#\n# Copyright (c) 2018-2"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 101,
    "preview": "custom: [\"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/master/SPONSORING.md\"]\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 564,
    "preview": "### Description\n\n<Please describe the issues fixed by this PR>\n\nRelated Issue: <Insert link here if applicable>\n\n### Pre"
  },
  {
    "path": ".github/workflows/build_rpi3.yml",
    "chars": 976,
    "preview": "name: BSP-RPi3\n\non:\n    push:\n        branches:\n            - master\n        paths-ignore:\n            - \"utils/**\"\n    "
  },
  {
    "path": ".github/workflows/build_rpi4.yml",
    "chars": 976,
    "preview": "name: BSP-RPi4\n\non:\n    push:\n        branches:\n            - master\n        paths-ignore:\n            - \"utils/**\"\n    "
  },
  {
    "path": ".github/workflows/sanity.yml",
    "chars": 1544,
    "preview": "name: Various Sanity Checks\n\non:\n    push:\n        branches:\n            - master\n    pull_request:\n        branches:\n  "
  },
  {
    "path": ".github/workflows/test_integration.yml",
    "chars": 996,
    "preview": "name: Integration-Tests\n\non:\n    push:\n        branches:\n            - master\n        paths-ignore:\n            - \"utils"
  },
  {
    "path": ".github/workflows/test_unit.yml",
    "chars": 1055,
    "preview": "name: Boot-and-Unit-Tests\n\non:\n    push:\n        branches:\n            - master\n        paths-ignore:\n            - \"uti"
  },
  {
    "path": ".github/workflows/test_xtra.yml",
    "chars": 966,
    "preview": "name: Xtra-Tests\n\non:\n    push:\n        branches:\n            - master\n        paths-ignore:\n            - \"utils/**\"\n  "
  },
  {
    "path": ".gitignore",
    "chars": 101,
    "preview": "**/target/*\n**/.gdb_history\n**/kernel8.img\n\nnode_modules\n.bundle\n.vendor\n\nGemfile.lock\npackage*.json\n"
  },
  {
    "path": ".prettierignore",
    "chars": 63,
    "preview": "**/*\n!**/*/\n\n**/target/\nnode_modules/\n.vendor/\n\n!*.json\n!*.yml\n"
  },
  {
    "path": ".prettierrc.json",
    "chars": 942,
    "preview": "{\n    \"printWidth\": 100,\n    \"tabWidth\": 4,\n    \"useTabs\": false,\n    \"semi\": true,\n    \"singleQuote\": false,\n    \"trail"
  },
  {
    "path": ".rubocop.yml",
    "chars": 825,
    "preview": "# The behavior of RuboCop can be controlled via the .rubocop.yml\n# configuration file. It makes it possible to enable/di"
  },
  {
    "path": ".ruby-version",
    "chars": 6,
    "preview": "3.0.2\n"
  },
  {
    "path": ".rustfmt.toml",
    "chars": 172,
    "preview": "newline_style = \"Unix\"\nedition = \"2021\"\nimports_granularity = \"Crate\"\nformat_code_in_doc_comments = true\nnormalize_comme"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 373,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "00_before_we_start/README.CN.md",
    "chars": 2215,
    "preview": "# 在我们开始之前\n\n下面的文本内容是1:1 复制的文档。在每个教程的内核主要源代码文档的头部。它描述了源代码的主要结构并且试着去传达各个方法背后的理念。请阅读文章以便你能熟悉你在教程中将会遇到的东西。这将帮助你更好的浏览代码和理解不同章节"
  },
  {
    "path": "00_before_we_start/README.ES.md",
    "chars": 5937,
    "preview": "# Antes de comenzar\n\nEl texto a continuación es una copia 1:1 de la documentación que \npuede ser encontrada al principio"
  },
  {
    "path": "00_before_we_start/README.md",
    "chars": 5156,
    "preview": "# Before we start\n\nThe following text is a 1:1 copy of the documentation that can be found at the top of the kernel's\nma"
  },
  {
    "path": "01_wait_forever/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "01_wait_forever/Cargo.toml",
    "chars": 479,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.1.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "01_wait_forever/Makefile",
    "chars": 7395,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "01_wait_forever/README.CN.md",
    "chars": 843,
    "preview": "# 教程 01 - 一直等待(死循环)\n\n## tl;dr\n\n项目框架已经构建完成;目前代码做的仅仅是挂起CPU核心执行内核代码。\n\n-  `Makefile` 目标项:\n    - `doc`: 生成文档。\n    - `qemu`: 在"
  },
  {
    "path": "01_wait_forever/README.ES.md",
    "chars": 1579,
    "preview": "# Tutorial 01 - Esperar infinitamente\n\n## tl;dr\n\n* Se configura la estructura que tiene el proyecto.\n\n* Se ejecuta una p"
  },
  {
    "path": "01_wait_forever/README.md",
    "chars": 1197,
    "preview": "# Tutorial 01 - Wait Forever\n\n## tl;dr\n\n- The project skeleton is set up.\n- A small piece of assembly code runs that jus"
  },
  {
    "path": "01_wait_forever/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "01_wait_forever/src/_arch/aarch64/cpu/boot.rs",
    "chars": 428,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/_arch/aarch64/cpu/boot.s",
    "chars": 703,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/bsp/raspberrypi/kernel.ld",
    "chars": 738,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "01_wait_forever/src/bsp/raspberrypi.rs",
    "chars": 189,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/bsp.rs",
    "chars": 329,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/cpu.rs",
    "chars": 150,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/main.rs",
    "chars": 5210,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "01_wait_forever/src/panic_wait.rs",
    "chars": 486,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "02_runtime_init/Cargo.toml",
    "chars": 603,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.2.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "02_runtime_init/Makefile",
    "chars": 7431,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "02_runtime_init/README.CN.md",
    "chars": 902,
    "preview": "# 教程 02 - 执行初始化\n\n## tl;dr\n\n- 我们拓展了`boot.S`,在第一次启动的时候调用Rust代码。\n  在跳转到rust代码前,对运行时进行了一些初始化工作。\n- Rust通过调用`panic()`挂起CPU。\n- "
  },
  {
    "path": "02_runtime_init/README.ES.md",
    "chars": 1810,
    "preview": "# Tutorial 02 - Inicialización del `runtime`\n\n## tl;dr\n\n* Extendimos la funcionalidad de `boot.s` para que sea capaz de "
  },
  {
    "path": "02_runtime_init/README.md",
    "chars": 11761,
    "preview": "# Tutorial 02 - Runtime Init\n\n## tl;dr\n\n- We extend `boot.s` to call into Rust code for the first time. Before the jump\n"
  },
  {
    "path": "02_runtime_init/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "02_runtime_init/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/_arch/aarch64/cpu/boot.s",
    "chars": 1873,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/_arch/aarch64/cpu.rs",
    "chars": 681,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/bsp/raspberrypi/kernel.ld",
    "chars": 2788,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "02_runtime_init/src/bsp/raspberrypi.rs",
    "chars": 186,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/bsp.rs",
    "chars": 329,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/cpu.rs",
    "chars": 499,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/main.rs",
    "chars": 5435,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "02_runtime_init/src/panic_wait.rs",
    "chars": 505,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "03_hacky_hello_world/Cargo.toml",
    "chars": 603,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.3.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "03_hacky_hello_world/Makefile",
    "chars": 8414,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "03_hacky_hello_world/README.CN.md",
    "chars": 740,
    "preview": "# 教程 03 - Hacky Hello World\n\n## tl;dr\n\n- 介绍全局的`println!()`宏以便尽早启用\"printf debugging\"。\n- 为了保持教程长度合理,打印函数目前 \"滥用\" 了 QEMU 属性,"
  },
  {
    "path": "03_hacky_hello_world/README.ES.md",
    "chars": 2573,
    "preview": "# Tutorial 03 - Hacky Hello World\n\n## tl;dr\n\n* Se añade la macro global `print!()` para habilitar la \"depuración basada "
  },
  {
    "path": "03_hacky_hello_world/README.md",
    "chars": 12267,
    "preview": "# Tutorial 03 - Hacky Hello World\n\n## tl;dr\n\n- Introducing global `println!()` macros to enable \"printf debugging\" at th"
  },
  {
    "path": "03_hacky_hello_world/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "03_hacky_hello_world/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/_arch/aarch64/cpu/boot.s",
    "chars": 1873,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/_arch/aarch64/cpu.rs",
    "chars": 681,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/bsp/raspberrypi/console.rs",
    "chars": 1633,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/bsp/raspberrypi/kernel.ld",
    "chars": 2788,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "03_hacky_hello_world/src/bsp/raspberrypi.rs",
    "chars": 203,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/bsp.rs",
    "chars": 329,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/console.rs",
    "chars": 1082,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/cpu.rs",
    "chars": 499,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/main.rs",
    "chars": 5570,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/panic_wait.rs",
    "chars": 2025,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/src/print.rs",
    "chars": 1012,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "03_hacky_hello_world/tests/boot_test_string.rb",
    "chars": 64,
    "preview": "# frozen_string_literal: true\n\nEXPECTED_PRINT = 'Stopping here'\n"
  },
  {
    "path": "04_safe_globals/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "04_safe_globals/Cargo.toml",
    "chars": 603,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.4.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "04_safe_globals/Makefile",
    "chars": 8414,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "04_safe_globals/README.CN.md",
    "chars": 1236,
    "preview": "# 教程 04 - 全局安全\n\n## tl;dr\n\n- 引入了假的锁。\n- 这是第一次展示原始操作系统同步,并支持安全访问全局数据结构。\n\n## Rust中的全局可变\n\n当我们引入全局可用的`print!`宏在 [教程03],我门有一点作弊"
  },
  {
    "path": "04_safe_globals/README.md",
    "chars": 12376,
    "preview": "# Tutorial 04 - Safe Globals\n\n## tl;dr\n\n- A pseudo-lock is introduced.\n- It is a first showcase of OS synchronization pr"
  },
  {
    "path": "04_safe_globals/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "04_safe_globals/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/_arch/aarch64/cpu/boot.s",
    "chars": 1873,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/_arch/aarch64/cpu.rs",
    "chars": 681,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/bsp/raspberrypi/console.rs",
    "chars": 3858,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/bsp/raspberrypi/kernel.ld",
    "chars": 2788,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "04_safe_globals/src/bsp/raspberrypi.rs",
    "chars": 203,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/bsp.rs",
    "chars": 329,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/console.rs",
    "chars": 1289,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/cpu.rs",
    "chars": 499,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/main.rs",
    "chars": 5745,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/panic_wait.rs",
    "chars": 2025,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/print.rs",
    "chars": 976,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/src/synchronization.rs",
    "chars": 2725,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "04_safe_globals/tests/boot_test_string.rb",
    "chars": 64,
    "preview": "# frozen_string_literal: true\n\nEXPECTED_PRINT = 'Stopping here'\n"
  },
  {
    "path": "05_drivers_gpio_uart/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "05_drivers_gpio_uart/Cargo.toml",
    "chars": 773,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.5.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "05_drivers_gpio_uart/Makefile",
    "chars": 9131,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "05_drivers_gpio_uart/README.CN.md",
    "chars": 3834,
    "preview": "# 教程 05 - 驱动程序: GPIO和UART\n\n## tl;dr\n\n- 添加了用于真实`UART`和`GPIO`控制器的驱动程序。\n- **我们将首次能够在真实硬件上运行代码** (请向下滚动查看说明)。\n\n## 简介\n\n在上一篇教程"
  },
  {
    "path": "05_drivers_gpio_uart/README.md",
    "chars": 56013,
    "preview": "# Tutorial 05 - Drivers: GPIO and UART\n\n## tl;dr\n\n- Drivers for the real `UART` and the `GPIO` controller are added.\n- *"
  },
  {
    "path": "05_drivers_gpio_uart/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.s",
    "chars": 1873,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/_arch/aarch64/cpu.rs",
    "chars": 856,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs",
    "chars": 6715,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs",
    "chars": 13925,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/device_driver/bcm.rs",
    "chars": 245,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/device_driver/common.rs",
    "chars": 1101,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/device_driver.rs",
    "chars": 289,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs",
    "chars": 518,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs",
    "chars": 2369,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi/kernel.ld",
    "chars": 2788,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs",
    "chars": 1168,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp/raspberrypi.rs",
    "chars": 644,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/bsp.rs",
    "chars": 349,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/console/null_console.rs",
    "chars": 1280,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2022-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/console.rs",
    "chars": 2446,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/cpu.rs",
    "chars": 571,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/driver.rs",
    "chars": 5213,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/main.rs",
    "chars": 6671,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/panic_wait.rs",
    "chars": 2025,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/print.rs",
    "chars": 976,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/src/synchronization.rs",
    "chars": 2725,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "05_drivers_gpio_uart/tests/boot_test_string.rb",
    "chars": 68,
    "preview": "# frozen_string_literal: true\n\nEXPECTED_PRINT = 'Echoing input now'\n"
  },
  {
    "path": "06_uart_chainloader/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "06_uart_chainloader/Cargo.toml",
    "chars": 773,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.6.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "06_uart_chainloader/Makefile",
    "chars": 9582,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "06_uart_chainloader/README.CN.md",
    "chars": 3063,
    "preview": "# 教程06 - UART链加载器\r\n\r\n## tl;dr\r\n\r\n- 从SD卡上运行是一次不错的体验,但是每次都为每个新的二进制文件这样做将非常繁琐。\r\n  因此,让我们编写一个[chainloader]。\r\n- 这将是您需要放在SD卡上的"
  },
  {
    "path": "06_uart_chainloader/README.md",
    "chars": 23560,
    "preview": "# Tutorial 06 - UART Chainloader\n\n## tl;dr\n\n- Running from an SD card was a nice experience, but it would be extremely t"
  },
  {
    "path": "06_uart_chainloader/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "06_uart_chainloader/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/_arch/aarch64/cpu/boot.s",
    "chars": 2544,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/_arch/aarch64/cpu.rs",
    "chars": 856,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs",
    "chars": 6715,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs",
    "chars": 13783,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/device_driver/bcm.rs",
    "chars": 245,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/device_driver/common.rs",
    "chars": 1101,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/device_driver.rs",
    "chars": 289,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/raspberrypi/driver.rs",
    "chars": 2369,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/raspberrypi/kernel.ld",
    "chars": 2946,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "06_uart_chainloader/src/bsp/raspberrypi/memory.rs",
    "chars": 1643,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp/raspberrypi.rs",
    "chars": 644,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/bsp.rs",
    "chars": 349,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/console/null_console.rs",
    "chars": 1280,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2022-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/console.rs",
    "chars": 2446,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/cpu.rs",
    "chars": 571,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/driver.rs",
    "chars": 4914,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/main.rs",
    "chars": 7592,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/panic_wait.rs",
    "chars": 2025,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/print.rs",
    "chars": 976,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/src/synchronization.rs",
    "chars": 2725,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "06_uart_chainloader/tests/chainboot_test.rb",
    "chars": 2479,
    "preview": "# frozen_string_literal: true\n\n# SPDX-License-Identifier: MIT OR Apache-2.0\n#\n# Copyright (c) 2020-2023 Andre Richter <a"
  },
  {
    "path": "06_uart_chainloader/update.sh",
    "chars": 202,
    "preview": "#!/usr/bin/env bash\n\ncd ../05_drivers_gpio_uart\nBSP=rpi4 make\ncp kernel8.img ../06_uart_chainloader/demo_payload_rpi4.im"
  },
  {
    "path": "07_timestamps/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "07_timestamps/Cargo.toml",
    "chars": 773,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.7.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "07_timestamps/Makefile",
    "chars": 9171,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "07_timestamps/README.CN.md",
    "chars": 1151,
    "preview": "# 教程 07 - 时间戳\n\n## tl;dr\n\n- 我们为计时器硬件添加了抽象,并在`_arch/aarch64`中实现了ARM架构计时器。\n- 新的计时器函数用于给UART打印添加时间戳,并且用于消除`GPIO`设备驱动中基于周期的延迟"
  },
  {
    "path": "07_timestamps/README.md",
    "chars": 33155,
    "preview": "# Tutorial 07 - Timestamps\n\n## tl;dr\n\n- We add abstractions for timer hardware, and implement them for the ARM architect"
  },
  {
    "path": "07_timestamps/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "07_timestamps/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/_arch/aarch64/cpu/boot.s",
    "chars": 2148,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/_arch/aarch64/cpu.rs",
    "chars": 700,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/_arch/aarch64/time.rs",
    "chars": 5694,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs",
    "chars": 6426,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs",
    "chars": 13925,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/device_driver/bcm.rs",
    "chars": 245,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/device_driver/common.rs",
    "chars": 1101,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/device_driver.rs",
    "chars": 289,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/raspberrypi/cpu.rs",
    "chars": 512,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/raspberrypi/driver.rs",
    "chars": 2879,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/raspberrypi/kernel.ld",
    "chars": 2788,
    "preview": "/* SPDX-License-Identifier: MIT OR Apache-2.0\n *\n * Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>\n *"
  },
  {
    "path": "07_timestamps/src/bsp/raspberrypi/memory.rs",
    "chars": 1168,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp/raspberrypi.rs",
    "chars": 644,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/bsp.rs",
    "chars": 349,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/console/null_console.rs",
    "chars": 1280,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2022-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/console.rs",
    "chars": 2446,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/cpu/boot.rs",
    "chars": 223,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/cpu.rs",
    "chars": 506,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/driver.rs",
    "chars": 5207,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/main.rs",
    "chars": 6785,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/panic_wait.rs",
    "chars": 2163,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/print.rs",
    "chars": 2334,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/synchronization.rs",
    "chars": 2725,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/src/time.rs",
    "chars": 1697,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "07_timestamps/tests/boot_test_string.rb",
    "chars": 72,
    "preview": "# frozen_string_literal: true\n\nEXPECTED_PRINT = 'Spinning for 1 second'\n"
  },
  {
    "path": "08_hw_debug_JTAG/.vscode/settings.json",
    "chars": 364,
    "preview": "{\n    \"editor.formatOnSave\": true,\n    \"editor.rulers\": [100],\n    \"rust-analyzer.cargo.target\": \"aarch64-unknown-none-s"
  },
  {
    "path": "08_hw_debug_JTAG/Cargo.toml",
    "chars": 773,
    "preview": "[package]\nname = \"mingo\"\nversion = \"0.8.0\"\nauthors = [\"Andre Richter <andre.o.richter@gmail.com>\"]\nedition = \"2021\"\n\n[pr"
  },
  {
    "path": "08_hw_debug_JTAG/Makefile",
    "chars": 11175,
    "preview": "## SPDX-License-Identifier: MIT OR Apache-2.0\n##\n## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>\n\ni"
  },
  {
    "path": "08_hw_debug_JTAG/README.CN.md",
    "chars": 7087,
    "preview": "# 教程 08 - 使用JTAG进行硬件调试\n\n## tl;dr\n\n按照以下顺序进行操作:\n\n1. 运行`make jtagboot`并保持终端打开。\n2. 连接USB串行设备。\n3. 连接`JTAG`调试器的USB设备。\n4. 在新的终端"
  },
  {
    "path": "08_hw_debug_JTAG/README.md",
    "chars": 15850,
    "preview": "# Tutorial 08 - Hardware Debugging using JTAG\n\n## tl;dr\n\nIn the exact order as listed:\n\n1. `make jtagboot` and keep term"
  },
  {
    "path": "08_hw_debug_JTAG/build.rs",
    "chars": 514,
    "preview": "use std::{env, fs, process};\n\nfn main() {\n    let ld_script_path = match env::var(\"LD_SCRIPT_PATH\") {\n        Ok(var) =>"
  },
  {
    "path": "08_hw_debug_JTAG/src/_arch/aarch64/cpu/boot.rs",
    "chars": 876,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2023 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  },
  {
    "path": "08_hw_debug_JTAG/src/_arch/aarch64/cpu/boot.s",
    "chars": 2148,
    "preview": "// SPDX-License-Identifier: MIT OR Apache-2.0\n//\n// Copyright (c) 2021-2022 Andre Richter <andre.o.richter@gmail.com>\n\n/"
  }
]

// ... and 975 more files (download for full content)

About this extraction

This page contains the full source code of the rust-embedded/rust-raspi3-tutorial GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1175 files (4.0 MB), approximately 1.1M tokens, and a symbol index with 6228 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!