From b94ba7759ecb7422cccfe9415dd8b8590e045d46 Mon Sep 17 00:00:00 2001 From: equation314 Date: Mon, 4 Mar 2019 15:22:19 +0800 Subject: [PATCH 1/8] add aarch64 bootloader framework --- .gitignore | 1 + bootloader/Cargo.lock | 6 +++ bootloader/Cargo.toml | 7 +++ bootloader/Makefile | 20 +++++++++ .../src/arch/aarch64}/boot.S | 11 ++--- bootloader/src/arch/aarch64/boot.ld | 45 +++++++++++++++++++ bootloader/src/arch/aarch64/mod.rs | 1 + bootloader/src/main.rs | 15 +++++++ bootloader/targets/aarch64.json | 36 +++++++++++++++ kernel/Cargo.toml | 2 +- kernel/Makefile | 45 ++++++++++++------- kernel/src/arch/aarch64/entry.S | 21 +++++++++ kernel/src/arch/aarch64/{boot => }/linker.ld | 6 --- kernel/src/arch/aarch64/mod.rs | 2 +- kernel/targets/aarch64.json | 2 +- 15 files changed, 188 insertions(+), 32 deletions(-) create mode 100644 bootloader/Cargo.lock create mode 100644 bootloader/Cargo.toml create mode 100644 bootloader/Makefile rename {kernel/src/arch/aarch64/boot => bootloader/src/arch/aarch64}/boot.S (97%) create mode 100644 bootloader/src/arch/aarch64/boot.ld create mode 100644 bootloader/src/arch/aarch64/mod.rs create mode 100644 bootloader/src/main.rs create mode 100644 bootloader/targets/aarch64.json create mode 100644 kernel/src/arch/aarch64/entry.S rename kernel/src/arch/aarch64/{boot => }/linker.ld (86%) diff --git a/.gitignore b/.gitignore index 975d0c4..446ff27 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ target Cargo.lock !kernel/Cargo.lock +!bootloader/Cargo.lock !user/Cargo.lock .DS_Store diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock new file mode 100644 index 0000000..505c019 --- /dev/null +++ b/bootloader/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rcore-bootloader" +version = "0.1.0" + diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml new file mode 100644 index 0000000..dde8976 --- /dev/null +++ b/bootloader/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rcore-bootloader" +version = "0.1.0" +authors = ["equation314 "] +edition = "2018" + +[dependencies] diff --git a/bootloader/Makefile b/bootloader/Makefile new file mode 100644 index 0000000..0545bbd --- /dev/null +++ b/bootloader/Makefile @@ -0,0 +1,20 @@ +arch ?= aarch64 +mode ?= debug +target := $(arch) + +bootloader := target/$(target)/$(mode)/rcore-bootloader + +build_args := --target=targets/$(arch).json +ifeq ($(mode), release) +build_args += --release +endif + +.PHONY: all clean + +all: $(bootloader) + +$(bootloader): + @cargo xbuild $(build_args) + +clean: + @cargo clean diff --git a/kernel/src/arch/aarch64/boot/boot.S b/bootloader/src/arch/aarch64/boot.S similarity index 97% rename from kernel/src/arch/aarch64/boot/boot.S rename to bootloader/src/arch/aarch64/boot.S index 7a126bd..4f66df3 100644 --- a/kernel/src/arch/aarch64/boot/boot.S +++ b/bootloader/src/arch/aarch64/boot.S @@ -1,8 +1,9 @@ # TODO rewrite in Rust, use crate cortex-a .section .text.boot +.globl _start -boot: +_start: # read cpu affinity, start core 0, halt rest mrs x1, mpidr_el1 and x1, x1, #3 @@ -104,11 +105,7 @@ zero_bss_loop: cbnz x2, zero_bss_loop zero_bss_loop_end: - b _start - -.section .text.entry -.globl _start -_start: # jump to rust_main, which shouldn't return. halt if it does - bl rust_main + mov x9, #0x100000 + blr x9 b halt diff --git a/bootloader/src/arch/aarch64/boot.ld b/bootloader/src/arch/aarch64/boot.ld new file mode 100644 index 0000000..57e2c4b --- /dev/null +++ b/bootloader/src/arch/aarch64/boot.ld @@ -0,0 +1,45 @@ +ENTRY(_start) + +SECTIONS { + . = 0x80000; /* Raspbery Pi 3 AArch64 (kernel8.img) load address */ + + .text : { + stext = .; + KEEP(*(.text.boot)) /* from boot.S */ + *(.text .text.* .gnu.linkonce.t*) + . = ALIGN(4K); + etext = .; + } + + .rodata : { + srodata = .; + *(.rodata .rodata.* .gnu.linkonce.r*) + . = ALIGN(4K); + erodata = .; + } + + .data : { + sdata = .; + *(.data .data.* .gnu.linkonce.d*) + . = ALIGN(4K); + edata = .; + } + + .bss (NOLOAD) : { + . = ALIGN(32); + sbss = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4K); + ebss = .; + } + + /* end of the binary */ + _end = ALIGN(8); + + /* number of bytes in BSS section and complete binary */ + __bss_length = (ebss - sbss); + __binary_length = (_end - _start); + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs new file mode 100644 index 0000000..8ffaf76 --- /dev/null +++ b/bootloader/src/arch/aarch64/mod.rs @@ -0,0 +1 @@ +global_asm!(include_str!("boot.S")); diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs new file mode 100644 index 0000000..46acd38 --- /dev/null +++ b/bootloader/src/main.rs @@ -0,0 +1,15 @@ +#![no_std] +#![no_main] +#![feature(global_asm)] + +use core::panic::PanicInfo; + +#[panic_handler] +#[no_mangle] +pub extern "C" fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +#[cfg(target_arch = "aarch64")] +#[path = "arch/aarch64/mod.rs"] +pub mod arch; diff --git a/bootloader/targets/aarch64.json b/bootloader/targets/aarch64.json new file mode 100644 index 0000000..4a59d7f --- /dev/null +++ b/bootloader/targets/aarch64.json @@ -0,0 +1,36 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "win64", + "sysv64" + ], + "arch": "aarch64", + "data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", + "executables": true, + "linker": "rust-lld", + "linker-flavor": "ld.lld", + "linker-is-gnu": true, + "pre-link-args": { + "ld.lld": [ + "-Tsrc/arch/aarch64/boot.ld" + ] + }, + "llvm-target": "aarch64-unknown-none", + "no-compiler-rt": true, + "features": "+a53,+strict-align,-neon", + "max-atomic-width": 128, + "os": "none", + "panic": "abort", + "panic-strategy": "abort", + "relocation-model": "static", + "position-independent-executables": true, + "target-c-int-width": "32", + "target-endian": "little", + "target-pointer-width": "64", + "target-family": "unix", + "disable-redzone": true, + "eliminate-frame-pointer": false +} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index b8b5d68..2619130 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -27,9 +27,9 @@ board_u540 = ["sv39"] # (for aarch64 RaspberryPi3) nographic = [] board_raspi3 = ["bcm2837", "link_user"] +raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] # (for riscv64) board_k210 = ["m_mode"] -raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] # Hard link user program link_user = [] diff --git a/kernel/Makefile b/kernel/Makefile index 685f362..14963de 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -32,8 +32,12 @@ m_mode ?= target := $(arch) kernel := target/$(target)/$(mode)/rcore -bin := target/$(target)/$(mode)/kernel.bin +boot_bin := target/$(target)/$(mode)/boot.bin +kernel_bin := target/$(target)/$(mode)/kernel.bin +kernel_img := target/$(target)/$(mode)/kernel.img bootimage := target/$(target)/bootimage.bin +bootloader_dir = ../bootloader +bootloader := $(bootloader_dir)/target/$(target)/$(mode)/rcore-bootloader bbl_path := $(PWD)/../riscv-pk user_dir := ../user k210_lib := ../tools/k210/libkendryte.a @@ -53,9 +57,7 @@ endif export M_MODE = $(m_mode) ifeq ($(arch), aarch64) -graphic ?= on -else -graphic ?= off +graphic := on endif ### qemu options ### @@ -76,7 +78,7 @@ qemu_net_opts += \ else ifeq ($(arch), riscv32) qemu_opts += \ -machine virt \ - -kernel $(bin) \ + -kernel $(kernel_img) \ -drive file=$(SFSIMG),format=raw,id=sfs \ -device virtio-blk-device,drive=sfs qemu_net_opts += \ @@ -89,7 +91,7 @@ endif else ifeq ($(arch), riscv64) qemu_opts += \ -machine virt \ - -kernel $(bin) \ + -kernel $(kernel_img) \ -drive file=$(SFSIMG),format=raw,id=sfs \ -device virtio-blk-device,drive=sfs qemu_net_opts += \ @@ -103,7 +105,7 @@ else ifeq ($(arch), aarch64) qemu_opts += \ -machine $(board) \ -serial null -serial mon:stdio \ - -kernel $(bin) + -kernel $(kernel_img) endif ifdef d @@ -170,7 +172,7 @@ objdump := $(prefix)objdump objcopy := $(prefix)objcopy cc := $(prefix)gcc as := $(prefix)as -gdb := gdb +gdb := $(prefix)gdb export CC=$(cc) .PHONY: all clean run build asm doc justrun debug kernel sfsimg install runnet @@ -179,6 +181,7 @@ all: kernel clean: @cargo clean + @cd $(bootloader_dir) && make clean @cd $(user_dir) && make clean doc: @@ -199,12 +202,12 @@ justrunui: build -device virtio-gpu-device \ -device virtio-mouse-device -debug: $(kernel) $(bin) +debug: $(kernel) $(kernel_img) @qemu-system-$(arch) $(qemu_opts) -s -S & @sleep 1 @$(gdb) $(kernel) -x ../tools/gdbinit -build: $(bin) +build: $(kernel_img) asm: @$(objdump) -dS $(kernel) | less @@ -215,7 +218,13 @@ header: sym: @$(objdump) -t $(kernel) | less -$(bin): kernel +$(bootloader): +ifeq ($(arch), aarch64) + @echo Building $(arch) bootloader + cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) +endif + +$(kernel_img): $(bootloader) kernel ifeq ($(arch), riscv32) @mkdir -p target/$(target)/bbl && \ cd target/$(target)/bbl && \ @@ -243,10 +252,14 @@ else cp bbl $(abspath $@) endif else ifeq ($(arch), aarch64) - @$(objcopy) $(kernel) --strip-all -O binary $@ + @$(objcopy) $(bootloader) --strip-all -O binary $(boot_bin) + @$(objcopy) $(kernel) --strip-all -O binary $(kernel_bin) + dd if=$(boot_bin) of=$@ conv=notrunc + dd if=$(kernel_bin) of=$@ seek=1024 conv=notrunc endif kernel: + @echo Building $(arch) kernel ifeq ($(arch), x86_64) @bootimage build $(build_args) else ifeq ($(arch), riscv32) @@ -287,8 +300,8 @@ endif ifdef sd_card .PHONY: -install: $(bin) - cp $(bin) $(sd_card)/kernel8.img +install: $(kernel_img) + cp $(kernel_img) $(sd_card)/kernel8.img sudo umount $(sd_card) endif @@ -296,9 +309,9 @@ endif ifeq ($(board), k210) .PHONY: -install: $(bin) +install: $(kernel_img) ## baudrate no more than 600000 - @python3 ../tools/k210/kflash.py $(bin) -b 600000 + @python3 ../tools/k210/kflash.py $(kernel_img) -b 600000 endif .PHONY: diff --git a/kernel/src/arch/aarch64/entry.S b/kernel/src/arch/aarch64/entry.S new file mode 100644 index 0000000..4f7c40b --- /dev/null +++ b/kernel/src/arch/aarch64/entry.S @@ -0,0 +1,21 @@ +.section .text.entry +.globl _start + +_start: + ldr x0, =bootstacktop + mov sp, x0 + +zero_bss: + # load the start address and number of bytes in BSS section + ldr x1, =sbss + ldr x2, =__bss_length + +zero_bss_loop: + # zero out the BSS section, 64-bits at a time + cbz x2, zero_bss_loop_end + str xzr, [x1], #8 + sub x2, x2, #8 + cbnz x2, zero_bss_loop + +zero_bss_loop_end: + bl rust_main diff --git a/kernel/src/arch/aarch64/boot/linker.ld b/kernel/src/arch/aarch64/linker.ld similarity index 86% rename from kernel/src/arch/aarch64/boot/linker.ld rename to kernel/src/arch/aarch64/linker.ld index 38dbba9..ef4c7dd 100644 --- a/kernel/src/arch/aarch64/boot/linker.ld +++ b/kernel/src/arch/aarch64/linker.ld @@ -1,12 +1,6 @@ ENTRY(_start) SECTIONS { - . = 0x80000; /* Raspbery Pi 3 AArch64 (kernel8.img) load address */ - - .boot : { - KEEP(*(.text.boot)) /* from boot.S */ - } - . = 0x100000; /* Load the kernel at this address. It's also kernel stack top address */ bootstacktop = .; diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index ecfc34d..4346ed3 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -12,7 +12,7 @@ pub mod driver; #[path = "board/raspi3/mod.rs"] pub mod board; -global_asm!(include_str!("boot/boot.S")); +global_asm!(include_str!("entry.S")); /// The entry point of kernel #[no_mangle] // don't mangle the name of this function diff --git a/kernel/targets/aarch64.json b/kernel/targets/aarch64.json index 149246a..02cbe21 100644 --- a/kernel/targets/aarch64.json +++ b/kernel/targets/aarch64.json @@ -15,7 +15,7 @@ "linker-is-gnu": true, "pre-link-args": { "ld.lld": [ - "-Tsrc/arch/aarch64/boot/linker.ld" + "-Tsrc/arch/aarch64/linker.ld" ] }, "llvm-target": "aarch64-unknown-none", From 8bb1e65ba706f2cbb09e30de4ed22c29c920982c Mon Sep 17 00:00:00 2001 From: equation314 Date: Wed, 6 Mar 2019 00:46:01 +0800 Subject: [PATCH 2/8] load kernel elf in bootloader --- bootloader/Cargo.lock | 213 +++++++++++++++++++ bootloader/Cargo.toml | 8 + bootloader/Makefile | 31 ++- bootloader/build.rs | 40 ++++ bootloader/src/arch/aarch64/boot.S | 20 +- bootloader/src/arch/aarch64/boot.ld | 24 +-- bootloader/src/arch/aarch64/mod.rs | 23 ++ bootloader/src/lang_items.rs | 7 + bootloader/src/main.rs | 54 ++++- kernel/Makefile | 18 +- kernel/build.rs | 138 ++++++------ kernel/src/arch/aarch64/{ => boot}/entry.S | 0 kernel/src/arch/aarch64/{ => boot}/linker.ld | 2 +- kernel/src/arch/aarch64/memory.rs | 1 + kernel/src/arch/aarch64/mod.rs | 2 +- kernel/targets/aarch64.json | 2 +- 16 files changed, 452 insertions(+), 131 deletions(-) create mode 100644 bootloader/build.rs create mode 100644 bootloader/src/lang_items.rs rename kernel/src/arch/aarch64/{ => boot}/entry.S (100%) rename kernel/src/arch/aarch64/{ => boot}/linker.ld (89%) diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index 505c019..42d8ed0 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -1,6 +1,219 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aarch64" +version = "2.2.2" +source = "git+https://github.com/equation314/aarch64#b6a0f4a3be6f74927c88305a6af5ad2be079bccd" +dependencies = [ + "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bit_field" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fixedvec" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "skeptic 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "getopts" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pulldown-cmark" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rcore-bootloader" version = "0.1.0" +dependencies = [ + "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "skeptic" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tock-registers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "usize_conversions" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ux" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "xmas-elf" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zero" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +[metadata] +"checksum aarch64 2.2.2 (git+https://github.com/equation314/aarch64)" = "" +"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum register 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e10f31b6d2299e5620986ad9fcdd66463e125ad72af4f403f9aedf7592d5ccdb" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum skeptic 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "061203a849117b0f7090baf8157aa91dac30545208fbb85166ac58b4ca33d89c" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tock-registers 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a385d94f3f62e60445a0adb9ff8d9621faa272234530d4c0f848ec98f88e316" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" +"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58" +"checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml index dde8976..5a77dff 100644 --- a/bootloader/Cargo.toml +++ b/bootloader/Cargo.toml @@ -5,3 +5,11 @@ authors = ["equation314 "] edition = "2018" [dependencies] +xmas-elf = "0.6.2" +fixedvec = "0.2.3" + +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64 = { git = "https://github.com/equation314/aarch64" } + +[build-dependencies] +cc = "1.0" diff --git a/bootloader/Makefile b/bootloader/Makefile index 0545bbd..e675023 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -1,9 +1,36 @@ arch ?= aarch64 mode ?= debug target := $(arch) +payload ?= bootloader := target/$(target)/$(mode)/rcore-bootloader +ifeq ($(arch), x86_64) +ifeq ($(uname), Darwin) +prefix := x86_64-elf- +endif +else ifeq ($(arch), riscv32) +prefix := riscv64-unknown-elf- +else ifeq ($(arch), riscv64) +prefix := riscv64-unknown-elf- +else ifeq ($(arch), aarch64) +prefix ?= aarch64-none-elf- +ifeq (,$(shell which $(prefix)ld)) + prefix := aarch64-elf- +endif +endif + +ld := $(prefix)ld +objdump := $(prefix)objdump +objcopy := $(prefix)objcopy +cc := $(prefix)gcc +as := $(prefix)as +gdb := $(prefix)gdb +strip := $(prefix)strip + +export CC = $(cc) +export PAYLOAD = $(payload) + build_args := --target=targets/$(arch).json ifeq ($(mode), release) build_args += --release @@ -11,9 +38,9 @@ endif .PHONY: all clean -all: $(bootloader) +all: bootloader -$(bootloader): +bootloader: $(payload) @cargo xbuild $(build_args) clean: diff --git a/bootloader/build.rs b/bootloader/build.rs new file mode 100644 index 0000000..b4e87e8 --- /dev/null +++ b/bootloader/build.rs @@ -0,0 +1,40 @@ +extern crate cc; + +use std::fs::File; +use std::io::{Result, Write}; +use std::path::Path; + +fn main() { + if let Ok(file_path) = gen_payload_asm() { + cc::Build::new().file(&file_path).compile("payload"); + } +} + +fn gen_payload_asm() -> Result { + let out_dir = std::env::var("OUT_DIR").unwrap(); + let payload = std::env::var("PAYLOAD").unwrap(); + + if !Path::new(&payload).is_file() { + panic!("Kernel payload `{}` not found", payload) + } + + let file_path = Path::new(&out_dir).join("payload.S"); + let mut f = File::create(&file_path).unwrap(); + + println!("{:x?} {:x?}", payload, file_path); + + write!(f, "# generated by build.rs - do not edit")?; + write!(f, r#" + .section .rodata + .align 12 + .global _kernel_payload_start, _kernel_payload_end +_kernel_payload_start: + .incbin "{}" +_kernel_payload_end: +"#, payload)?; + + println!("cargo:rerun-if-changed={}", payload); + println!("cargo:rerun-if-env-changed=PAYLOAD"); + + Ok(file_path) +} diff --git a/bootloader/src/arch/aarch64/boot.S b/bootloader/src/arch/aarch64/boot.S index 4f66df3..dc393c7 100644 --- a/bootloader/src/arch/aarch64/boot.S +++ b/bootloader/src/arch/aarch64/boot.S @@ -1,5 +1,3 @@ -# TODO rewrite in Rust, use crate cortex-a - .section .text.boot .globl _start @@ -92,20 +90,6 @@ set_stack: # set the current stack pointer mov sp, x1 -zero_bss: - # load the start address and number of bytes in BSS section - ldr x1, =sbss - ldr x2, =__bss_length - -zero_bss_loop: - # zero out the BSS section, 64-bits at a time - cbz x2, zero_bss_loop_end - str xzr, [x1], #8 - sub x2, x2, #8 - cbnz x2, zero_bss_loop - -zero_bss_loop_end: - # jump to rust_main, which shouldn't return. halt if it does - mov x9, #0x100000 - blr x9 +goto_main: + bl boot_main b halt diff --git a/bootloader/src/arch/aarch64/boot.ld b/bootloader/src/arch/aarch64/boot.ld index 57e2c4b..7c9b8cb 100644 --- a/bootloader/src/arch/aarch64/boot.ld +++ b/bootloader/src/arch/aarch64/boot.ld @@ -4,42 +4,20 @@ SECTIONS { . = 0x80000; /* Raspbery Pi 3 AArch64 (kernel8.img) load address */ .text : { - stext = .; KEEP(*(.text.boot)) /* from boot.S */ *(.text .text.* .gnu.linkonce.t*) . = ALIGN(4K); - etext = .; } .rodata : { - srodata = .; *(.rodata .rodata.* .gnu.linkonce.r*) . = ALIGN(4K); - erodata = .; } - .data : { - sdata = .; + .data : {= *(.data .data.* .gnu.linkonce.d*) . = ALIGN(4K); - edata = .; } - .bss (NOLOAD) : { - . = ALIGN(32); - sbss = .; - *(.bss .bss.*) - *(COMMON) - . = ALIGN(4K); - ebss = .; - } - - /* end of the binary */ - _end = ALIGN(8); - - /* number of bytes in BSS section and complete binary */ - __bss_length = (ebss - sbss); - __binary_length = (_end - _start); - /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } } diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index 8ffaf76..6eafc58 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -1 +1,24 @@ +use core::slice; +use fixedvec::FixedVec; +use xmas_elf::program::{ProgramHeader64, Type}; + global_asm!(include_str!("boot.S")); + +pub fn map_kernel(kernel_start: u64, segments: &FixedVec) { + for segment in segments { + if segment.get_type() != Ok(Type::Load) { + continue; + } + let virt_addr = segment.virtual_addr; + let offset = segment.offset; + let file_size = segment.file_size as usize; + let mem_size = segment.mem_size as usize; + + unsafe { + let target = slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size); + let source = slice::from_raw_parts((kernel_start + offset) as *const u8, file_size); + target.copy_from_slice(source); + target[file_size..].iter_mut().for_each(|x| *x = 0); + } + } +} diff --git a/bootloader/src/lang_items.rs b/bootloader/src/lang_items.rs new file mode 100644 index 0000000..52e5deb --- /dev/null +++ b/bootloader/src/lang_items.rs @@ -0,0 +1,7 @@ +use core::panic::PanicInfo; + +#[panic_handler] +#[no_mangle] +pub extern "C" fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 46acd38..2c80a39 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -1,15 +1,57 @@ #![no_std] #![no_main] +#![feature(lang_items)] #![feature(global_asm)] -use core::panic::PanicInfo; +#[macro_use] +extern crate fixedvec; +extern crate xmas_elf; -#[panic_handler] -#[no_mangle] -pub extern "C" fn panic(_info: &PanicInfo) -> ! { - loop {} -} +use core::mem::transmute; +use core::slice; +use fixedvec::FixedVec; +use xmas_elf::{ + header, + program::{ProgramHeader, ProgramHeader64}, + ElfFile, +}; #[cfg(target_arch = "aarch64")] #[path = "arch/aarch64/mod.rs"] pub mod arch; +pub mod lang_items; + +extern "C" { + fn _kernel_payload_start(); + fn _kernel_payload_end(); +} + +/// The entry point of bootloader +#[no_mangle] // don't mangle the name of this function +pub extern "C" fn boot_main() -> ! { + let kernel_size = _kernel_payload_end as usize - _kernel_payload_start as usize; + let kernel = unsafe { slice::from_raw_parts(_kernel_payload_start as *const u8, kernel_size) }; + let kernel_elf = ElfFile::new(kernel).unwrap(); + header::sanity_check(&kernel_elf).unwrap(); + + let mut preallocated_space = alloc_stack!([ProgramHeader64; 32]); + let mut segments = FixedVec::new(&mut preallocated_space); + + for program_header in kernel_elf.program_iter() { + match program_header { + ProgramHeader::Ph64(header) => segments + .push(*header) + .expect("does not support more than 32 program segments"), + ProgramHeader::Ph32(_) => panic!("does not support 32 bit elf files"), + } + } + + arch::map_kernel(_kernel_payload_start as u64, &segments); + + let entry = kernel_elf.header.pt2.entry_point(); + let kernel_main: extern "C" fn() = unsafe { transmute(entry) }; + + kernel_main(); + + loop {} +} diff --git a/kernel/Makefile b/kernel/Makefile index 14963de..0c2a118 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -32,8 +32,6 @@ m_mode ?= target := $(arch) kernel := target/$(target)/$(mode)/rcore -boot_bin := target/$(target)/$(mode)/boot.bin -kernel_bin := target/$(target)/$(mode)/kernel.bin kernel_img := target/$(target)/$(mode)/kernel.img bootimage := target/$(target)/bootimage.bin bootloader_dir = ../bootloader @@ -173,7 +171,8 @@ objcopy := $(prefix)objcopy cc := $(prefix)gcc as := $(prefix)as gdb := $(prefix)gdb -export CC=$(cc) +strip := $(prefix)strip +export CC = $(cc) .PHONY: all clean run build asm doc justrun debug kernel sfsimg install runnet @@ -218,13 +217,15 @@ header: sym: @$(objdump) -t $(kernel) | less -$(bootloader): +$(bootloader): $(kernel) ifeq ($(arch), aarch64) @echo Building $(arch) bootloader - cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) + @$(strip) $(kernel) -o $(kernel)_stripped + @cd $(bootloader_dir) && make arch=$(arch) mode=$(mode) payload=../kernel/$(kernel)_stripped + @rm $(kernel)_stripped endif -$(kernel_img): $(bootloader) kernel +$(kernel_img): kernel $(bootloader) ifeq ($(arch), riscv32) @mkdir -p target/$(target)/bbl && \ cd target/$(target)/bbl && \ @@ -252,10 +253,7 @@ else cp bbl $(abspath $@) endif else ifeq ($(arch), aarch64) - @$(objcopy) $(bootloader) --strip-all -O binary $(boot_bin) - @$(objcopy) $(kernel) --strip-all -O binary $(kernel_bin) - dd if=$(boot_bin) of=$@ conv=notrunc - dd if=$(kernel_bin) of=$@ seek=1024 conv=notrunc + @$(objcopy) $(bootloader) --strip-all -O binary $@ endif kernel: diff --git a/kernel/build.rs b/kernel/build.rs index 7573489..fd3864b 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -5,90 +5,90 @@ use std::path::Path; use std::io::{Result, Write}; fn main() { - println!("cargo:rerun-if-env-changed=LOG"); - println!("cargo:rerun-if-env-changed=BOARD"); + println!("cargo:rerun-if-env-changed=LOG"); + println!("cargo:rerun-if-env-changed=BOARD"); - let arch: String = std::env::var("ARCH").unwrap(); - let board: String = std::env::var("BOARD").unwrap(); - match arch.as_str() { - "x86_64" => { - gen_vector_asm().unwrap(); - } - "riscv32" => { - if let Ok(file_path) = gen_sfsimg_asm() { - cc::Build::new() - .file(&file_path) - .flag("-march=rv32imac") - .flag("-mabi=ilp32") - .compile("sfsimg"); - } - } - "riscv64" => { - if let Ok(file_path) = gen_sfsimg_asm() { - cc::Build::new() - .file(&file_path) - .flag("-march=rv64imac") - .flag("-mabi=lp64") - .compile("sfsimg"); - } - if board == "k210" { - println!("cargo:rustc-link-search=native={}", "../tools/k210"); - println!("cargo:rustc-link-lib=static=kendryte"); - } - } - "aarch64" => { - if let Ok(file_path) = gen_sfsimg_asm() { - cc::Build::new().file(&file_path).compile("sfsimg"); - } - } - _ => panic!("Unknown arch {}", arch), - } + let arch: String = std::env::var("ARCH").unwrap(); + let board: String = std::env::var("BOARD").unwrap(); + match arch.as_str() { + "x86_64" => { + gen_vector_asm().unwrap(); + } + "riscv32" => { + if let Ok(file_path) = gen_sfsimg_asm() { + cc::Build::new() + .file(&file_path) + .flag("-march=rv32imac") + .flag("-mabi=ilp32") + .compile("sfsimg"); + } + } + "riscv64" => { + if let Ok(file_path) = gen_sfsimg_asm() { + cc::Build::new() + .file(&file_path) + .flag("-march=rv64imac") + .flag("-mabi=lp64") + .compile("sfsimg"); + } + if board == "k210" { + println!("cargo:rustc-link-search=native={}", "../tools/k210"); + println!("cargo:rustc-link-lib=static=kendryte"); + } + } + "aarch64" => { + if let Ok(file_path) = gen_sfsimg_asm() { + cc::Build::new().file(&file_path).compile("sfsimg"); + } + } + _ => panic!("Unknown arch {}", arch), + } } fn gen_vector_asm() -> Result<()> { - let mut f = File::create("src/arch/x86_64/interrupt/vector.asm").unwrap(); + let mut f = File::create("src/arch/x86_64/interrupt/vector.asm").unwrap(); - writeln!(f, "# generated by build.rs - do not edit")?; - writeln!(f, ".section .text")?; - writeln!(f, ".intel_syntax noprefix")?; - for i in 0..256 { - writeln!(f, "vector{}:", i)?; - if !(i == 8 || (i >= 10 && i <= 14) || i == 17) { - writeln!(f, "\tpush 0")?; - } - writeln!(f, "\tpush {}", i)?; - writeln!(f, "\tjmp __alltraps")?; - } + writeln!(f, "# generated by build.rs - do not edit")?; + writeln!(f, ".section .text")?; + writeln!(f, ".intel_syntax noprefix")?; + for i in 0..256 { + writeln!(f, "vector{}:", i)?; + if !(i == 8 || (i >= 10 && i <= 14) || i == 17) { + writeln!(f, "\tpush 0")?; + } + writeln!(f, "\tpush {}", i)?; + writeln!(f, "\tjmp __alltraps")?; + } - writeln!(f, "\n.section .rodata")?; - writeln!(f, ".global __vectors")?; - writeln!(f, "__vectors:")?; - for i in 0..256 { - writeln!(f, "\t.quad vector{}", i)?; - } - Ok(()) + writeln!(f, "\n.section .rodata")?; + writeln!(f, ".global __vectors")?; + writeln!(f, "__vectors:")?; + for i in 0..256 { + writeln!(f, "\t.quad vector{}", i)?; + } + Ok(()) } fn gen_sfsimg_asm() -> Result { - let out_dir = std::env::var("OUT_DIR").unwrap(); - let sfsimg = std::env::var("SFSIMG").unwrap(); + let out_dir = std::env::var("OUT_DIR").unwrap(); + let sfsimg = std::env::var("SFSIMG").unwrap(); - let file_path = Path::new(&out_dir).join("sfsimg.S"); - let mut f = File::create(&file_path).unwrap(); + let file_path = Path::new(&out_dir).join("sfsimg.S"); + let mut f = File::create(&file_path).unwrap(); - write!(f, "# generated by build.rs - do not edit")?; - write!(f, r#" - .section .rodata - .align 12 - .global _user_img_start - .global _user_img_end + write!(f, "# generated by build.rs - do not edit")?; + write!(f, r#" + .section .rodata + .align 12 + .global _user_img_start + .global _user_img_end _user_img_start: .incbin "{}" _user_img_end: "#, sfsimg)?; - println!("cargo:rerun-if-changed={}", sfsimg); - println!("cargo:rerun-if-env-changed=SFSIMG"); + println!("cargo:rerun-if-changed={}", sfsimg); + println!("cargo:rerun-if-env-changed=SFSIMG"); - Ok(file_path) + Ok(file_path) } diff --git a/kernel/src/arch/aarch64/entry.S b/kernel/src/arch/aarch64/boot/entry.S similarity index 100% rename from kernel/src/arch/aarch64/entry.S rename to kernel/src/arch/aarch64/boot/entry.S diff --git a/kernel/src/arch/aarch64/linker.ld b/kernel/src/arch/aarch64/boot/linker.ld similarity index 89% rename from kernel/src/arch/aarch64/linker.ld rename to kernel/src/arch/aarch64/boot/linker.ld index ef4c7dd..399f3fa 100644 --- a/kernel/src/arch/aarch64/linker.ld +++ b/kernel/src/arch/aarch64/boot/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x100000; /* Load the kernel at this address. It's also kernel stack top address */ + . = 0x2000000; /* Load the kernel at this address. It's also kernel stack top address */ bootstacktop = .; .text : { diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index f4b7cc0..c2a1b87 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -112,6 +112,7 @@ fn remap_the_kernel() { use super::board::{IO_REMAP_BASE, IO_REMAP_END}; ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(0, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); + info!("{:#x?}", ms); unsafe { ms.get_page_table_mut().activate_as_kernel() } unsafe { KERNEL_MEMORY_SET = Some(ms) } info!("kernel remap end"); diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 4346ed3..370e1c0 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -12,7 +12,7 @@ pub mod driver; #[path = "board/raspi3/mod.rs"] pub mod board; -global_asm!(include_str!("entry.S")); +global_asm!(include_str!("boot/entry.S")); /// The entry point of kernel #[no_mangle] // don't mangle the name of this function diff --git a/kernel/targets/aarch64.json b/kernel/targets/aarch64.json index 02cbe21..149246a 100644 --- a/kernel/targets/aarch64.json +++ b/kernel/targets/aarch64.json @@ -15,7 +15,7 @@ "linker-is-gnu": true, "pre-link-args": { "ld.lld": [ - "-Tsrc/arch/aarch64/linker.ld" + "-Tsrc/arch/aarch64/boot/linker.ld" ] }, "llvm-target": "aarch64-unknown-none", From 0e38439fb867ed7a678143c77877e540f4e57956 Mon Sep 17 00:00:00 2001 From: equation314 Date: Thu, 7 Mar 2019 23:25:26 +0800 Subject: [PATCH 3/8] aarch64: enable MMU in bootloader --- bootloader/Cargo.lock | 2 +- bootloader/src/arch/aarch64/boot.S | 14 ++- bootloader/src/arch/aarch64/boot.ld | 10 +- bootloader/src/arch/aarch64/mod.rs | 122 +++++++++++++++++++++++-- bootloader/src/main.rs | 3 +- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/boot/entry.S | 14 --- kernel/src/arch/aarch64/boot/linker.ld | 4 +- kernel/src/arch/aarch64/memory.rs | 59 +----------- kernel/src/arch/aarch64/mod.rs | 1 - kernel/src/arch/aarch64/paging.rs | 42 +-------- 11 files changed, 147 insertions(+), 126 deletions(-) diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index 42d8ed0..80bde96 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#b6a0f4a3be6f74927c88305a6af5ad2be079bccd" +source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/bootloader/src/arch/aarch64/boot.S b/bootloader/src/arch/aarch64/boot.S index dc393c7..e5fabd2 100644 --- a/bootloader/src/arch/aarch64/boot.S +++ b/bootloader/src/arch/aarch64/boot.S @@ -90,6 +90,18 @@ set_stack: # set the current stack pointer mov sp, x1 -goto_main: +zero_bss: + # load the start address and number of bytes in BSS section + ldr x1, =_sbss + ldr x2, =_ebss + +zero_bss_loop: + # zero out the BSS section, 64-bits at a time + cmp x1, x2 + b.ge zero_bss_loop_end + str xzr, [x1], #8 + b zero_bss_loop + +zero_bss_loop_end: bl boot_main b halt diff --git a/bootloader/src/arch/aarch64/boot.ld b/bootloader/src/arch/aarch64/boot.ld index 7c9b8cb..20c42ab 100644 --- a/bootloader/src/arch/aarch64/boot.ld +++ b/bootloader/src/arch/aarch64/boot.ld @@ -14,10 +14,18 @@ SECTIONS { . = ALIGN(4K); } - .data : {= + .data : { *(.data .data.* .gnu.linkonce.d*) . = ALIGN(4K); } + .bss : { + _sbss = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4K); + _ebss = .; + } + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } } diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index 6eafc58..e7cb408 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -1,24 +1,130 @@ -use core::slice; +use aarch64::addr::{VirtAddr, PhysAddr}; +use aarch64::paging::{memory_attribute::*, Page, PageTable, PageTableFlags as EF, PhysFrame}; +use aarch64::paging::{Size4KiB, Size2MiB, Size1GiB}; +use aarch64::{asm::*, barrier, regs::*}; +use core::ptr; use fixedvec::FixedVec; use xmas_elf::program::{ProgramHeader64, Type}; +const PAGE_SIZE: usize = 4096; +const ALIGN_2MB: u64 = 0x200000; + +const IO_REMAP_BASE: u64 = 0x3F00_0000; +const MEMORY_END: u64 = 0x4000_0000; + +const RECURSIVE_INDEX: usize = 0o777; +const KERNEL_OFFSET: u64 = 0x0000_0000_0000_0000; + global_asm!(include_str!("boot.S")); -pub fn map_kernel(kernel_start: u64, segments: &FixedVec) { +fn setup_temp_page_table(start_vaddr: VirtAddr, end_vaddr: VirtAddr, offset: u64) { + #[repr(align(4096))] + struct PageData([u8; PAGE_SIZE]); + static mut PAGE_TABLE_LVL4: PageData = PageData([0; PAGE_SIZE]); + static mut PAGE_TABLE_LVL3: PageData = PageData([0; PAGE_SIZE]); + static mut PAGE_TABLE_LVL2: PageData = PageData([0; PAGE_SIZE]); + + let frame_lvl4 = unsafe { PhysFrame::::containing_address(PhysAddr::new(&PAGE_TABLE_LVL4 as *const _ as u64)) }; + let frame_lvl3 = unsafe { PhysFrame::::containing_address(PhysAddr::new(&PAGE_TABLE_LVL3 as *const _ as u64)) }; + let frame_lvl2 = unsafe { PhysFrame::::containing_address(PhysAddr::new(&PAGE_TABLE_LVL2 as *const _ as u64)) }; + let p4 = unsafe { &mut *(frame_lvl4.start_address().as_u64() as *mut PageTable) }; + let p3 = unsafe { &mut *(frame_lvl3.start_address().as_u64() as *mut PageTable) }; + let p2 = unsafe { &mut *(frame_lvl2.start_address().as_u64() as *mut PageTable) }; + p4.zero(); + p3.zero(); + p2.zero(); + + let block_flags = EF::VALID | EF::AF | EF::WRITE | EF::UXN; + // normal memory + for page in Page::::range_of(start_vaddr.as_u64(), end_vaddr.as_u64()) { + let paddr = PhysAddr::new(page.start_address().as_u64().wrapping_add(offset)); + p2[page.p2_index()].set_block::(paddr, block_flags, MairNormal::attr_value()); + } + // device memory + for page in Page::::range_of(IO_REMAP_BASE, MEMORY_END) { + let paddr = PhysAddr::new(page.start_address().as_u64()); + p2[page.p2_index()].set_block::(paddr, block_flags | EF::PXN, MairDevice::attr_value()); + } + + p3[0].set_frame(frame_lvl2, EF::default(), MairNormal::attr_value()); + p3[1].set_block::(PhysAddr::new(MEMORY_END), block_flags | EF::PXN, MairDevice::attr_value()); + + p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value()); + p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value()); + + ttbr_el1_write(VirtAddr::new(KERNEL_OFFSET).va_range().unwrap() as u8, frame_lvl4); + tlb_invalidate_all(); +} + +fn enable_mmu() { + MAIR_EL1.write( + MAIR_EL1::Attr0.val(MairNormal::config_value()) + + MAIR_EL1::Attr1.val(MairDevice::config_value()) + + MAIR_EL1::Attr2.val(MairNormalNonCacheable::config_value()), + ); + + // Configure various settings of stage 1 of the EL1 translation regime. + let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); + TCR_EL1.write( + TCR_EL1::TBI1::Ignored + + TCR_EL1::TBI0::Ignored + + TCR_EL1::AS::Bits_16 + + TCR_EL1::IPS.val(ips) + + + TCR_EL1::TG1::KiB_4 + + TCR_EL1::SH1::Inner + + TCR_EL1::ORGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::IRGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::EPD1::EnableTTBR1Walks + + TCR_EL1::A1::UseTTBR1ASID + + TCR_EL1::T1SZ.val(16) + + + TCR_EL1::TG0::KiB_4 + + TCR_EL1::SH0::Inner + + TCR_EL1::ORGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::IRGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::EPD0::EnableTTBR0Walks + + TCR_EL1::T0SZ.val(16), + ); + + // Switch the MMU on. + // + // First, force all previous changes to be seen before the MMU is enabled. + unsafe { barrier::isb(barrier::SY) } + + // Enable the MMU and turn on data and instruction caching. + SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); + + // Force MMU init to complete before next instruction + unsafe { barrier::isb(barrier::SY) } +} + +pub fn map_kernel(kernel_start: usize, segments: &FixedVec) { + let (mut start_vaddr, mut end_vaddr) = (VirtAddr::new(core::u64::MAX), VirtAddr::zero()); for segment in segments { if segment.get_type() != Ok(Type::Load) { continue; } let virt_addr = segment.virtual_addr; let offset = segment.offset; - let file_size = segment.file_size as usize; - let mem_size = segment.mem_size as usize; + let file_size = segment.file_size; + let mem_size = segment.mem_size; unsafe { - let target = slice::from_raw_parts_mut(virt_addr as *mut u8, mem_size); - let source = slice::from_raw_parts((kernel_start + offset) as *const u8, file_size); - target.copy_from_slice(source); - target[file_size..].iter_mut().for_each(|x| *x = 0); + let src = (kernel_start as u64 + offset) as *const u8; + let dst = virt_addr as *mut u8; + ptr::copy(src, dst, file_size as usize); + ptr::write_bytes((virt_addr + file_size) as *mut u8, 0, (mem_size - file_size) as usize); + } + + if virt_addr < start_vaddr.as_u64() { + start_vaddr = VirtAddr::new(virt_addr).align_down(ALIGN_2MB); + } + if virt_addr + mem_size > end_vaddr.as_u64() { + end_vaddr = VirtAddr::new(virt_addr + mem_size).align_up(ALIGN_2MB); } } + + setup_temp_page_table(start_vaddr, end_vaddr, KERNEL_OFFSET.wrapping_neg()); + enable_mmu(); } diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 2c80a39..88a6ac7 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -46,11 +46,10 @@ pub extern "C" fn boot_main() -> ! { } } - arch::map_kernel(_kernel_payload_start as u64, &segments); - let entry = kernel_elf.header.pt2.entry_point(); let kernel_main: extern "C" fn() = unsafe { transmute(entry) }; + arch::map_kernel(_kernel_payload_start as usize, &segments); kernel_main(); loop {} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index a856fd5..eae162f 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#b6a0f4a3be6f74927c88305a6af5ad2be079bccd" +source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/boot/entry.S b/kernel/src/arch/aarch64/boot/entry.S index 4f7c40b..e2a22f4 100644 --- a/kernel/src/arch/aarch64/boot/entry.S +++ b/kernel/src/arch/aarch64/boot/entry.S @@ -4,18 +4,4 @@ _start: ldr x0, =bootstacktop mov sp, x0 - -zero_bss: - # load the start address and number of bytes in BSS section - ldr x1, =sbss - ldr x2, =__bss_length - -zero_bss_loop: - # zero out the BSS section, 64-bits at a time - cbz x2, zero_bss_loop_end - str xzr, [x1], #8 - sub x2, x2, #8 - cbnz x2, zero_bss_loop - -zero_bss_loop_end: bl rust_main diff --git a/kernel/src/arch/aarch64/boot/linker.ld b/kernel/src/arch/aarch64/boot/linker.ld index 399f3fa..0c102a0 100644 --- a/kernel/src/arch/aarch64/boot/linker.ld +++ b/kernel/src/arch/aarch64/boot/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x2000000; /* Load the kernel at this address. It's also kernel stack top address */ + . = 0x100000; /* Load the kernel at this address. It's also kernel stack top address */ bootstacktop = .; .text : { @@ -26,7 +26,7 @@ SECTIONS { edata = .; } - .bss (NOLOAD) : { + .bss : { . = ALIGN(32); sbss = .; *(.bss .bss.*) diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index c2a1b87..416c7f8 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -2,8 +2,7 @@ use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; use super::paging::MMIOType; -use aarch64::paging::{memory_attribute::*, PhysFrame as Frame}; -use aarch64::{addr::*, barrier, regs::*}; +use aarch64::regs::*; use atags::atags::Atags; use log::*; use rcore_memory::PAGE_SIZE; @@ -16,62 +15,6 @@ pub fn init() { info!("memory: init end"); } -/// initialize temporary paging and enable mmu immediately after boot. Serial port is disabled at this time. -pub fn init_mmu_early() { - #[repr(align(4096))] - struct PageData([u8; PAGE_SIZE]); - static PAGE_TABLE_LVL4: PageData = PageData([0; PAGE_SIZE]); - static PAGE_TABLE_LVL3: PageData = PageData([0; PAGE_SIZE]); - static PAGE_TABLE_LVL2: PageData = PageData([0; PAGE_SIZE]); - - let frame_lvl4 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL4 as *const _ as u64)); - let frame_lvl3 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL3 as *const _ as u64)); - let frame_lvl2 = Frame::containing_address(PhysAddr::new(&PAGE_TABLE_LVL2 as *const _ as u64)); - super::paging::setup_temp_page_table(frame_lvl4, frame_lvl3, frame_lvl2); - - // device. - MAIR_EL1.write( - MAIR_EL1::Attr0.val(MairNormal::config_value()) + - MAIR_EL1::Attr1.val(MairDevice::config_value()) + - MAIR_EL1::Attr2.val(MairNormalNonCacheable::config_value()), - ); - - // Configure various settings of stage 1 of the EL1 translation regime. - let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); - TCR_EL1.write( - TCR_EL1::TBI1::Ignored + - TCR_EL1::TBI0::Ignored + - TCR_EL1::AS::Bits_16 + - TCR_EL1::IPS.val(ips) + - - TCR_EL1::TG1::KiB_4 + - TCR_EL1::SH1::Inner + - TCR_EL1::ORGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + - TCR_EL1::IRGN1::WriteBack_ReadAlloc_WriteAlloc_Cacheable + - TCR_EL1::EPD1::EnableTTBR1Walks + - TCR_EL1::A1::UseTTBR1ASID + - TCR_EL1::T1SZ.val(16) + - - TCR_EL1::TG0::KiB_4 + - TCR_EL1::SH0::Inner + - TCR_EL1::ORGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + - TCR_EL1::IRGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + - TCR_EL1::EPD0::EnableTTBR0Walks + - TCR_EL1::T0SZ.val(16), - ); - - // Switch the MMU on. - // - // First, force all previous changes to be seen before the MMU is enabled. - unsafe { barrier::isb(barrier::SY) } - - // Enable the MMU and turn on data and instruction caching. - SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); - - // Force MMU init to complete before next instruction - unsafe { barrier::isb(barrier::SY) } -} - fn init_frame_allocator() { use crate::consts::MEMORY_OFFSET; use bit_allocator::BitAlloc; diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 370e1c0..4707027 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -17,7 +17,6 @@ global_asm!(include_str!("boot/entry.S")); /// The entry point of kernel #[no_mangle] // don't mangle the name of this function pub extern "C" fn rust_main() -> ! { - memory::init_mmu_early(); // Enable mmu and paging board::init_serial_early(); crate::logging::init(); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 04e5b36..76995d8 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -3,45 +3,13 @@ use rcore_memory::paging::*; use aarch64::asm::{tlb_invalidate, tlb_invalidate_all, ttbr_el1_read, ttbr_el1_write}; use aarch64::{PhysAddr, VirtAddr}; use aarch64::paging::{Mapper, PageTable as Aarch64PageTable, PageTableEntry, PageTableFlags as EF, RecursivePageTable}; -use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame, Size4KiB, Size2MiB, Size1GiB}; +use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame, Size4KiB}; use aarch64::paging::memory_attribute::*; use log::*; // Depends on kernel use crate::consts::{KERNEL_PML4, RECURSIVE_INDEX}; use crate::memory::{active_table, alloc_frame, dealloc_frame}; -// need 3 page -pub fn setup_temp_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: Frame) { - let p4 = unsafe { &mut *(frame_lvl4.start_address().as_u64() as *mut Aarch64PageTable) }; - let p3 = unsafe { &mut *(frame_lvl3.start_address().as_u64() as *mut Aarch64PageTable) }; - let p2 = unsafe { &mut *(frame_lvl2.start_address().as_u64() as *mut Aarch64PageTable) }; - p4.zero(); - p3.zero(); - p2.zero(); - - let (start_addr, end_addr) = (0, 0x40000000); - let block_flags = EF::VALID | EF::AF | EF::WRITE | EF::UXN; - for page in Page::::range_of(start_addr, end_addr) { - let paddr = PhysAddr::new(page.start_address().as_u64()); - - use super::board::IO_REMAP_BASE; - if paddr.as_u64() >= IO_REMAP_BASE as u64 { - p2[page.p2_index()].set_block::(paddr, block_flags | EF::PXN, MairDevice::attr_value()); - } else { - p2[page.p2_index()].set_block::(paddr, block_flags, MairNormal::attr_value()); - } - } - - p3[0].set_frame(frame_lvl2, EF::default(), MairNormal::attr_value()); - p3[1].set_block::(PhysAddr::new(0x40000000), block_flags | EF::PXN, MairDevice::attr_value()); - - p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value()); - p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value()); - - ttbr_el1_write(0, frame_lvl4); - tlb_invalidate_all(); -} - pub struct ActivePageTable(RecursivePageTable<'static>); pub struct PageEntry(PageTableEntry); @@ -50,13 +18,13 @@ impl PageTable for ActivePageTable { fn map(&mut self, addr: usize, target: usize) -> &mut Entry { let flags = EF::default(); let attr = MairNormal::attr_value(); - self.0.map_to(Page::of_addr(addr), Frame::of_addr(target), flags, attr, &mut FrameAllocatorForAarch64) + self.0.map_to(Page::of_addr(addr as u64), Frame::of_addr(target as u64), flags, attr, &mut FrameAllocatorForAarch64) .unwrap().flush(); self.get_entry(addr).expect("fail to get entry") } fn unmap(&mut self, addr: usize) { - let (_frame, flush) = self.0.unmap(Page::of_addr(addr)).unwrap(); + let (_frame, flush) = self.0.unmap(Page::of_addr(addr as u64)).unwrap(); flush.flush(); } @@ -191,7 +159,7 @@ impl InactivePageTable for InactivePageTable0 { fn new_bare() -> Self { let target = alloc_frame().expect("failed to allocate frame"); - let frame = Frame::of_addr(target); + let frame = Frame::of_addr(target as u64); active_table().with_temporary_map(target, |_, table: &mut Aarch64PageTable| { table.zero(); // set up recursive mapping for the table @@ -274,7 +242,7 @@ struct FrameAllocatorForAarch64; impl FrameAllocator for FrameAllocatorForAarch64 { fn alloc(&mut self) -> Option { - alloc_frame().map(|addr| Frame::of_addr(addr)) + alloc_frame().map(|addr| Frame::of_addr(addr as u64)) } } From 279f9837860afd82e2fc3f85754e3c114a2574b6 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sat, 9 Mar 2019 19:50:11 +0800 Subject: [PATCH 4/8] aarch64: put the kernel in the top VA range --- bootloader/Cargo.lock | 2 +- bootloader/src/arch/aarch64/mod.rs | 9 +++--- crate/bcm2837/src/lib.rs | 2 +- crate/bcm2837/src/timer/generic_timer.rs | 2 +- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/fb.rs | 14 ++++----- kernel/src/arch/aarch64/board/raspi3/mod.rs | 2 +- kernel/src/arch/aarch64/boot/linker.ld | 2 +- kernel/src/arch/aarch64/consts.rs | 6 ++-- kernel/src/arch/aarch64/interrupt/context.rs | 4 +-- kernel/src/arch/aarch64/memory.rs | 25 +++++++++------- kernel/src/arch/aarch64/paging.rs | 31 ++++++++++++-------- kernel/src/process/structs.rs | 3 -- user | 2 +- 14 files changed, 57 insertions(+), 49 deletions(-) diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index 80bde96..1b96241 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" +source = "git+https://github.com/equation314/aarch64#14a08f4d285ae0ff515b03bff9f5e66eb68feaed" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index e7cb408..61f9152 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -13,7 +13,7 @@ const IO_REMAP_BASE: u64 = 0x3F00_0000; const MEMORY_END: u64 = 0x4000_0000; const RECURSIVE_INDEX: usize = 0o777; -const KERNEL_OFFSET: u64 = 0x0000_0000_0000_0000; +const KERNEL_OFFSET: u64 = 0xFFFF_0000_0000_0000; global_asm!(include_str!("boot.S")); @@ -52,7 +52,8 @@ fn setup_temp_page_table(start_vaddr: VirtAddr, end_vaddr: VirtAddr, offset: u64 p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value()); p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value()); - ttbr_el1_write(VirtAddr::new(KERNEL_OFFSET).va_range().unwrap() as u8, frame_lvl4); + ttbr_el1_write(0, frame_lvl4); + ttbr_el1_write(1, frame_lvl4); tlb_invalidate_all(); } @@ -112,9 +113,9 @@ pub fn map_kernel(kernel_start: usize, segments: &FixedVec) { unsafe { let src = (kernel_start as u64 + offset) as *const u8; - let dst = virt_addr as *mut u8; + let dst = virt_addr.wrapping_sub(KERNEL_OFFSET) as *mut u8; ptr::copy(src, dst, file_size as usize); - ptr::write_bytes((virt_addr + file_size) as *mut u8, 0, (mem_size - file_size) as usize); + ptr::write_bytes(dst.offset(file_size as isize), 0, (mem_size - file_size) as usize); } if virt_addr < start_vaddr.as_u64() { diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs index d8af5ab..2755e55 100644 --- a/crate/bcm2837/src/lib.rs +++ b/crate/bcm2837/src/lib.rs @@ -9,4 +9,4 @@ pub mod mailbox; pub mod mini_uart; pub mod interrupt; -pub const IO_BASE: usize = 0x3F000000; +pub const IO_BASE: usize = 0xFFFF_0000_3F00_0000; diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs index c4db806..bc54053 100644 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ b/crate/bcm2837/src/timer/generic_timer.rs @@ -5,7 +5,7 @@ use aarch64::regs::*; use volatile::*; /// The base address for the ARM generic timer, IRQs, mailboxes -const GEN_TIMER_REG_BASE: usize = 0x40000000; +const GEN_TIMER_REG_BASE: usize = 0xFFFF_0000_4000_0000; /// Core interrupt sources (ref: QA7 4.10, page 16) #[repr(u8)] diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index eae162f..c14e2d1 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -3,7 +3,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#ad81f8f0ebd6fed15b2b0696f5d1b566d36f1172" +source = "git+https://github.com/equation314/aarch64#14a08f4d285ae0ff515b03bff9f5e66eb68feaed" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 05fc6c0..02c647a 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -53,19 +53,19 @@ union ColorBuffer { } impl ColorBuffer { - fn new(color_depth: ColorDepth, bus_addr: u32, size: u32) -> ColorBuffer { + fn new(color_depth: ColorDepth, base_addr: usize, size: usize) -> ColorBuffer { unsafe { match color_depth { ColorDepth16 => ColorBuffer { buf16: core::slice::from_raw_parts_mut( - bus_addr as *mut u16, - (size / 2) as usize, + base_addr as *mut u16, + size / 2, ), }, ColorDepth32 => ColorBuffer { buf32: core::slice::from_raw_parts_mut( - bus_addr as *mut u32, - (size / 4) as usize, + base_addr as *mut u32, + size / 4, ), }, } @@ -144,7 +144,7 @@ impl Framebuffer { use crate::arch::memory; let paddr = info.bus_addr & !0xC0000000; - let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb") as u32; + let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb"); if vaddr == 0 { Err(format!( "cannot remap memory range [{:#x?}..{:#x?}]", @@ -153,7 +153,7 @@ impl Framebuffer { ))?; } Ok(Framebuffer { - buf: ColorBuffer::new(color_depth, vaddr, info.screen_size), + buf: ColorBuffer::new(color_depth, vaddr, info.screen_size as usize), color_depth, fb_info: info, }) diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index 6954e99..c001b34 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -9,7 +9,7 @@ pub mod serial; pub mod mailbox; pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; -pub const IO_REMAP_END: usize = 0x40001000; +pub const IO_REMAP_END: usize = 0xFFFF_0000_4000_1000; /// Initialize serial port before other initializations. pub fn init_serial_early() { diff --git a/kernel/src/arch/aarch64/boot/linker.ld b/kernel/src/arch/aarch64/boot/linker.ld index 0c102a0..e8a1046 100644 --- a/kernel/src/arch/aarch64/boot/linker.ld +++ b/kernel/src/arch/aarch64/boot/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x100000; /* Load the kernel at this address. It's also kernel stack top address */ + . = 0xffff000000100000; /* Load the kernel at this address. It's also kernel stack top address */ bootstacktop = .; .text : { diff --git a/kernel/src/arch/aarch64/consts.rs b/kernel/src/arch/aarch64/consts.rs index af9f49c..ea71e7a 100644 --- a/kernel/src/arch/aarch64/consts.rs +++ b/kernel/src/arch/aarch64/consts.rs @@ -1,8 +1,8 @@ pub const RECURSIVE_INDEX: usize = 0o777; -pub const KERNEL_OFFSET: usize = 0; +pub const KERNEL_OFFSET: usize = 0xFFFF_0000_0000_0000; pub const KERNEL_PML4: usize = 0; pub const KERNEL_HEAP_SIZE: usize = 8 * 1024 * 1024; pub const MEMORY_OFFSET: usize = 0; -pub const USER_STACK_OFFSET: usize = 0xffff_8000_0000_0000; +pub const USER_STACK_OFFSET: usize = 0x0000_8000_0000_0000 - USER_STACK_SIZE; pub const USER_STACK_SIZE: usize = 1 * 1024 * 1024; -pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; \ No newline at end of file +pub const USER32_STACK_OFFSET: usize = USER_STACK_OFFSET; diff --git a/kernel/src/arch/aarch64/interrupt/context.rs b/kernel/src/arch/aarch64/interrupt/context.rs index ab24ecf..2f82217 100644 --- a/kernel/src/arch/aarch64/interrupt/context.rs +++ b/kernel/src/arch/aarch64/interrupt/context.rs @@ -127,11 +127,11 @@ impl Context { } pub unsafe fn switch(&mut self, target: &mut Self) { - self.ttbr = ttbr_el1_read(1); + self.ttbr = ttbr_el1_read(0); target.asid = ASID_ALLOCATOR.lock().alloc(target.asid); // with ASID we needn't flush TLB frequently - ttbr_el1_write_asid(1, target.asid.value, target.ttbr); + ttbr_el1_write_asid(0, target.asid.value, target.ttbr); barrier::dsb(barrier::ISH); Self::__switch(&mut self.stack_top, &mut target.stack_top); } diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 416c7f8..1fd2162 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -1,6 +1,7 @@ //! Memory initialization for aarch64. use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; +use crate::consts::{MEMORY_OFFSET, KERNEL_OFFSET}; use super::paging::MMIOType; use aarch64::regs::*; use atags::atags::Atags; @@ -16,7 +17,6 @@ pub fn init() { } fn init_frame_allocator() { - use crate::consts::MEMORY_OFFSET; use bit_allocator::BitAlloc; use core::ops::Range; @@ -45,15 +45,16 @@ static mut KERNEL_MEMORY_SET: Option = None; /// remap kernel page table after all initialization. fn remap_the_kernel() { + let offset = -(KERNEL_OFFSET as isize); let mut ms = MemorySet::new_bare(); - ms.push(0, bootstacktop as usize, Linear::new(0, MemoryAttr::default()), "kstack"); - ms.push(stext as usize, etext as usize, Linear::new(0, MemoryAttr::default().execute().readonly()), "text"); - ms.push(sdata as usize, edata as usize, Linear::new(0, MemoryAttr::default()), "data"); - ms.push(srodata as usize, erodata as usize, Linear::new(0, MemoryAttr::default().readonly()), "rodata"); - ms.push(sbss as usize, ebss as usize, Linear::new(0, MemoryAttr::default()), "bss"); + ms.push(KERNEL_OFFSET, bootstacktop as usize, Linear::new(offset, MemoryAttr::default()), "kstack"); + ms.push(stext as usize, etext as usize, Linear::new(offset, MemoryAttr::default().execute().readonly()), "text"); + ms.push(sdata as usize, edata as usize, Linear::new(offset, MemoryAttr::default()), "data"); + ms.push(srodata as usize, erodata as usize, Linear::new(offset, MemoryAttr::default().readonly()), "rodata"); + ms.push(sbss as usize, ebss as usize, Linear::new(offset, MemoryAttr::default()), "bss"); use super::board::{IO_REMAP_BASE, IO_REMAP_END}; - ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(0, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); + ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(offset, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); info!("{:#x?}", ms); unsafe { ms.get_page_table_mut().activate_as_kernel() } @@ -61,10 +62,12 @@ fn remap_the_kernel() { info!("kernel remap end"); } -pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { +pub fn ioremap(paddr: usize, len: usize, name: &'static str) -> usize { + let offset = -(KERNEL_OFFSET as isize); + let vaddr = paddr.wrapping_add(KERNEL_OFFSET); if let Some(ms) = unsafe { KERNEL_MEMORY_SET.as_mut() } { - ms.push(start, start + len, Linear::new(0, MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8)), name); - return start; + ms.push(vaddr, vaddr + len, Linear::new(offset, MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8)), name); + return vaddr; } 0 } @@ -74,7 +77,7 @@ pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { /// /// This function is expected to return `Some` under all normal cirumstances. fn memory_map() -> Option<(usize, usize)> { - let binary_end = _end as u32; + let binary_end = (_end as u64).wrapping_sub(KERNEL_OFFSET as u64); let mut atags: Atags = Atags::get(); while let Some(atag) = atags.next() { diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 76995d8..51735c4 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -7,7 +7,7 @@ use aarch64::paging::{FrameAllocator, FrameDeallocator, Page, PhysFrame as Frame use aarch64::paging::memory_attribute::*; use log::*; // Depends on kernel -use crate::consts::{KERNEL_PML4, RECURSIVE_INDEX}; +use crate::consts::{KERNEL_OFFSET, KERNEL_PML4, RECURSIVE_INDEX}; use crate::memory::{active_table, alloc_frame, dealloc_frame}; pub struct ActivePageTable(RecursivePageTable<'static>); @@ -36,10 +36,16 @@ impl PageTable for ActivePageTable { } } -impl PageTableExt for ActivePageTable {} +impl PageTableExt for ActivePageTable { + const TEMP_PAGE_ADDR: usize = KERNEL_OFFSET | 0xcafeb000; +} const ROOT_PAGE_TABLE: *mut Aarch64PageTable = - ((RECURSIVE_INDEX << 39) | (RECURSIVE_INDEX << 30) | (RECURSIVE_INDEX << 21) | (RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable; + (KERNEL_OFFSET | + (RECURSIVE_INDEX << 39) | + (RECURSIVE_INDEX << 30) | + (RECURSIVE_INDEX << 21) | + (RECURSIVE_INDEX << 12)) as *mut Aarch64PageTable; impl ActivePageTable { pub unsafe fn new() -> Self { @@ -183,11 +189,11 @@ impl InactivePageTable for InactivePageTable0 { } unsafe fn set_token(token: usize) { - ttbr_el1_write(1, Frame::containing_address(PhysAddr::new(token as u64))); + ttbr_el1_write(0, Frame::containing_address(PhysAddr::new(token as u64))); } fn active_token() -> usize { - ttbr_el1_read(1).start_address().as_u64() as usize + ttbr_el1_read(0).start_address().as_u64() as usize } fn flush_tlb() { @@ -195,14 +201,14 @@ impl InactivePageTable for InactivePageTable0 { } fn edit(&mut self, f: impl FnOnce(&mut Self::Active) -> T) -> T { - let target = ttbr_el1_read(0).start_address().as_u64() as usize; + let target = ttbr_el1_read(1).start_address().as_u64() as usize; active_table().with_temporary_map(target, |active_table, p4_table: &mut Aarch64PageTable| { let backup = p4_table[RECURSIVE_INDEX].clone(); - let old_frame = ttbr_el1_read(1); + let old_frame = ttbr_el1_read(0); // overwrite recursive mapping p4_table[RECURSIVE_INDEX].set_frame(self.p4_frame.clone(), EF::default(), MairNormal::attr_value()); - ttbr_el1_write(1, self.p4_frame.clone()); + ttbr_el1_write(0, self.p4_frame.clone()); tlb_invalidate_all(); // execute f in the new context @@ -210,7 +216,7 @@ impl InactivePageTable for InactivePageTable0 { // restore recursive mapping to original p4 table p4_table[RECURSIVE_INDEX] = backup; - ttbr_el1_write(1, old_frame); + ttbr_el1_write(0, old_frame); tlb_invalidate_all(); ret }) @@ -221,11 +227,12 @@ impl InactivePageTable0 { /// Activate as kernel page table (TTBR0). /// Used in `arch::memory::remap_the_kernel()`. pub unsafe fn activate_as_kernel(&self) { - let old_frame = ttbr_el1_read(0); + let old_frame = ttbr_el1_read(1); let new_frame = self.p4_frame.clone(); - debug!("switch TTBR0 {:?} -> {:?}", old_frame, new_frame); + debug!("switch TTBR1 {:?} -> {:?}", old_frame, new_frame); if old_frame != new_frame { - ttbr_el1_write(0, new_frame); + ttbr_el1_write(0, Frame::of_addr(0)); + ttbr_el1_write(1, new_frame); tlb_invalidate_all(); } } diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 6218338..b6dafa1 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -238,9 +238,6 @@ fn memory_set_from(elf: &ElfFile<'_>) -> (MemorySet, usize) { let file_size = ph.file_size() as usize; let mem_size = ph.mem_size() as usize; - #[cfg(target_arch = "aarch64")] - assert_eq!((virt_addr >> 48), 0xffff, "Segment Fault"); - // Get target slice #[cfg(feature = "no_mmu")] let target = &mut target[virt_addr - va_begin..virt_addr - va_begin + mem_size]; diff --git a/user b/user index 64dac11..bbf127b 160000 --- a/user +++ b/user @@ -1 +1 @@ -Subproject commit 64dac11ac304eece980ba4cffb2eac2040aa08b3 +Subproject commit bbf127b24e3ec46b03dcedab4e4364d6494a26d9 From 68b967b48e74be3b5c35bc399cef65fa6749478b Mon Sep 17 00:00:00 2001 From: equation314 Date: Sat, 9 Mar 2019 22:20:03 +0800 Subject: [PATCH 5/8] aarch64: move crate `atags` into crate `bcm2837` --- bootloader/Cargo.lock | 14 +++++++++++++ bootloader/Cargo.toml | 1 + bootloader/src/arch/aarch64/mod.rs | 8 +++---- crate/atags/Cargo.toml | 6 ------ crate/atags/src/lib.rs | 6 ------ crate/bcm2837/Cargo.toml | 1 + .../{atags/src => bcm2837/src/atags}/atag.rs | 14 ++++++------- .../src/atags.rs => bcm2837/src/atags/mod.rs} | 14 ++++++++----- crate/{atags/src => bcm2837/src/atags}/raw.rs | 14 ++++++------- crate/bcm2837/src/consts.rs | 7 +++++++ crate/bcm2837/src/gpio.rs | 2 +- crate/bcm2837/src/interrupt.rs | 2 +- crate/bcm2837/src/lib.rs | 8 +++---- crate/bcm2837/src/mailbox.rs | 2 +- crate/bcm2837/src/mini_uart.rs | 2 +- crate/bcm2837/src/timer/generic_timer.rs | 3 ++- crate/bcm2837/src/timer/system_timer.rs | 2 +- kernel/Cargo.lock | 5 ----- kernel/Cargo.toml | 1 - kernel/src/arch/aarch64/board/raspi3/mod.rs | 19 +++++++++++++++-- kernel/src/arch/aarch64/memory.rs | 21 ++----------------- kernel/src/arch/aarch64/paging.rs | 3 +-- 22 files changed, 78 insertions(+), 77 deletions(-) delete mode 100644 crate/atags/Cargo.toml delete mode 100644 crate/atags/src/lib.rs rename crate/{atags/src => bcm2837/src/atags}/atag.rs (88%) rename crate/{atags/src/atags.rs => bcm2837/src/atags/mod.rs} (75%) rename crate/{atags/src => bcm2837/src/atags}/raw.rs (85%) create mode 100644 crate/bcm2837/src/consts.rs diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index 1b96241..e2fe90a 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -12,6 +12,13 @@ dependencies = [ "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bcm2837" +version = "0.1.0" +dependencies = [ + "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bit_field" version = "0.9.0" @@ -91,6 +98,7 @@ name = "rcore-bootloader" version = "0.1.0" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", + "bcm2837 0.1.0", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -158,6 +166,11 @@ name = "ux" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "volatile" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.6" @@ -212,6 +225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" "checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f" +"checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml index 5a77dff..70f7550 100644 --- a/bootloader/Cargo.toml +++ b/bootloader/Cargo.toml @@ -10,6 +10,7 @@ fixedvec = "0.2.3" [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } +bcm2837 = { path = "../crate/bcm2837" } [build-dependencies] cc = "1.0" diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index 61f9152..2ba1473 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -2,6 +2,7 @@ use aarch64::addr::{VirtAddr, PhysAddr}; use aarch64::paging::{memory_attribute::*, Page, PageTable, PageTableFlags as EF, PhysFrame}; use aarch64::paging::{Size4KiB, Size2MiB, Size1GiB}; use aarch64::{asm::*, barrier, regs::*}; +use bcm2837::consts::RAW_IO_BASE; use core::ptr; use fixedvec::FixedVec; use xmas_elf::program::{ProgramHeader64, Type}; @@ -9,9 +10,6 @@ use xmas_elf::program::{ProgramHeader64, Type}; const PAGE_SIZE: usize = 4096; const ALIGN_2MB: u64 = 0x200000; -const IO_REMAP_BASE: u64 = 0x3F00_0000; -const MEMORY_END: u64 = 0x4000_0000; - const RECURSIVE_INDEX: usize = 0o777; const KERNEL_OFFSET: u64 = 0xFFFF_0000_0000_0000; @@ -41,13 +39,13 @@ fn setup_temp_page_table(start_vaddr: VirtAddr, end_vaddr: VirtAddr, offset: u64 p2[page.p2_index()].set_block::(paddr, block_flags, MairNormal::attr_value()); } // device memory - for page in Page::::range_of(IO_REMAP_BASE, MEMORY_END) { + for page in Page::::range_of(RAW_IO_BASE as u64, 0x4000_0000) { let paddr = PhysAddr::new(page.start_address().as_u64()); p2[page.p2_index()].set_block::(paddr, block_flags | EF::PXN, MairDevice::attr_value()); } p3[0].set_frame(frame_lvl2, EF::default(), MairNormal::attr_value()); - p3[1].set_block::(PhysAddr::new(MEMORY_END), block_flags | EF::PXN, MairDevice::attr_value()); + p3[1].set_block::(PhysAddr::new(0x4000_0000), block_flags | EF::PXN, MairDevice::attr_value()); p4[0].set_frame(frame_lvl3, EF::default(), MairNormal::attr_value()); p4[RECURSIVE_INDEX].set_frame(frame_lvl4, EF::default(), MairNormal::attr_value()); diff --git a/crate/atags/Cargo.toml b/crate/atags/Cargo.toml deleted file mode 100644 index 3c095bf..0000000 --- a/crate/atags/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "atags" -version = "0.1.0" -authors = ["koumingyang <1761674434@qq.com>"] - -[dependencies] \ No newline at end of file diff --git a/crate/atags/src/lib.rs b/crate/atags/src/lib.rs deleted file mode 100644 index 33c76c2..0000000 --- a/crate/atags/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![no_std] - -mod raw; -mod atag; - -pub mod atags; diff --git a/crate/bcm2837/Cargo.toml b/crate/bcm2837/Cargo.toml index 456ee0e..18cb598 100644 --- a/crate/bcm2837/Cargo.toml +++ b/crate/bcm2837/Cargo.toml @@ -5,6 +5,7 @@ authors = ["equation314 "] edition = "2018" [features] +zero_kernel_offset = [] use_generic_timer = ["aarch64"] [dependencies] diff --git a/crate/atags/src/atag.rs b/crate/bcm2837/src/atags/atag.rs similarity index 88% rename from crate/atags/src/atag.rs rename to crate/bcm2837/src/atags/atag.rs index 77f729a..30315ea 100644 --- a/crate/atags/src/atag.rs +++ b/crate/bcm2837/src/atags/atag.rs @@ -1,9 +1,7 @@ -use raw; +use super::raw; use core::slice; use core::str; -pub use raw::{Core, Mem}; - /// An ATAG. #[derive(Debug, Copy, Clone)] pub enum Atag { @@ -11,12 +9,12 @@ pub enum Atag { Mem(raw::Mem), Cmd(&'static str), Unknown(u32), - None + None, } impl Atag { /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`. - pub fn core(self) -> Option { + pub fn core(self) -> Option { match self { Atag::Core(x) => Some(x), _ => None, @@ -24,7 +22,7 @@ impl Atag { } /// Returns `Some` if this is a `Mem` ATAG. Otherwise returns `None`. - pub fn mem(self) -> Option { + pub fn mem(self) -> Option { match self { Atag::Mem(x) => Some(x), _ => None, @@ -49,7 +47,7 @@ impl<'a> From<&'a raw::Atag> for Atag { (raw::Atag::CORE, &raw::Kind { core }) => Atag::Core(core), (raw::Atag::MEM, &raw::Kind { mem }) => Atag::Mem(mem), (raw::Atag::CMDLINE, &raw::Kind { ref cmd }) => { - let mut cmd_ptr: *const u8 = &cmd.cmd as *const u8; + let cmd_ptr: *const u8 = &cmd.cmd as *const u8; let mut len: usize = 0; while *cmd_ptr.add(len) != 0 { @@ -58,7 +56,7 @@ impl<'a> From<&'a raw::Atag> for Atag { let cmd_slice = slice::from_raw_parts(cmd_ptr, len); Atag::Cmd(str::from_utf8_unchecked(cmd_slice)) - }, + } (raw::Atag::NONE, _) => Atag::None, (id, _) => Atag::Unknown(id), } diff --git a/crate/atags/src/atags.rs b/crate/bcm2837/src/atags/mod.rs similarity index 75% rename from crate/atags/src/atags.rs rename to crate/bcm2837/src/atags/mod.rs index 98b7522..8787fcc 100644 --- a/crate/atags/src/atags.rs +++ b/crate/bcm2837/src/atags/mod.rs @@ -1,8 +1,12 @@ -pub use atag::*; -use raw; +mod atag; +mod raw; + +use super::consts::KERNEL_OFFSET; +pub use self::atag::*; +pub use self::raw::{Cmd, Core, Mem}; /// The address at which the firmware loads the ATAGS. -const ATAG_BASE: usize = 0x100; +const ATAG_BASE: usize = KERNEL_OFFSET + 0x100; /// An iterator over the ATAGS on this system. pub struct Atags { @@ -13,7 +17,7 @@ impl Atags { /// Returns an instance of `Atags`, an iterator over ATAGS on this system. pub fn get() -> Atags { Atags { - ptr: unsafe { &*(ATAG_BASE as *const raw::Atag) } + ptr: unsafe { &*(ATAG_BASE as *const raw::Atag) }, } } } @@ -30,7 +34,7 @@ impl Iterator for Atags { let result = Some(Atag::from(cur)); self.ptr = next; result - }, + } None => None, } } diff --git a/crate/atags/src/raw.rs b/crate/bcm2837/src/atags/raw.rs similarity index 85% rename from crate/atags/src/raw.rs rename to crate/bcm2837/src/atags/raw.rs index abfd166..22bed83 100644 --- a/crate/atags/src/raw.rs +++ b/crate/bcm2837/src/atags/raw.rs @@ -3,7 +3,7 @@ pub struct Atag { pub dwords: u32, pub tag: u32, - pub kind: Kind + pub kind: Kind, } impl Atag { @@ -24,9 +24,7 @@ impl Atag { None } else { let current = self as *const Atag as *const u32; - let next: &Atag = unsafe { - &*(current.add(self.dwords as usize) as *const Atag) - }; + let next: &Atag = unsafe { &*(current.add(self.dwords as usize) as *const Atag) }; Some(next) } @@ -38,7 +36,7 @@ impl Atag { pub union Kind { pub core: Core, pub mem: Mem, - pub cmd: Cmd + pub cmd: Cmd, } /// A `CORE` ATAG. @@ -47,7 +45,7 @@ pub union Kind { pub struct Core { pub flags: u32, pub page_size: u32, - pub root_dev: u32 + pub root_dev: u32, } /// A `MEM` ATAG. @@ -55,7 +53,7 @@ pub struct Core { #[derive(Debug, Copy, Clone)] pub struct Mem { pub size: u32, - pub start: u32 + pub start: u32, } /// A `CMDLINE` ATAG. @@ -63,5 +61,5 @@ pub struct Mem { #[derive(Debug, Copy, Clone)] pub struct Cmd { /// The first byte of the command line string. - pub cmd: u8 + pub cmd: u8, } diff --git a/crate/bcm2837/src/consts.rs b/crate/bcm2837/src/consts.rs new file mode 100644 index 0000000..92ec433 --- /dev/null +++ b/crate/bcm2837/src/consts.rs @@ -0,0 +1,7 @@ +#[cfg(feature = "zero_kernel_offset")] +pub const KERNEL_OFFSET: usize = 0; +#[cfg(not(feature = "zero_kernel_offset"))] +pub const KERNEL_OFFSET: usize = 0xFFFF_0000_0000_0000; + +pub const RAW_IO_BASE: usize = 0x3F00_0000; +pub const IO_BASE: usize = KERNEL_OFFSET + RAW_IO_BASE; diff --git a/crate/bcm2837/src/gpio.rs b/crate/bcm2837/src/gpio.rs index ef258d6..2bcf901 100644 --- a/crate/bcm2837/src/gpio.rs +++ b/crate/bcm2837/src/gpio.rs @@ -1,4 +1,4 @@ -use crate::IO_BASE; +use crate::consts::IO_BASE; use crate::timer::delay; use core::marker::PhantomData; use volatile::{ReadOnly, Volatile, WriteOnly}; diff --git a/crate/bcm2837/src/interrupt.rs b/crate/bcm2837/src/interrupt.rs index 03657c9..d3caba6 100644 --- a/crate/bcm2837/src/interrupt.rs +++ b/crate/bcm2837/src/interrupt.rs @@ -1,4 +1,4 @@ -use crate::IO_BASE; +use crate::consts::IO_BASE; use volatile::{ReadOnly, Volatile}; const INT_BASE: usize = IO_BASE + 0xB000 + 0x200; diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs index 2755e55..ba9cc2a 100644 --- a/crate/bcm2837/src/lib.rs +++ b/crate/bcm2837/src/lib.rs @@ -3,10 +3,10 @@ extern crate volatile; +pub mod atags; +pub mod consts; pub mod gpio; -pub mod timer; +pub mod interrupt; pub mod mailbox; pub mod mini_uart; -pub mod interrupt; - -pub const IO_BASE: usize = 0xFFFF_0000_3F00_0000; +pub mod timer; diff --git a/crate/bcm2837/src/mailbox.rs b/crate/bcm2837/src/mailbox.rs index 0e7d32f..e20c0ff 100644 --- a/crate/bcm2837/src/mailbox.rs +++ b/crate/bcm2837/src/mailbox.rs @@ -1,4 +1,4 @@ -use crate::IO_BASE; +use crate::consts::IO_BASE; use volatile::{ReadOnly, Volatile, WriteOnly}; /// The base address for the `MU` registers. diff --git a/crate/bcm2837/src/mini_uart.rs b/crate/bcm2837/src/mini_uart.rs index a3a5503..9606cf8 100644 --- a/crate/bcm2837/src/mini_uart.rs +++ b/crate/bcm2837/src/mini_uart.rs @@ -1,4 +1,4 @@ -use crate::IO_BASE; +use crate::consts::IO_BASE; use crate::gpio::{Function, Gpio}; use volatile::{ReadOnly, Volatile}; diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs index bc54053..9128dce 100644 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ b/crate/bcm2837/src/timer/generic_timer.rs @@ -1,11 +1,12 @@ extern crate aarch64; use super::BasicTimer; +use crate::consts::KERNEL_OFFSET; use aarch64::regs::*; use volatile::*; /// The base address for the ARM generic timer, IRQs, mailboxes -const GEN_TIMER_REG_BASE: usize = 0xFFFF_0000_4000_0000; +const GEN_TIMER_REG_BASE: usize = KERNEL_OFFSET + 0x4000_0000; /// Core interrupt sources (ref: QA7 4.10, page 16) #[repr(u8)] diff --git a/crate/bcm2837/src/timer/system_timer.rs b/crate/bcm2837/src/timer/system_timer.rs index 9261c4a..6ad1d85 100644 --- a/crate/bcm2837/src/timer/system_timer.rs +++ b/crate/bcm2837/src/timer/system_timer.rs @@ -1,6 +1,6 @@ use super::BasicTimer; +use crate::consts::IO_BASE; use crate::interrupt::{Controller, Interrupt}; -use crate::IO_BASE; use volatile::{ReadOnly, Volatile}; /// The base address for the ARM system timer registers. diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index c14e2d1..fe415ce 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -30,10 +30,6 @@ dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "atags" -version = "0.1.0" - [[package]] name = "bare-metal" version = "0.2.4" @@ -251,7 +247,6 @@ version = "0.1.0" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)", - "atags 0.1.0", "bbl 0.1.0", "bcm2837 0.1.0", "bit-allocator 0.1.0", diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2619130..6b26913 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -72,7 +72,6 @@ bbl = { path = "../crate/bbl" } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } -atags = { path = "../crate/atags" } bcm2837 = { path = "../crate/bcm2837", optional = true } [package.metadata.bootimage] diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index c001b34..ff959e4 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -1,6 +1,7 @@ //! Raspberry PI 3 Model B/B+ use once::*; +use bcm2837::atags::Atags; pub mod fb; pub mod irq; @@ -8,8 +9,8 @@ pub mod timer; pub mod serial; pub mod mailbox; -pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; -pub const IO_REMAP_END: usize = 0xFFFF_0000_4000_1000; +pub const IO_REMAP_BASE: usize = bcm2837::consts::IO_BASE; +pub const IO_REMAP_END: usize = bcm2837::consts::KERNEL_OFFSET + 0x4000_1000; /// Initialize serial port before other initializations. pub fn init_serial_early() { @@ -26,3 +27,17 @@ pub fn init_driver() { fb::init(); timer::init(); } + +/// Returns the (start address, end address) of the physical memory on this +/// system if it can be determined. If it cannot, `None` is returned. +/// +/// This function is expected to return `Some` under all normal cirumstances. +pub fn probe_memory() -> Option<(usize, usize)> { + let mut atags: Atags = Atags::get(); + while let Some(atag) = atags.next() { + if let Some(mem) = atag.mem() { + return Some((mem.start as usize, (mem.start + mem.size) as usize)); + } + } + None +} diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 1fd2162..c40a055 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -4,7 +4,6 @@ use crate::memory::{init_heap, Linear, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; use crate::consts::{MEMORY_OFFSET, KERNEL_OFFSET}; use super::paging::MMIOType; use aarch64::regs::*; -use atags::atags::Atags; use log::*; use rcore_memory::PAGE_SIZE; @@ -20,7 +19,8 @@ fn init_frame_allocator() { use bit_allocator::BitAlloc; use core::ops::Range; - let (start, end) = memory_map().expect("failed to find memory map"); + let end = super::board::probe_memory().expect("failed to find memory map").1; + let start = (_end as u64 + PAGE_SIZE as u64).wrapping_sub(KERNEL_OFFSET as u64) as usize; let mut ba = FRAME_ALLOCATOR.lock(); ba.insert(to_range(start, end)); info!("FrameAllocator init end"); @@ -72,23 +72,6 @@ pub fn ioremap(paddr: usize, len: usize, name: &'static str) -> usize { 0 } -/// Returns the (start address, end address) of the available memory on this -/// system if it can be determined. If it cannot, `None` is returned. -/// -/// This function is expected to return `Some` under all normal cirumstances. -fn memory_map() -> Option<(usize, usize)> { - let binary_end = (_end as u64).wrapping_sub(KERNEL_OFFSET as u64); - - let mut atags: Atags = Atags::get(); - while let Some(atag) = atags.next() { - if let Some(mem) = atag.mem() { - return Some((binary_end as usize, (mem.start + mem.size) as usize)); - } - } - - None -} - extern "C" { fn bootstacktop(); fn stext(); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index 51735c4..e5da2bb 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -30,8 +30,7 @@ impl PageTable for ActivePageTable { fn get_entry(&mut self, vaddr: usize) -> Option<&mut Entry> { // get p1 entry - let entry_addr = ((vaddr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39) - | (vaddr & 0xffff_0000_0000_0000); + let entry_addr = ((vaddr >> 9) & 0o777_777_777_7770) | (RECURSIVE_INDEX << 39) | (vaddr & KERNEL_OFFSET); Some(unsafe { &mut *(entry_addr as *mut PageEntry) }) } } From f3d47f4b021c6824575f7bd979ea671759fe9a63 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sat, 9 Mar 2019 23:03:44 +0800 Subject: [PATCH 6/8] aarch64: move crate bcm2837 to remote --- bootloader/Cargo.lock | 4 +- bootloader/Cargo.toml | 2 +- crate/bcm2837/Cargo.toml | 13 -- crate/bcm2837/src/atags/atag.rs | 65 --------- crate/bcm2837/src/atags/mod.rs | 41 ------ crate/bcm2837/src/atags/raw.rs | 65 --------- crate/bcm2837/src/consts.rs | 7 - crate/bcm2837/src/gpio.rs | 163 ----------------------- crate/bcm2837/src/interrupt.rs | 88 ------------ crate/bcm2837/src/lib.rs | 12 -- crate/bcm2837/src/mailbox.rs | 80 ----------- crate/bcm2837/src/mini_uart.rs | 133 ------------------ crate/bcm2837/src/timer/generic_timer.rs | 77 ----------- crate/bcm2837/src/timer/mod.rs | 38 ------ crate/bcm2837/src/timer/system_timer.rs | 62 --------- kernel/Cargo.lock | 4 +- kernel/Cargo.toml | 2 +- 17 files changed, 8 insertions(+), 848 deletions(-) delete mode 100644 crate/bcm2837/Cargo.toml delete mode 100644 crate/bcm2837/src/atags/atag.rs delete mode 100644 crate/bcm2837/src/atags/mod.rs delete mode 100644 crate/bcm2837/src/atags/raw.rs delete mode 100644 crate/bcm2837/src/consts.rs delete mode 100644 crate/bcm2837/src/gpio.rs delete mode 100644 crate/bcm2837/src/interrupt.rs delete mode 100644 crate/bcm2837/src/lib.rs delete mode 100644 crate/bcm2837/src/mailbox.rs delete mode 100644 crate/bcm2837/src/mini_uart.rs delete mode 100644 crate/bcm2837/src/timer/generic_timer.rs delete mode 100644 crate/bcm2837/src/timer/mod.rs delete mode 100644 crate/bcm2837/src/timer/system_timer.rs diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock index e2fe90a..3e48379 100644 --- a/bootloader/Cargo.lock +++ b/bootloader/Cargo.lock @@ -15,6 +15,7 @@ dependencies = [ [[package]] name = "bcm2837" version = "0.1.0" +source = "git+https://github.com/equation314/bcm2837#446f0ea04deb5216ba5e08f10af36e5c1729e6fd" dependencies = [ "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -98,7 +99,7 @@ name = "rcore-bootloader" version = "0.1.0" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", - "bcm2837 0.1.0", + "bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -205,6 +206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aarch64 2.2.2 (git+https://github.com/equation314/aarch64)" = "" +"checksum bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml index 70f7550..09c8b6d 100644 --- a/bootloader/Cargo.toml +++ b/bootloader/Cargo.toml @@ -10,7 +10,7 @@ fixedvec = "0.2.3" [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } -bcm2837 = { path = "../crate/bcm2837" } +bcm2837 = { git = "https://github.com/equation314/bcm2837" } [build-dependencies] cc = "1.0" diff --git a/crate/bcm2837/Cargo.toml b/crate/bcm2837/Cargo.toml deleted file mode 100644 index 18cb598..0000000 --- a/crate/bcm2837/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "bcm2837" -version = "0.1.0" -authors = ["equation314 "] -edition = "2018" - -[features] -zero_kernel_offset = [] -use_generic_timer = ["aarch64"] - -[dependencies] -volatile = "0.2.4" -aarch64= { git = "https://github.com/equation314/aarch64", optional = true } diff --git a/crate/bcm2837/src/atags/atag.rs b/crate/bcm2837/src/atags/atag.rs deleted file mode 100644 index 30315ea..0000000 --- a/crate/bcm2837/src/atags/atag.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::raw; -use core::slice; -use core::str; - -/// An ATAG. -#[derive(Debug, Copy, Clone)] -pub enum Atag { - Core(raw::Core), - Mem(raw::Mem), - Cmd(&'static str), - Unknown(u32), - None, -} - -impl Atag { - /// Returns `Some` if this is a `Core` ATAG. Otherwise returns `None`. - pub fn core(self) -> Option { - match self { - Atag::Core(x) => Some(x), - _ => None, - } - } - - /// Returns `Some` if this is a `Mem` ATAG. Otherwise returns `None`. - pub fn mem(self) -> Option { - match self { - Atag::Mem(x) => Some(x), - _ => None, - } - } - - /// Returns `Some` with the command line string if this is a `Cmd` ATAG. - /// Otherwise returns `None`. - pub fn cmd(self) -> Option<&'static str> { - match self { - Atag::Cmd(x) => Some(x), - _ => None, - } - } -} - -// Convert between raw::* types and Atag wrapper. -impl<'a> From<&'a raw::Atag> for Atag { - fn from(atag: &raw::Atag) -> Atag { - unsafe { - match (atag.tag, &atag.kind) { - (raw::Atag::CORE, &raw::Kind { core }) => Atag::Core(core), - (raw::Atag::MEM, &raw::Kind { mem }) => Atag::Mem(mem), - (raw::Atag::CMDLINE, &raw::Kind { ref cmd }) => { - let cmd_ptr: *const u8 = &cmd.cmd as *const u8; - let mut len: usize = 0; - - while *cmd_ptr.add(len) != 0 { - len += 1; - } - - let cmd_slice = slice::from_raw_parts(cmd_ptr, len); - Atag::Cmd(str::from_utf8_unchecked(cmd_slice)) - } - (raw::Atag::NONE, _) => Atag::None, - (id, _) => Atag::Unknown(id), - } - } - } -} diff --git a/crate/bcm2837/src/atags/mod.rs b/crate/bcm2837/src/atags/mod.rs deleted file mode 100644 index 8787fcc..0000000 --- a/crate/bcm2837/src/atags/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -mod atag; -mod raw; - -use super::consts::KERNEL_OFFSET; -pub use self::atag::*; -pub use self::raw::{Cmd, Core, Mem}; - -/// The address at which the firmware loads the ATAGS. -const ATAG_BASE: usize = KERNEL_OFFSET + 0x100; - -/// An iterator over the ATAGS on this system. -pub struct Atags { - ptr: &'static raw::Atag, -} - -impl Atags { - /// Returns an instance of `Atags`, an iterator over ATAGS on this system. - pub fn get() -> Atags { - Atags { - ptr: unsafe { &*(ATAG_BASE as *const raw::Atag) }, - } - } -} - -impl Iterator for Atags { - type Item = Atag; - - /// Iterate over Atags. Returns a valid Atag until the iterator hits the - /// Atag::None. - fn next(&mut self) -> Option { - let cur = self.ptr; - match cur.next() { - Some(next) => { - let result = Some(Atag::from(cur)); - self.ptr = next; - result - } - None => None, - } - } -} diff --git a/crate/bcm2837/src/atags/raw.rs b/crate/bcm2837/src/atags/raw.rs deleted file mode 100644 index 22bed83..0000000 --- a/crate/bcm2837/src/atags/raw.rs +++ /dev/null @@ -1,65 +0,0 @@ -/// A raw `ATAG` as laid out in memory. -#[repr(C)] -pub struct Atag { - pub dwords: u32, - pub tag: u32, - pub kind: Kind, -} - -impl Atag { - pub const NONE: u32 = 0x00000000; - pub const CORE: u32 = 0x54410001; - pub const MEM: u32 = 0x54410002; - pub const VIDEOTEXT: u32 = 0x54410003; - pub const RAMDISK: u32 = 0x54410004; - pub const INITRD2: u32 = 0x54420005; - pub const SERIAL: u32 = 0x54410006; - pub const REVISION: u32 = 0x54410007; - pub const VIDEOLFB: u32 = 0x54410008; - pub const CMDLINE: u32 = 0x54410009; - - /// Returns the ATAG following `self`, if there is one. - pub fn next(&self) -> Option<&Atag> { - if self.tag == Atag::NONE { - None - } else { - let current = self as *const Atag as *const u32; - let next: &Atag = unsafe { &*(current.add(self.dwords as usize) as *const Atag) }; - - Some(next) - } - } -} - -/// The possible variant of an ATAG. -#[repr(C)] -pub union Kind { - pub core: Core, - pub mem: Mem, - pub cmd: Cmd, -} - -/// A `CORE` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Core { - pub flags: u32, - pub page_size: u32, - pub root_dev: u32, -} - -/// A `MEM` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Mem { - pub size: u32, - pub start: u32, -} - -/// A `CMDLINE` ATAG. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct Cmd { - /// The first byte of the command line string. - pub cmd: u8, -} diff --git a/crate/bcm2837/src/consts.rs b/crate/bcm2837/src/consts.rs deleted file mode 100644 index 92ec433..0000000 --- a/crate/bcm2837/src/consts.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[cfg(feature = "zero_kernel_offset")] -pub const KERNEL_OFFSET: usize = 0; -#[cfg(not(feature = "zero_kernel_offset"))] -pub const KERNEL_OFFSET: usize = 0xFFFF_0000_0000_0000; - -pub const RAW_IO_BASE: usize = 0x3F00_0000; -pub const IO_BASE: usize = KERNEL_OFFSET + RAW_IO_BASE; diff --git a/crate/bcm2837/src/gpio.rs b/crate/bcm2837/src/gpio.rs deleted file mode 100644 index 2bcf901..0000000 --- a/crate/bcm2837/src/gpio.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::consts::IO_BASE; -use crate::timer::delay; -use core::marker::PhantomData; -use volatile::{ReadOnly, Volatile, WriteOnly}; - -/// The base address of the `GPIO` registers. -const GPIO_BASE: usize = IO_BASE + 0x200000; - -/// An alternative GPIO function. (ref: peripherals 6.1, page 92) -#[repr(u8)] -pub enum Function { - Input = 0b000, - Output = 0b001, - Alt0 = 0b100, - Alt1 = 0b101, - Alt2 = 0b110, - Alt3 = 0b111, - Alt4 = 0b011, - Alt5 = 0b010, -} - -/// GPIO registers starting from `GPIO_BASE` (ref: peripherals 6.1, page 90) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - FSEL: [Volatile; 6], - __reserved0: u32, - SET: [WriteOnly; 2], - __reserved1: u32, - CLR: [WriteOnly; 2], - __reserved2: u32, - LEV: [ReadOnly; 2], - __reserved3: u32, - EDS: [Volatile; 2], - __reserved4: u32, - REN: [Volatile; 2], - __reserved5: u32, - FEN: [Volatile; 2], - __reserved6: u32, - HEN: [Volatile; 2], - __reserved7: u32, - LEN: [Volatile; 2], - __reserved8: u32, - AREN: [Volatile; 2], - __reserved9: u32, - AFEN: [Volatile; 2], - __reserved10: u32, - PUD: Volatile, - PUDCLK: [Volatile; 2], -} - -/// Possible states for a GPIO pin. -pub enum Uninitialized {} -pub enum Input {} -pub enum Output {} -pub enum Alt {} - -/// A GPIO pin in state `State`. -/// -/// The `State` generic always corresponds to an uninstantiatable type that is -/// use solely to mark and track the state of a given GPIO pin. A `Gpio` -/// structure starts in the `Uninitialized` state and must be transitions into -/// one of `Input`, `Output`, or `Alt` via the `into_input`, `into_output`, and -/// `into_alt` methods before it can be used. -pub struct Gpio { - pin: u8, - registers: &'static mut Registers, - _state: PhantomData, -} - -impl Gpio { - /// Transitions `self` to state `S`, consuming `self` and returning a new - /// `Gpio` instance in state `S`. This method should _never_ be exposed to - /// the public! - #[inline(always)] - fn transition(self) -> Gpio { - Gpio { - pin: self.pin, - registers: self.registers, - _state: PhantomData, - } - } - - /// Set the Gpio pull-up/pull-down state for values in `pin_value` - /// (ref: peripherals 6.1, page 101) - pub fn set_gpio_pd(&mut self, pud_value: u8) { - let index = if self.pin >= 32 { 1 } else { 0 }; - - self.registers.PUD.write(pud_value as u32); - delay(150); - self.registers.PUDCLK[index as usize].write((1 << self.pin) as u32); - delay(150); - self.registers.PUD.write(0); - self.registers.PUDCLK[index as usize].write(0); - } -} - -impl Gpio { - /// Returns a new `GPIO` structure for pin number `pin`. - /// - /// # Panics - /// - /// Panics if `pin` > `53`. - pub fn new(pin: u8) -> Gpio { - if pin > 53 { - panic!("Gpio::new(): pin {} exceeds maximum of 53", pin); - } - - Gpio { - registers: unsafe { &mut *(GPIO_BASE as *mut Registers) }, - pin: pin, - _state: PhantomData, - } - } - - /// Enables the alternative function `function` for `self`. Consumes self - /// and returns a `Gpio` structure in the `Alt` state. - pub fn into_alt(self, function: Function) -> Gpio { - let select = (self.pin / 10) as usize; - let offset = 3 * (self.pin % 10) as usize; - self.registers.FSEL[select].update(|value| { - *value &= !(0b111 << offset); - *value |= (function as u32) << offset; - }); - self.transition() - } - - /// Sets this pin to be an _output_ pin. Consumes self and returns a `Gpio` - /// structure in the `Output` state. - pub fn into_output(self) -> Gpio { - self.into_alt(Function::Output).transition() - } - - /// Sets this pin to be an _input_ pin. Consumes self and returns a `Gpio` - /// structure in the `Input` state. - pub fn into_input(self) -> Gpio { - self.into_alt(Function::Input).transition() - } -} - -impl Gpio { - /// Sets (turns on) the pin. - pub fn set(&mut self) { - let index = if self.pin >= 32 { 1 } else { 0 }; - self.registers.SET[index as usize].write(1 << (self.pin - index * 32)); - } - - /// Clears (turns off) the pin. - pub fn clear(&mut self) { - let index = if self.pin >= 32 { 1 } else { 0 }; - self.registers.CLR[index as usize].write(1 << (self.pin - index * 32)); - } -} - -impl Gpio { - /// Reads the pin's value. Returns `true` if the level is high and `false` - /// if the level is low. - pub fn level(&mut self) -> bool { - let index = if self.pin >= 32 { 1 } else { 0 }; - let high = 1 << (self.pin - index * 32); - (self.registers.LEV[index as usize].read() & high) == high - } -} diff --git a/crate/bcm2837/src/interrupt.rs b/crate/bcm2837/src/interrupt.rs deleted file mode 100644 index d3caba6..0000000 --- a/crate/bcm2837/src/interrupt.rs +++ /dev/null @@ -1,88 +0,0 @@ -use crate::consts::IO_BASE; -use volatile::{ReadOnly, Volatile}; - -const INT_BASE: usize = IO_BASE + 0xB000 + 0x200; - -/// Allowed interrupts (ref: peripherals 7.5, page 113) -#[repr(u8)] -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum Interrupt { - Timer1 = 1, - Timer3 = 3, - Usb = 9, - Aux = 29, - Gpio0 = 49, - Gpio1 = 50, - Gpio2 = 51, - Gpio3 = 52, - Uart = 57, -} - -/// Interrupts registers starting from `INT_BASE` (ref: peripherals 7.5, page 112) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - IRQBasicPending: ReadOnly, - IRQPending: [ReadOnly; 2], - FIQControl: Volatile, - EnableIRQ: [Volatile; 2], - EnableBasicIRQ: Volatile, - DisableIRQ: [Volatile; 2], - DisableBasicIRQ: Volatile, -} - -/// Pending interrupts -pub struct PendingInterrupts(u64); - -impl Iterator for PendingInterrupts { - type Item = usize; - - #[inline] - fn next(&mut self) -> Option { - let int = self.0.trailing_zeros(); - if int < 64 { - self.0 &= !(1 << int); - Some(int as usize) - } else { - None - } - } -} - -/// An interrupt controller. Used to enable and disable interrupts as well as to -/// check if an interrupt is pending. -pub struct Controller { - registers: &'static mut Registers, -} - -impl Controller { - /// Returns a new handle to the interrupt controller. - #[inline] - pub fn new() -> Controller { - Controller { - registers: unsafe { &mut *(INT_BASE as *mut Registers) }, - } - } - - /// Enables the interrupt `int`. - pub fn enable(&mut self, int: Interrupt) { - self.registers.EnableIRQ[int as usize / 32].write(1 << (int as usize) % 32); - } - - /// Disables the interrupt `int`. - pub fn disable(&mut self, int: Interrupt) { - self.registers.DisableIRQ[int as usize / 32].write(1 << (int as usize) % 32); - } - - /// Returns `true` if `int` is pending. Otherwise, returns `false`. - pub fn is_pending(&self, int: Interrupt) -> bool { - self.registers.IRQPending[int as usize / 32].read() & (1 << (int as usize) % 32) != 0 - } - - /// Return all pending interrupts. - pub fn pending_interrupts(&self) -> PendingInterrupts { - let irq1 = self.registers.IRQPending[0].read() as u64; - let irq2 = self.registers.IRQPending[1].read() as u64; - PendingInterrupts((irq2 << 32) | irq1) - } -} diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs deleted file mode 100644 index ba9cc2a..0000000 --- a/crate/bcm2837/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![no_std] -#![feature(asm)] - -extern crate volatile; - -pub mod atags; -pub mod consts; -pub mod gpio; -pub mod interrupt; -pub mod mailbox; -pub mod mini_uart; -pub mod timer; diff --git a/crate/bcm2837/src/mailbox.rs b/crate/bcm2837/src/mailbox.rs deleted file mode 100644 index e20c0ff..0000000 --- a/crate/bcm2837/src/mailbox.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::consts::IO_BASE; -use volatile::{ReadOnly, Volatile, WriteOnly}; - -/// The base address for the `MU` registers. -const MAILBOX_BASE: usize = IO_BASE + 0xB000 + 0x880; - -/// Available mailbox channels -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) -#[repr(u8)] -#[derive(Copy, Clone, Debug)] -pub enum MailboxChannel { - Framebuffer = 1, - Property = 8, -} - -/// Read from mailbox status register (MAILx_STA). -#[repr(u32)] -enum MailboxStatus { - MailboxEmpty = 1 << 30, - MailboxFull = 1 << 31, -} - -/// Mailbox registers. We basically only support mailbox 0 & 1. We -/// deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See -/// BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about -/// the placement of memory barriers. -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - MAIL0_RD: ReadOnly, // 0x00 - __reserved0: [u32; 3], - MAIL0_POL: ReadOnly, // 0x10 - MAIL0_SND: ReadOnly, // 0x14 - MAIL0_STA: ReadOnly, // 0x18 - MAIL0_CNF: Volatile, // 0x1c - - MAIL1_WRT: WriteOnly, // 0x20 - __reserved1: [u32; 3], - _MAIL1_POL: ReadOnly, // 0x30 - _MAIL1_SND: ReadOnly, // 0x34 - MAIL1_STA: ReadOnly, // 0x38 - _MAIL1_CNF: Volatile, // 0x3c -} - -/// The Raspberry Pi's mailbox. -/// -/// (ref: https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) -pub struct Mailbox { - registers: &'static mut Registers, -} - -impl Mailbox { - /// Returns a new instance of `Mailbox`. - #[inline] - pub fn new() -> Mailbox { - Mailbox { - registers: unsafe { &mut *(MAILBOX_BASE as *mut Registers) }, - } - } - - /// Read from the requested channel of mailbox 0. - pub fn read(&self, channel: MailboxChannel) -> u32 { - loop { - while self.registers.MAIL0_STA.read() & (MailboxStatus::MailboxEmpty as u32) != 0 {} - let data = self.registers.MAIL0_RD.read(); - if data & 0xF == channel as u32 { - return data & !0xF; - } - } - } - - /// Write to the requested channel of mailbox 1. - pub fn write(&mut self, channel: MailboxChannel, data: u32) { - while self.registers.MAIL1_STA.read() & (MailboxStatus::MailboxFull as u32) != 0 {} - self.registers.MAIL1_WRT.write((data & !0xF) | (channel as u32)); - } -} diff --git a/crate/bcm2837/src/mini_uart.rs b/crate/bcm2837/src/mini_uart.rs deleted file mode 100644 index 9606cf8..0000000 --- a/crate/bcm2837/src/mini_uart.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::consts::IO_BASE; -use crate::gpio::{Function, Gpio}; -use volatile::{ReadOnly, Volatile}; - -/// The `AUXENB` register from page 9 of the BCM2837 documentation. -const AUX_ENABLES: *mut Volatile = (IO_BASE + 0x215004) as *mut Volatile; - -/// The base address for the `MU` registers. -const MU_REG_BASE: usize = IO_BASE + 0x215040; - -/// Enum representing bit fields of the `AUX_MU_IIR_REG` register. -#[repr(u8)] -pub enum MiniUartInterruptId { - Transmit = 0b010, - Recive = 0b100, -} - -/// Enum representing bit fields of the `AUX_MU_LSR_REG` register. -#[repr(u8)] -enum LsrStatus { - DataReady = 1, - TxAvailable = 1 << 5, -} - -/// MU registers starting from `MU_REG_BASE` (ref: peripherals 2.1, page 8) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - AUX_MU_IO_REG: Volatile, - __r0: [u8; 3], - AUX_MU_IER_REG: Volatile, - __r1: [u8; 3], - AUX_MU_IIR_REG: Volatile, - __r2: [u8; 3], - AUX_MU_LCR_REG: Volatile, - __r3: [u8; 3], - AUX_MU_MCR_REG: Volatile, - __r4: [u8; 3], - AUX_MU_LSR_REG: ReadOnly, - __r5: [u8; 3], - AUX_MU_MSR_REG: ReadOnly, - __r6: [u8; 3], - AUX_MU_SCRATCH: Volatile, - __r7: [u8; 3], - AUX_MU_CNTL_REG: Volatile, - __r8: [u8; 3], - AUX_MU_STAT_REG: ReadOnly, - AUX_MU_BAUD_REG: Volatile, -} - -/// The Raspberry Pi's "mini UART". -pub struct MiniUart { - registers: &'static mut Registers, - timeout: Option, -} - -impl MiniUart { - /// Returns a new instance of `MiniUart`. - #[inline] - pub fn new() -> MiniUart { - let registers = unsafe { &mut *(MU_REG_BASE as *mut Registers) }; - - MiniUart { - registers: registers, - timeout: None, - } - } - - /// Initializes the mini UART by enabling it as an auxiliary peripheral, - /// setting the data size to 8 bits, setting the BAUD rate to ~115200 (baud - /// divider of 270), setting GPIO pins 14 and 15 to alternative function 5 - /// (TXD1/RDXD1), and finally enabling the UART transmitter and receiver. - /// - /// By default, reads will never time out. To set a read timeout, use - /// `set_read_timeout()`. - pub fn init(&mut self) { - // Enable the mini UART as an auxiliary device. - unsafe { (*AUX_ENABLES).write(1) } - - Gpio::new(14).into_alt(Function::Alt5).set_gpio_pd(0); - Gpio::new(15).into_alt(Function::Alt5).set_gpio_pd(0); - - self.registers.AUX_MU_CNTL_REG.write(0); // Disable auto flow control and disable receiver and transmitter (for now) - self.registers.AUX_MU_IER_REG.write(1); // Enable receive interrupts and disable transmit interrupts - self.registers.AUX_MU_LCR_REG.write(3); // Enable 8 bit mode - self.registers.AUX_MU_MCR_REG.write(0); // Set RTS line to be always high - self.registers.AUX_MU_BAUD_REG.write(270); // Set baud rate to 115200 - - self.registers.AUX_MU_CNTL_REG.write(3); // Finally, enable transmitter and receiver - } - - /// Set the read timeout to `milliseconds` milliseconds. - pub fn set_read_timeout(&mut self, milliseconds: u32) { - self.timeout = Some(milliseconds) - } - - /// Write the byte `byte`. This method blocks until there is space available - /// in the output FIFO. - pub fn write_byte(&mut self, byte: u8) { - while self.registers.AUX_MU_LSR_REG.read() & (LsrStatus::TxAvailable as u8) == 0 {} - self.registers.AUX_MU_IO_REG.write(byte); - } - - /// Returns `true` if there is at least one byte ready to be read. If this - /// method returns `true`, a subsequent call to `read_byte` is guaranteed to - /// return immediately. This method does not block. - pub fn has_byte(&self) -> bool { - self.registers.AUX_MU_LSR_REG.read() & (LsrStatus::DataReady as u8) != 0 - } - - /// Blocks until there is a byte ready to read. If a read timeout is set, - /// this method blocks for at most that amount of time. Otherwise, this - /// method blocks indefinitely until there is a byte to read. - /// - /// Returns `Ok(())` if a byte is ready to read. Returns `Err(())` if the - /// timeout expired while waiting for a byte to be ready. If this method - /// returns `Ok(())`, a subsequent call to `read_byte` is guaranteed to - /// return immediately. - pub fn wait_for_byte(&self) -> Result<(), ()> { - unimplemented!() - } - - /// Reads a byte. Blocks indefinitely until a byte is ready to be read. - pub fn read_byte(&self) -> u8 { - while !self.has_byte() {} - self.registers.AUX_MU_IO_REG.read() - } - - // Read `AUX_MU_IIR_REG` and determine if the interrupt `id` is pending. - pub fn interrupt_is_pending(&self, id: MiniUartInterruptId) -> bool { - self.registers.AUX_MU_IIR_REG.read() & 0b110 == id as u8 - } -} diff --git a/crate/bcm2837/src/timer/generic_timer.rs b/crate/bcm2837/src/timer/generic_timer.rs deleted file mode 100644 index 9128dce..0000000 --- a/crate/bcm2837/src/timer/generic_timer.rs +++ /dev/null @@ -1,77 +0,0 @@ -extern crate aarch64; - -use super::BasicTimer; -use crate::consts::KERNEL_OFFSET; -use aarch64::regs::*; -use volatile::*; - -/// The base address for the ARM generic timer, IRQs, mailboxes -const GEN_TIMER_REG_BASE: usize = KERNEL_OFFSET + 0x4000_0000; - -/// Core interrupt sources (ref: QA7 4.10, page 16) -#[repr(u8)] -#[allow(dead_code)] -#[allow(non_snake_case)] -#[derive(Copy, Clone, PartialEq, Debug)] -enum CoreInterrupt { - CNTPSIRQ = 0, - CNTPNSIRQ = 1, - CNTHPIRQ = 2, - CNTVIRQ = 3, - Mailbox0 = 4, - Mailbox1 = 5, - Mailbox2 = 6, - Mailbox3 = 7, - Gpu = 8, - Pmu = 9, - AxiOutstanding = 10, - LocalTimer = 11, -} - -/// Timer, IRQs, mailboxes registers (ref: QA7 chapter 4, page 7) -#[allow(non_snake_case)] -#[repr(C)] -struct Registers { - CONTROL: Volatile, - _unused1: [Volatile; 8], - LOCAL_IRQ: Volatile, - _unused2: [Volatile; 3], - LOCAL_TIMER_CTL: Volatile, - LOCAL_TIMER_FLAGS: Volatile, - _unused3: Volatile, - CORE_TIMER_IRQCNTL: [Volatile; 4], - CORE_MAILBOX_IRQCNTL: [Volatile; 4], - CORE_IRQ_SRC: [Volatile; 4], -} - -/// The ARM generic timer. -pub struct GenericTimer { - registers: &'static mut Registers, -} - -impl BasicTimer for GenericTimer { - fn new() -> Self { - GenericTimer { - registers: unsafe { &mut *(GEN_TIMER_REG_BASE as *mut Registers) }, - } - } - - fn init(&mut self) { - self.registers.CORE_TIMER_IRQCNTL[0].write(1 << (CoreInterrupt::CNTPNSIRQ as u8)); - CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET); - } - - fn read(&self) -> u64 { - let cntfrq = CNTFRQ_EL0.get(); // 62500000 - (CNTPCT_EL0.get() * 1000000 / (cntfrq as u64)) as u64 - } - - fn tick_in(&mut self, us: u32) { - let cntfrq = CNTFRQ_EL0.get(); // 62500000 - CNTP_TVAL_EL0.set(((cntfrq as f64) * (us as f64) / 1000000.0) as u32); - } - - fn is_pending(&self) -> bool { - self.registers.CORE_IRQ_SRC[0].read() & (1 << (CoreInterrupt::CNTPNSIRQ as u8)) != 0 - } -} diff --git a/crate/bcm2837/src/timer/mod.rs b/crate/bcm2837/src/timer/mod.rs deleted file mode 100644 index e628a99..0000000 --- a/crate/bcm2837/src/timer/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -#[cfg(feature = "use_generic_timer")] -mod generic_timer; -#[cfg(feature = "use_generic_timer")] -pub use self::generic_timer::GenericTimer as Timer; - -#[cfg(not(feature = "use_generic_timer"))] -mod system_timer; -#[cfg(not(feature = "use_generic_timer"))] -pub use self::system_timer::SystemTimer as Timer; - -/// The Raspberry Pi timer. -pub trait BasicTimer { - /// Returns a new instance. - fn new() -> Self; - - /// Initialization timer. - fn init(&mut self); - - /// Reads the timer's counter and returns the 64-bit counter value. - /// The returned value is the number of elapsed microseconds. - fn read(&self) -> u64; - - /// Sets up a match in timer 1 to occur `us` microseconds from now. If - /// interrupts for timer 1 are enabled and IRQs are unmasked, then a timer - /// interrupt will be issued in `us` microseconds. - fn tick_in(&mut self, us: u32); - - /// Returns `true` if timer interruption is pending. Otherwise, returns `false`. - fn is_pending(&self) -> bool; -} - -/// wait for `cycle` CPU cycles -#[inline(always)] -pub fn delay(cycle: u32) { - for _ in 0..cycle { - unsafe { asm!("nop") } - } -} diff --git a/crate/bcm2837/src/timer/system_timer.rs b/crate/bcm2837/src/timer/system_timer.rs deleted file mode 100644 index 6ad1d85..0000000 --- a/crate/bcm2837/src/timer/system_timer.rs +++ /dev/null @@ -1,62 +0,0 @@ -use super::BasicTimer; -use crate::consts::IO_BASE; -use crate::interrupt::{Controller, Interrupt}; -use volatile::{ReadOnly, Volatile}; - -/// The base address for the ARM system timer registers. -const TIMER_REG_BASE: usize = IO_BASE + 0x3000; - -/// System timer registers (ref: peripherals 12.1, page 172) -#[repr(C)] -#[allow(non_snake_case)] -struct Registers { - CS: Volatile, - CLO: ReadOnly, - CHI: ReadOnly, - COMPARE: [Volatile; 4], -} - -#[repr(u8)] -#[allow(dead_code)] -#[derive(Copy, Clone, PartialEq, Debug)] -enum SystemTimerId { - Timer0 = 0, - Timer1 = 1, - Timer2 = 2, - Timer3 = 3, -} - -/// The Raspberry Pi ARM system timer. -pub struct SystemTimer { - registers: &'static mut Registers, -} - -impl BasicTimer for SystemTimer { - fn new() -> Self { - SystemTimer { - registers: unsafe { &mut *(TIMER_REG_BASE as *mut Registers) }, - } - } - - fn init(&mut self) { - Controller::new().enable(Interrupt::Timer1); - } - - fn read(&self) -> u64 { - let low = self.registers.CLO.read(); - let high = self.registers.CHI.read(); - ((high as u64) << 32) | (low as u64) - } - - fn tick_in(&mut self, us: u32) { - let current_low = self.registers.CLO.read(); - let compare = current_low.wrapping_add(us); - self.registers.COMPARE[SystemTimerId::Timer1 as usize].write(compare); - self.registers.CS.write(1 << (SystemTimerId::Timer1 as usize)); // unmask - } - - fn is_pending(&self) -> bool { - let controller = Controller::new(); - controller.is_pending(Interrupt::Timer1) - } -} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index fe415ce..2468c5d 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -45,6 +45,7 @@ version = "0.1.0" [[package]] name = "bcm2837" version = "0.1.0" +source = "git+https://github.com/equation314/bcm2837#446f0ea04deb5216ba5e08f10af36e5c1729e6fd" dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -248,7 +249,7 @@ dependencies = [ "aarch64 2.2.2 (git+https://github.com/equation314/aarch64)", "apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)", "bbl 0.1.0", - "bcm2837 0.1.0", + "bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)", "bit-allocator 0.1.0", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -525,6 +526,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum apic 0.1.0 (git+https://github.com/wangrunji0408/APIC-Rust)" = "" "checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" "checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a" +"checksum bcm2837 0.1.0 (git+https://github.com/equation314/bcm2837)" = "" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bitvec 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cfadef5c4e2c2e64067b9ecc061179f12ac7ec65ba613b1f60f3972bbada1f5b" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6b26913..159e350 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -72,7 +72,7 @@ bbl = { path = "../crate/bbl" } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64 = { git = "https://github.com/equation314/aarch64" } -bcm2837 = { path = "../crate/bcm2837", optional = true } +bcm2837 = { git = "https://github.com/equation314/bcm2837", optional = true } [package.metadata.bootimage] default-target = "targets/x86_64.json" From 681c0be8011b5f40b91d9f39eb56c1898f333795 Mon Sep 17 00:00:00 2001 From: equation314 Date: Tue, 12 Mar 2019 01:28:28 +0800 Subject: [PATCH 7/8] aarch64: fix the potential memory overlapping bug of bootloader --- bootloader/build.rs | 2 +- bootloader/src/arch/aarch64/boot.ld | 4 ++++ kernel/src/arch/aarch64/boot/entry.S | 1 + kernel/src/arch/aarch64/boot/linker.ld | 12 +++++++----- kernel/src/arch/aarch64/memory.rs | 5 +++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/bootloader/build.rs b/bootloader/build.rs index b4e87e8..958e977 100644 --- a/bootloader/build.rs +++ b/bootloader/build.rs @@ -25,7 +25,7 @@ fn gen_payload_asm() -> Result { write!(f, "# generated by build.rs - do not edit")?; write!(f, r#" - .section .rodata + .section .payload,"a" .align 12 .global _kernel_payload_start, _kernel_payload_end _kernel_payload_start: diff --git a/bootloader/src/arch/aarch64/boot.ld b/bootloader/src/arch/aarch64/boot.ld index 20c42ab..3e95fe5 100644 --- a/bootloader/src/arch/aarch64/boot.ld +++ b/bootloader/src/arch/aarch64/boot.ld @@ -27,5 +27,9 @@ SECTIONS { _ebss = .; } + .payload : { + *(.payload) + } + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } } diff --git a/kernel/src/arch/aarch64/boot/entry.S b/kernel/src/arch/aarch64/boot/entry.S index e2a22f4..3cf258d 100644 --- a/kernel/src/arch/aarch64/boot/entry.S +++ b/kernel/src/arch/aarch64/boot/entry.S @@ -5,3 +5,4 @@ _start: ldr x0, =bootstacktop mov sp, x0 bl rust_main +1: b 1b diff --git a/kernel/src/arch/aarch64/boot/linker.ld b/kernel/src/arch/aarch64/boot/linker.ld index e8a1046..c82f537 100644 --- a/kernel/src/arch/aarch64/boot/linker.ld +++ b/kernel/src/arch/aarch64/boot/linker.ld @@ -2,7 +2,6 @@ ENTRY(_start) SECTIONS { . = 0xffff000000100000; /* Load the kernel at this address. It's also kernel stack top address */ - bootstacktop = .; .text : { stext = .; @@ -35,12 +34,15 @@ SECTIONS { ebss = .; } + .stack : { + . = ALIGN(4K); + bootstack = .; + . += 0x100000; + bootstacktop = .; + } + /* end of the binary */ _end = ALIGN(8); - /* number of bytes in BSS section and complete binary */ - __bss_length = (ebss - sbss); - __binary_length = (_end - _start); - /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } } diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index c40a055..6de1ba8 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -47,11 +47,11 @@ static mut KERNEL_MEMORY_SET: Option = None; fn remap_the_kernel() { let offset = -(KERNEL_OFFSET as isize); let mut ms = MemorySet::new_bare(); - ms.push(KERNEL_OFFSET, bootstacktop as usize, Linear::new(offset, MemoryAttr::default()), "kstack"); ms.push(stext as usize, etext as usize, Linear::new(offset, MemoryAttr::default().execute().readonly()), "text"); ms.push(sdata as usize, edata as usize, Linear::new(offset, MemoryAttr::default()), "data"); ms.push(srodata as usize, erodata as usize, Linear::new(offset, MemoryAttr::default().readonly()), "rodata"); ms.push(sbss as usize, ebss as usize, Linear::new(offset, MemoryAttr::default()), "bss"); + ms.push(bootstack as usize, bootstacktop as usize, Linear::new(offset, MemoryAttr::default()), "kstack"); use super::board::{IO_REMAP_BASE, IO_REMAP_END}; ms.push(IO_REMAP_BASE, IO_REMAP_END, Linear::new(offset, MemoryAttr::default().mmio(MMIOType::Device as u8)), "io_remap"); @@ -73,7 +73,6 @@ pub fn ioremap(paddr: usize, len: usize, name: &'static str) -> usize { } extern "C" { - fn bootstacktop(); fn stext(); fn etext(); fn sdata(); @@ -82,6 +81,8 @@ extern "C" { fn erodata(); fn sbss(); fn ebss(); + fn bootstack(); + fn bootstacktop(); fn _start(); fn _end(); } From eb1e72d6ec86aebf22b68bdb1eb5c7f341b115f2 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sat, 16 Mar 2019 21:03:15 +0800 Subject: [PATCH 8/8] aarch64: reverse program headers to avoid overlapping in memory copying --- bootloader/src/arch/aarch64/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/bootloader/src/arch/aarch64/mod.rs b/bootloader/src/arch/aarch64/mod.rs index 2ba1473..3aa3762 100644 --- a/bootloader/src/arch/aarch64/mod.rs +++ b/bootloader/src/arch/aarch64/mod.rs @@ -99,8 +99,15 @@ fn enable_mmu() { } pub fn map_kernel(kernel_start: usize, segments: &FixedVec) { + // reverse program headers to avoid overlapping in memory copying + let mut space = alloc_stack!([ProgramHeader64; 32]); + let mut rev_segments = FixedVec::new(&mut space); + for i in (0..segments.len()).rev() { + rev_segments.push(segments[i]).unwrap(); + } + let (mut start_vaddr, mut end_vaddr) = (VirtAddr::new(core::u64::MAX), VirtAddr::zero()); - for segment in segments { + for segment in &rev_segments { if segment.get_type() != Ok(Type::Load) { continue; }