diff --git a/kernel/.cargo/config.toml b/kernel/.cargo/config.toml index 94da74e..f0c003a 100644 --- a/kernel/.cargo/config.toml +++ b/kernel/.cargo/config.toml @@ -14,7 +14,8 @@ unstable-options = true [target.riscv64imac-unknown-none-elf] rustflags = [ - "-Ztls-model=local-exec" + "-Ztls-model=local-exec", + "-Clink-arg=-Tkernel/src/arch/riscv/linker.lds_pp" ] [env] diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 0679ec9..fb6e1c9 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -3,11 +3,6 @@ name = "rel4_kernel" version = "0.1.0" edition = "2021" -[lib] -name = "rustlib" -path = "src/lib.rs" -crate-type = ["staticlib"] - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/kernel/src/arch/riscv/head.S b/kernel/src/arch/riscv/head.S new file mode 100644 index 0000000..ffdb1aa --- /dev/null +++ b/kernel/src/arch/riscv/head.S @@ -0,0 +1,20 @@ + +.section .boot.text, "ax" +.global _start +.extern init_kernel +.extern kernel_stack_alloc +.extern __global_pointer$ +.extern restore_user_context + +_start: + fence.i +.option push +.option norelax +1:auipc gp, %pcrel_hi(__global_pointer$) + addi gp, gp, %pcrel_lo(1b) +.option pop + la sp, (kernel_stack_alloc + (1ul << (12))) + csrw sscratch, x0 + jal init_kernel + la ra, restore_user_context + jr ra diff --git a/kernel/src/arch/riscv/linker.lds_pp b/kernel/src/arch/riscv/linker.lds_pp new file mode 100644 index 0000000..9beac54 --- /dev/null +++ b/kernel/src/arch/riscv/linker.lds_pp @@ -0,0 +1,318 @@ +/* + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * Copyright 2015, 2016 Hesham Almatary + * Copyright 2021, HENSOLDT Cyber + * Copyright 2023, DornerWorks + * + * SPDX-License-Identifier: GPL-2.0-only + */ +OUTPUT_ARCH(riscv) +ENTRY(_start) +/* + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/* + * Copyright 2014, General Dynamics C4 Systems + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* Compile-time configuration parameters. Might be set by the build system. */ + + +/* disabled: CONFIG_ARCH_AARCH32 */ +/* disabled: CONFIG_ARCH_AARCH64 */ +/* disabled: CONFIG_ARCH_ARM_HYP */ +/* disabled: CONFIG_ARCH_RISCV32 */ +/* disabled: CONFIG_ARCH_X86_64 */ +/* disabled: CONFIG_ARCH_IA32 */ +/* disabled: CONFIG_ARM_CORTEX_A7 */ +/* disabled: CONFIG_ARM_CORTEX_A8 */ +/* disabled: CONFIG_ARM_CORTEX_A9 */ +/* disabled: CONFIG_ARM_CORTEX_A15 */ +/* disabled: CONFIG_ARM_CORTEX_A35 */ +/* disabled: CONFIG_ARM_CORTEX_A53 */ +/* disabled: CONFIG_ARM_CORTEX_A55 */ +/* disabled: CONFIG_ARM_CORTEX_A57 */ +/* disabled: CONFIG_ARM_CORTEX_A72 */ +/* disabled: CONFIG_ARCH_ARM_V7A */ +/* disabled: CONFIG_ARCH_ARM_V7VE */ +/* disabled: CONFIG_ARCH_ARM_V8A */ +/* disabled: CONFIG_AARCH64_SERROR_IGNORE */ +/* disabled: CONFIG_KERNEL_MCS */ +/* disabled: CONFIG_RISCV_EXT_F */ +/* disabled: CONFIG_RISCV_EXT_D */ +/* disabled: CONFIG_EXPORT_PCNT_USER */ +/* disabled: CONFIG_EXPORT_VCNT_USER */ +/* disabled: CONFIG_EXPORT_PTMR_USER */ +/* disabled: CONFIG_EXPORT_VTMR_USER */ +/* disabled: CONFIG_HAVE_FPU */ +/* disabled: CONFIG_EXCEPTION_FASTPATH */ +/* disabled: CONFIG_SIGNAL_FASTPATH */ +/* disabled: CONFIG_ENABLE_SMP_SUPPORT */ +/* disabled: CONFIG_VERIFICATION_BUILD */ +/* disabled: CONFIG_BINARY_VERIFICATION_BUILD */ +/* disabled: CONFIG_HARDWARE_DEBUG_API */ +/* disabled: CONFIG_KERNEL_INVOCATION_REPORT_ERROR_IPC */ +/* disabled: CONFIG_BENCHMARK_GENERIC */ +/* disabled: CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES */ +/* disabled: CONFIG_BENCHMARK_TRACEPOINTS */ +/* disabled: CONFIG_BENCHMARK_TRACK_UTILISATION */ +/* disabled: CONFIG_ENABLE_BENCHMARKS */ +/* disabled: CONFIG_KERNEL_LOG_BUFFER */ +/* disabled: CONFIG_KERNEL_OPT_LEVEL_OS */ +/* disabled: CONFIG_KERNEL_OPT_LEVEL_O0 */ +/* disabled: CONFIG_KERNEL_OPT_LEVEL_O1 */ +/* disabled: CONFIG_KERNEL_OPT_LEVEL_O3 */ +/* disabled: CONFIG_KERNEL_FWHOLE_PROGRAM */ +/* disabled: CONFIG_DANGEROUS_CODE_INJECTION */ +/* disabled: CONFIG_DEBUG_DISABLE_PREFETCHERS */ +/* disabled: CONFIG_SET_TLS_BASE_SELF */ +/* disabled: CONFIG_CLZ_32 */ +/* disabled: CONFIG_CTZ_32 */ +/* disabled: CONFIG_CLZ_NO_BUILTIN */ +/* disabled: CONFIG_CTZ_NO_BUILTIN */ +/* disabled: CONFIG_LINUX_APP_SUPPORT */ +/* Set ENABLE_SMP_SUPPORT for kernel source files */ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/* Each architecture defines a set of constants in #defines. These + * constants describe the memory regions of the kernel's portion of the + * address space including the physical memory window, the kernel ELF + * region, and the device region. + * + * - USER_TOP: The first address after the end of user memory + * + * - PADDR_BASE: The first physical address mapped in the kernel's + * physical memory window. + * - PPTR_BASE: The first virtual address of the kernel's physical + * memory window. + * - PPTR_TOP: The first virtual address after the end of the kernel's + * physical memory window. + * + * - KERNEL_ELF_PADDR_BASE: The first physical address used to map the + * initial kernel image. The kernel ELF is mapped contiguously + * starting at this address. + * - KERNEL_ELF_BASE: The first virtual address used to map the initial + * kernel image. + * + * - KDEV_BASE: The first virtual address used to map devices. + */ +/* The offset from a physical address to a virtual address in the + * physical memory window. */ +/* The last address in the physical memory region mapped into the + * physical memory window */ +/* The kernel base offset is a way to translate the kernel image segment + * from virtual to physical. This translation must be a single offset + * for for the entire segment (i.e. the kernel image must be contiguous + * both virtually and physically) */ +/* + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/* + * Copyright 2014, General Dynamics C4 Systems + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/* Provide a helper macro to define integer constants that are not of the + * default type 'int', but 'unsigned long [long]'. When such constants are + * shared between assembly and C code, some assemblers will fail because they + * don't support C-style integer suffixes like 'ul'. Using a macro works around + * this, as the suffix is only applied when the C compiler is used and dropped + * when the assembler runs. + */ +/* Time constants are defined to use the 'unsigned long long'. Rationale is, + * that the C rules define the calculation result is determined by largest type + * involved. Enforcing the largest possible type C provides avoids pitfalls with + * 32-bit overflows when values are getting quite large. Keep in mind that even + * 2^32 milli-seconds roll over within 50 days, which is an uptime that embedded + * systems will reach easily and it resembles not even two months in a calendar + * calculation. In addition, using the largest integer type C currently defines + * enforces that all calculations results need a cast back to a 32-bit type + * explicitly. This might feel annoying, but practically it makes code more + * robust and enforces thinking about potential overflows. + * Note that at this stage of the includes, we do not have defined the type + * uint64_t yet, so we can't use any definitions around it, but have to stick to + * plain C types. Neither moving the time constant definitions behind the + * uint64_t type definitions nor including the header with the uint64_t + * definitions here is currently a feasible option. + */ +/* + * The top half of the address space is reserved for the kernel. This means that 256 top level + * entries are for the user, and 256 are for the kernel. This will be further split into the + * 'regular' kernel window, which contains mappings to physical memory, a small (1GiB) higher + * kernel image window that we use for running the actual kernel from and a top 1GiB window for + * kernel device mappings. This means that between PPTR_BASE and + * KERNEL_ELF_BASE there are 254 entries remaining, which represents how much physical memory + * can be used. + * + * Almost all of the top 256 kernel entries will contain 1GiB page mappings. The only 2 entries + * that contain a 2nd level PageTable consisting of 2MiB page entries is the entry + * for the 1GiB Kernel ELF region and the 1GiB region corresponding to the physical memory + * of the kernel ELF in the kernel window. The same 2nd level PageTable is used and so both + * entries refer to the same 1GiB of physical memory. + * This means that the 1GiB kernel ELF mapping will correspond to physical memory with a 1GiB + * alignment. + * + * +-----------------------------+ 2^64 + * | Kernel Devices | + * -> +-------------------KDEV_BASE-+ 2^64 - 1GiB + * | | Kernel ELF | + * ----| +-------------KERNEL_ELF_BASE-+ --+ 2^64 - 2GiB + (KERNEL_ELF_PADDR_BASE % 1GiB) + * | | | | + * | -> +-----------------------------+ --+ 2^64 - 2GiB = (KERNEL_ELF_BASE % 1GiB) + * Shared 1GiB| | | | + * table entry| | PSpace | | + * | | (direct kernel mappings) | +----+ + * ------>| | | | + * | | | | + * +-------------------PPTR_BASE-+ --+ 2^64 - 2^b + * | | | +-------------------------+ + * | | | | | + * | | | | | + * | Invalid | | | | + * | | | | not | + * | | | | kernel | + * | | | | addressable | + * +--------------------USER_TOP-+ 2^c | | | + * | | | | | + * | | | | | + * | | | +- --------------------------+ PADDR_TOP = + * | | | | | | PPTR_TOP - PPTR_BASE + * | | | | | | + * | | | | | | + * | User | | | | | + * | | | | | | + * | | +------+ +-------------------------+ KDEV_BASE - KERNEL_ELF_BASE + PADDR_LOAD + * | | kernel | | Kernel ELF | + * | | addressable | +-------------------------+ KERNEL_ELF_PADDR_BASE + * | | | | | + * | | | | | + * +-----------------------------+ 0 +- +-------------------------+ 0 PADDR_BASE + * + * virtual address space physical address space + * + * + * c = one less than number of bits the page tables can translate + * = sign extension bit for canonical addresses + * (= 47 on x64, 38 on RISCV64 sv39, 47 on RISCV64 sv48) + * b = The number of bits used by kernel mapping. + * = 38 (half of the 1 level page table) on RISCV64 sc39 + * = 39 (entire second level page table) on aarch64 / X64 / sv48 + */ +/* last accessible virtual address in user space */ +/* The first physical address to map into the kernel's physical memory + * window */ +/* The base address in virtual memory to use for the 1:1 physical memory + * mapping */ +/* Top of the physical memory window */ +/* The physical memory address to use for mapping the kernel ELF */ +/* This represents the physical address that the kernel image will be linked to. This needs to + * be on a 1gb boundary as we currently require being able to creating a mapping to this address + * as the largest frame size */ +/* For use by the linker (only integer constants allowed) */ +/* The base address in virtual memory to use for the kernel ELF mapping */ +/* For use by the linker (only integer constants allowed) */ +/* The base address in virtual memory to use for the kernel device + * mapping region. These are mapped in the kernel page table. */ +/* Place the kernel log buffer at the end of the kernel device page table */ +/* + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + */ +/* + * This file is autogenerated by /tools/hardware/outputs/c_header.py. + */ + +KERNEL_OFFSET = (0xFFFFFFFF80000000 + ((0x80000000 + 0x4000000) & ((1 << (30)) - 1))) - (0x80000000 + 0x4000000); +SECTIONS +{ + . = (0xFFFFFFFF80000000 + ((0x80000000 + 0x4000000) & ((1 << (30)) - 1))); + .boot.text . : AT(ADDR(.boot.text) - KERNEL_OFFSET) + { + *(.boot.text) + } + .boot.rodata . : AT(ADDR(.boot.rodata) - KERNEL_OFFSET) + { + *(.boot.rodata) + } + .boot.data . : AT(ADDR(.boot.data) - KERNEL_OFFSET) + { + *(.boot.data) + } + .boot.bss . : AT(ADDR(.boot.bss) - KERNEL_OFFSET) + { + *(.boot.bss) + } + . = ALIGN(4K); + ki_boot_end = .; + .text . : AT(ADDR(.text) - KERNEL_OFFSET) + { + . = ALIGN(4K); + /* Standard kernel */ + *(.text) + } + /* Start of data section */ + _sdata = .; + .small : { + /* Small data that should be accessed relative to gp. ld has trouble + with the relaxation if they are not in a single section. */ + __global_pointer$ = . + 0x800; + *(.srodata*) + *(.sdata*) + *(.sbss) + } + .rodata . : AT(ADDR(.rodata) - KERNEL_OFFSET) + { + *(.rodata) + *(.rodata.*) + } + .data . : AT(ADDR(.data) - KERNEL_OFFSET) + { + *(.data) + } + /* The kernel's idle thread section contains no code or data. */ + ._idle_thread . (NOLOAD): AT(ADDR(._idle_thread) - KERNEL_OFFSET) + { + *(._idle_thread) + } + .bss . (NOLOAD): AT(ADDR(.bss) - KERNEL_OFFSET) + { + *(.bss) + *(COMMON) /* fallback in case '-fno-common' is not used */ + /* 4k breakpoint stack */ + _breakpoint_stack_bottom = .; + . = . + 4K; + _breakpoint_stack_top = .; + /* large data such as the globals frame and global PD */ + *(.bss.aligned) + } + . = ALIGN(4K); + . = . + 8K; + . = ALIGN(4K); + .page_table : + { + . = ALIGN(4K); + *(.page_table.aligned) + } + . = ALIGN(4K); + ki_end = .; +} diff --git a/kernel/src/arch/riscv/mod.rs b/kernel/src/arch/riscv/mod.rs index f51c52a..2ddc450 100644 --- a/kernel/src/arch/riscv/mod.rs +++ b/kernel/src/arch/riscv/mod.rs @@ -11,6 +11,7 @@ pub use platform::{init_cpu, init_freemem}; pub use exception::handleUnknownSyscall; core::arch::global_asm!(include_str!("restore_fp.S")); +core::arch::global_asm!(include_str!("head.S")); pub fn read_stval() -> usize { let temp: usize; diff --git a/kernel/src/lib.rs b/kernel/src/main.rs similarity index 82% rename from kernel/src/lib.rs rename to kernel/src/main.rs index 9f19829..9325cc5 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/main.rs @@ -51,3 +51,16 @@ pub extern "C" fn strnlen(str: *const u8, _max_len: usize) -> usize { ans } } + +#[no_mangle] +#[link_section = ".boot.text"] +pub fn init_kernel( + ui_p_reg_start: usize, + ui_p_reg_end: usize, + pv_offset: usize, + v_entry: usize, + dtb_addr_p: usize, + dtb_size: usize +) -> ! { + +}