From 64d7f2976fda35f979c7395f4cb64eb243850d27 Mon Sep 17 00:00:00 2001 From: Yang Chen Date: Mon, 6 Feb 2023 12:21:41 +0800 Subject: [PATCH 1/3] elfloader/loongarch: add support for loongarch and run on the loongson 3A5000 platform Signed-off-by: Yang Chen --- .gitignore | 3 + cmake-tool/helpers/application_settings.cmake | 14 +- cmake-tool/helpers/check_arch_compiler.cmake | 25 +- cmake-tool/helpers/cpio.cmake | 2 +- cmake-tool/helpers/environment_flags.cmake | 5 +- cmake-tool/helpers/make-uimage | 1 + cmake-tool/helpers/rootserver.cmake | 11 +- cmake-tool/helpers/simulation.cmake | 2 +- elfloader-tool/CMakeLists.txt | 16 +- .../include/arch-loongarch/elfloader.h | 31 ++ .../include/arch-loongarch/larchintrin.h | 413 ++++++++++++++++++ .../include/arch-loongarch/machine.h | 383 ++++++++++++++++ elfloader-tool/include/elfloader_common.h | 7 +- elfloader-tool/src/arch-loongarch/boot.c | 276 ++++++++++++ elfloader-tool/src/arch-loongarch/crt0.S | 71 +++ elfloader-tool/src/arch-loongarch/linker.lds | 68 +++ elfloader-tool/src/arch-loongarch/tlbex.S | 38 ++ elfloader-tool/src/arch-loongarch/traps.S | 22 + elfloader-tool/src/common.c | 15 +- .../src/drivers/uart/loongson3A5000-uart.c | 65 +++ 20 files changed, 1431 insertions(+), 37 deletions(-) create mode 100644 elfloader-tool/include/arch-loongarch/elfloader.h create mode 100644 elfloader-tool/include/arch-loongarch/larchintrin.h create mode 100644 elfloader-tool/include/arch-loongarch/machine.h create mode 100644 elfloader-tool/src/arch-loongarch/boot.c create mode 100644 elfloader-tool/src/arch-loongarch/crt0.S create mode 100644 elfloader-tool/src/arch-loongarch/linker.lds create mode 100644 elfloader-tool/src/arch-loongarch/tlbex.S create mode 100644 elfloader-tool/src/arch-loongarch/traps.S create mode 100644 elfloader-tool/src/drivers/uart/loongson3A5000-uart.c diff --git a/.gitignore b/.gitignore index 67ecb238..1c315c3c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ # Generated python bytecode **/*.pyc + +# backup +*.backup \ No newline at end of file diff --git a/cmake-tool/helpers/application_settings.cmake b/cmake-tool/helpers/application_settings.cmake index 955dd447..7a358633 100644 --- a/cmake-tool/helpers/application_settings.cmake +++ b/cmake-tool/helpers/application_settings.cmake @@ -53,6 +53,9 @@ function(ApplyData61ElfLoaderSettings kernel_platform kernel_sel4_arch) if(KernelPlatformSpike AND KernelSel4ArchRiscV32) set(IMAGE_START_ADDR 0x80400000 CACHE INTERNAL "" FORCE) endif() + if(KernelPlatform3A5000 AND KernelSel4ArchLoongarch64) + set(IMAGE_START_ADDR 0x9000000002000000 CACHE INTERNAL "" FORCE) #32MB alignment + endif() endfunction() function(ApplyCommonSimulationSettings kernel_sel4_arch) @@ -101,6 +104,7 @@ endfunction() # - aarch64: AARCH64 # - riscv64: RISCV64 # - riscv32: RISCV32 +# - loongarch64: loongarch64 # # Calling this function will result in forced updates to the cache. function(correct_platform_strings) @@ -134,6 +138,9 @@ function(correct_platform_strings) elseif(KernelRiscVSel4Arch) # this should not have been in use at all message(FATAL_ERROR "KernelRiscVSel4Arch is no longer supported, use PLATFROM") + elseif(KernelLoongarchSel4Arch) + # this should not have been in use at all + message(FATAL_ERROR "KernelLoongarchSel4Arch is no longer supported, use PLATFROM") endif() set( @@ -166,13 +173,13 @@ function(correct_platform_strings) "-KernelSel4Arch" "pc99:x86_64,ia32" ) - + # "-KernelLoongarchPlatform" + # "loongson3A:3A5000" set(all_boards "") set(block_kernel_var "") set(kernel_var "") foreach(item IN LISTS platform_aliases) - if(item MATCHES "^-(.*)$") set(block_kernel_var "${CMAKE_MATCH_1}") continue() @@ -224,7 +231,6 @@ function(correct_platform_strings) set(${kernel_var} "${PLATFORM}" CACHE STRING "" FORCE) endforeach() - if(NOT kernel_var) set(KernelPlatform "${PLATFORM}" CACHE STRING "" FORCE) endif() @@ -263,6 +269,8 @@ function(correct_platform_strings) set(KernelSel4Arch "riscv64" CACHE STRING "" FORCE) elseif(RISCV32) set(KernelSel4Arch "riscv32" CACHE STRING "" FORCE) + elseif(Loongarch64) + set(KernelSel4Arch "loongarch64" CACHE STRING "" FORCE) else() set(_REWRITE OFF) endif() diff --git a/cmake-tool/helpers/check_arch_compiler.cmake b/cmake-tool/helpers/check_arch_compiler.cmake index f0e05ff2..5b5dcae3 100644 --- a/cmake-tool/helpers/check_arch_compiler.cmake +++ b/cmake-tool/helpers/check_arch_compiler.cmake @@ -53,6 +53,14 @@ function(check_arch_clang) correct_triple ${TRIPLE} ) + elseif("${KernelSel4Arch}" STREQUAL "loongarch64") + string( + REGEX + MATCH + "^loongarch64" + correct_triple + ${TRIPLE} + ) else() message(SEND_ERROR "KernelSel4Arch is not set to a valid arch") endif() @@ -80,20 +88,19 @@ function(check_arch_gcc) set(compiler_variable "__riscv_xlen == 32") elseif("${KernelSel4Arch}" STREQUAL "riscv64") set(compiler_variable "__riscv_xlen == 64") + elseif("${KernelSel4Arch}" STREQUAL "loongarch64") + set(compiler_variable "__loongarch_xlen == 64") else() message(SEND_ERROR "KernelSel4Arch is not set to a valid arch") endif() - set(arch_test " -#if ${compiler_variable} - int main() {return 0;} -#else -#error Invalid arch -#endif - ") - - check_c_source_compiles("${arch_test}" compiler_arch_test) + if(NOT ${compiler_variable} STREQUAL "") + set(arch_test "int main() {return 0;}") + else() + set(arch_test "Invalid arch") + endif() + check_c_source_compiles("${arch_test}" compiler_arch_test ) if(NOT compiler_arch_test) message(SEND_ERROR "Compiler: ${CMAKE_C_COMPILER} isn't for seL4_arch: ${KernelSel4Arch}") endif() diff --git a/cmake-tool/helpers/cpio.cmake b/cmake-tool/helpers/cpio.cmake index 53b3c442..f23e49cc 100644 --- a/cmake-tool/helpers/cpio.cmake +++ b/cmake-tool/helpers/cpio.cmake @@ -50,6 +50,7 @@ function(MakeCPIO output_name input_files) "bash;-c;cpio ${cpio_reproducible_flag} --quiet --create -H newc --file=${CMAKE_CURRENT_BINARY_DIR}/archive.${output_name}.cpio;&&" ) foreach(file IN LISTS input_files) + # Try and generate reproducible cpio meta-data as we do this: # - touch -d @0 file sets the modified time to 0 # - --owner=root:root sets user and group values to 0:0 @@ -65,7 +66,6 @@ function(MakeCPIO output_name input_files) if(CMAKE_C_COMPILER_ID STREQUAL "Clang") list(APPEND cmake_c_flags_sep "${CMAKE_C_COMPILE_OPTIONS_TARGET}${CMAKE_C_COMPILER_TARGET}") endif() - add_custom_command( OUTPUT ${output_name} COMMAND rm -f archive.${output_name}.cpio diff --git a/cmake-tool/helpers/environment_flags.cmake b/cmake-tool/helpers/environment_flags.cmake index cb2c9126..54c3f0ef 100644 --- a/cmake-tool/helpers/environment_flags.cmake +++ b/cmake-tool/helpers/environment_flags.cmake @@ -10,7 +10,7 @@ include_guard(GLOBAL) macro(add_default_compilation_options) # Setup base flags as defined by the kernel before including the rest include(${KERNEL_FLAGS_PATH}) - + if(("${CMAKE_BUILD_TYPE}" STREQUAL "Release") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")) option(UserLinkerGCSections "Perform dead code and data removal Build user level with -ffunction-sections and -fdata-sections and @@ -26,7 +26,6 @@ macro(add_default_compilation_options) endif() endif() mark_as_advanced(UserLinkerGCSections) - add_compile_options( -nostdinc -fno-pic @@ -43,7 +42,7 @@ macro(add_default_compilation_options) CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static -nostdlib -z max-page-size=${LinkPageSize}" ) - + if(KernelArchX86) add_compile_options(-mtls-direct-seg-refs) endif() diff --git a/cmake-tool/helpers/make-uimage b/cmake-tool/helpers/make-uimage index c5e46c7f..612914b5 100755 --- a/cmake-tool/helpers/make-uimage +++ b/cmake-tool/helpers/make-uimage @@ -119,6 +119,7 @@ trap cleanup HUP INT QUIT TERM EXIT # first and reintroduce the race that mktemp avoids. "$OBJCOPY" -O binary "$ELF_FILE" /dev/stdout >> $TEMPFILE START=$(get_start_symbol "$ELF_FILE") + mkimage -A $ARCHITECTURE -O linux -T kernel -C none \ -a $START -e $START -d $TEMPFILE "$OUTPUT" diff --git a/cmake-tool/helpers/rootserver.cmake b/cmake-tool/helpers/rootserver.cmake index 38684fb5..3665c130 100644 --- a/cmake-tool/helpers/rootserver.cmake +++ b/cmake-tool/helpers/rootserver.cmake @@ -25,12 +25,15 @@ find_file( PATHS "${CMAKE_CURRENT_LIST_DIR}" CMAKE_FIND_ROOT_PATH_BOTH ) + mark_as_advanced(TLS_ROOTSERVER) find_file(UIMAGE_TOOL make-uimage PATHS "${CMAKE_CURRENT_LIST_DIR}" CMAKE_FIND_ROOT_PATH_BOTH) + mark_as_advanced(UIMAGE_TOOL) include(CMakeDependentOption) -cmake_dependent_option(UseRiscVOpenSBI "Use OpenSBI." ON DEPENDS "KernelArchRiscV" OFF) + +cmake_dependent_option(UseRiscVOpenSBI "Use OpenSBI." ON "KernelArchRiscV" OFF) if(UseRiscVOpenSBI) set(OPENSBI_PATH "${CMAKE_SOURCE_DIR}/tools/opensbi" CACHE STRING "OpenSBI Folder location") @@ -85,13 +88,14 @@ function(DeclareRootserver rootservername) $ ${rootservername} ) - elseif(KernelArchARM OR KernelArchRiscV) + elseif(KernelArchARM OR KernelArchRiscV OR KernelArchLoongarch) set( IMAGE_NAME "${CMAKE_BINARY_DIR}/images/${rootservername}-image-${KernelArch}-${KernelPlatform}" ) set(elf_target_file $) - if(KernelArchRiscV) + + if(KernelArchRiscV OR KernelArchLoongarch) if(UseRiscVOpenSBI) # When using OpenSBI, the whole system image (usually consisting # of the ELF-Loader, a device tree, the kernel, and a userland) @@ -100,7 +104,6 @@ function(DeclareRootserver rootservername) if("${CROSS_COMPILER_PREFIX}" STREQUAL "") message(FATAL_ERROR "CROSS_COMPILER_PREFIX not set.") endif() - if("${KernelOpenSBIPlatform}" STREQUAL "") message(FATAL_ERROR "KernelOpenSBIPlatform not set.") endif() diff --git a/cmake-tool/helpers/simulation.cmake b/cmake-tool/helpers/simulation.cmake index e4c24914..cf38b557 100644 --- a/cmake-tool/helpers/simulation.cmake +++ b/cmake-tool/helpers/simulation.cmake @@ -118,7 +118,7 @@ function(GenerateSimulateScript) elseif(KernelPlatformRpi3 AND KernelSel4ArchAarch64) set(QemuBinaryMachine "qemu-system-aarch64") set(sim_serial_opt "-serial null -serial mon:stdio") - set(sim_machine "raspi3") + set(sim_machine "raspi3b") SetDefaultMemSize("1024M") elseif(KernelPlatformSpike) if(KernelSel4ArchRiscV32) diff --git a/elfloader-tool/CMakeLists.txt b/elfloader-tool/CMakeLists.txt index f13589f1..45c95697 100644 --- a/elfloader-tool/CMakeLists.txt +++ b/elfloader-tool/CMakeLists.txt @@ -8,8 +8,8 @@ cmake_minimum_required(VERSION 3.7.2) project(elfloader C ASM) -if(KernelArchX86) - # This project is only used on Arm or RISC-V +if(KernelArchX86) + # This project is only used on Arm or RISC-V OR KernelArchLoongarch return() endif() @@ -26,7 +26,7 @@ config_choice( ElfloaderImage ELFLOADER_IMAGE "Boot image type" - "elf;ElfloaderImageELF;IMAGE_ELF;KernelArchARM OR KernelArchRiscV" + "elf;ElfloaderImageELF;IMAGE_ELF;KernelArchARM OR KernelArchRiscV OR KernelArchLoongarch" "binary;ElfloaderImageBinary;IMAGE_BINARY;KernelArchARM OR KernelArchRiscV" "efi;ElfloaderImageEFI;IMAGE_EFI;KernelArchARM" "uimage;ElfloaderImageUimage;IMAGE_UIMAGE;KernelArchARM" @@ -77,7 +77,7 @@ config_option( ElfloaderIncludeDtb ELFLOADER_INCLUDE_DTB "Include DTB in the CPIO in case bootloader doesn't provide one" DEFAULT ON - DEPENDS "KernelArchARM OR KernelArchRiscV" + DEPENDS "KernelArchARM OR KernelArchRiscV OR KernelArchLoongarch" DEFAULT_DISABLED OFF ) @@ -99,10 +99,12 @@ add_config_library(elfloader "${configure_string}") add_compile_options(-D_XOPEN_SOURCE=700 -ffreestanding -Wall -Werror -W -Wextra) set(linkerScript "${CMAKE_CURRENT_LIST_DIR}/src/arch-${KernelArch}/linker.lds") + if(KernelArchRiscV) add_compile_options(-mcmodel=medany) endif() + if(ElfloaderArmV8LeaveAarch64) # We need to build a aarch64 assembly file during an aarch32 build. We have # to write custom rules to do this as CMake doesn't support multiple compilers @@ -234,6 +236,7 @@ list(SORT files) set(cpio_files "") list(APPEND cpio_files "$") + if(ElfloaderIncludeDtb) list(APPEND cpio_files "${KernelDTBPath}") endif() @@ -267,7 +270,6 @@ endif() # Construct the ELF loader's payload. MakeCPIO(archive.o "${cpio_files}" CPIO_SYMBOL _archive_start) - set(PLATFORM_HEADER_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen_headers") set(PLATFORM_INFO_H "${PLATFORM_HEADER_DIR}/platform_info.h") set(IMAGE_START_ADDR_H "${PLATFORM_HEADER_DIR}/image_start_addr.h") @@ -289,7 +291,6 @@ elseif(NOT DEFINED platform_yaml) message(FATAL_ERROR "IMAGE_START_ADDR not set and 'platform_yaml' undefined") else() - # The following does two things. These commands are put together as for some weird # reason, CMake does not execute the first command if it's by itself. This could be # due to the CMakeLists.txt file in the capDL repository also invoking a similar command @@ -324,9 +325,7 @@ else() "${ELF_SIFT}" "${SHOEHORN}" ) - endif() - if(DEFINED KernelDTBPath) get_filename_component(KernelTools ${HARDWARE_GEN_PATH} DIRECTORY) set(config_file "${KernelTools}/hardware.yml") @@ -347,7 +346,6 @@ if(DEFINED KernelDTBPath) ) set_property(SOURCE src/drivers/driver.c PROPERTY OBJECT_DEPENDS ${DEVICES_GEN_H}) endif() - # Generate linker script separate_arguments(c_arguments NATIVE_COMMAND "${CMAKE_C_FLAGS}") # Add extra compilation flags required for clang diff --git a/elfloader-tool/include/arch-loongarch/elfloader.h b/elfloader-tool/include/arch-loongarch/elfloader.h new file mode 100644 index 00000000..b2f072a8 --- /dev/null +++ b/elfloader-tool/include/arch-loongarch/elfloader.h @@ -0,0 +1,31 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * Derived from: + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * Copyright 2021, HENSOLDT Cyber + * + * SPDX-License-Identifier: GPL-2.0-only + */ +#pragma once + +#include +#include + +/* This is a low level binary interface, thus we do not preserve the type + * information here. All parameters are just register values (or stack values + * that are register-sized). + */ +typedef void (*init_loongarch_kernel_t)(word_t ui_p_reg_start, + word_t ui_p_reg_end, + word_t pv_offset, + word_t v_entry, + word_t dtb_addr_p, + word_t dtb_size +#if CONFIG_MAX_NUM_NODES > 1 + , + word_t hart_id, + word_t core_id +#endif + ); diff --git a/elfloader-tool/include/arch-loongarch/larchintrin.h b/elfloader-tool/include/arch-loongarch/larchintrin.h new file mode 100644 index 00000000..fcf50438 --- /dev/null +++ b/elfloader-tool/include/arch-loongarch/larchintrin.h @@ -0,0 +1,413 @@ +/* Intrinsics for LoongArch BASE operations. + Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Loongson Ltd. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 3, or (at your +option) any later version. + +GCC is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef _GCC_LOONGARCH_BASE_INTRIN_H +#define _GCC_LOONGARCH_BASE_INTRIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct drdtime +{ + unsigned long dvalue; + unsigned long dtimeid; +} __drdtime_t; + +typedef struct rdtime +{ + unsigned int value; + unsigned int timeid; +} __rdtime_t; + +#ifdef __loongarch64 +extern __inline __drdtime_t +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_rdtime_d (void) +{ + __drdtime_t drdtime; + __asm__ volatile ( + "rdtime.d\t%[val],%[tid]\n\t" + : [val]"=&r"(drdtime.dvalue),[tid]"=&r"(drdtime.dtimeid) + :); + return drdtime; +} +#define __rdtime_d __builtin_loongarch_rdtime_d +#endif + +extern __inline __rdtime_t +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_rdtimeh_w (void) +{ + __rdtime_t rdtime; + __asm__ volatile ( + "rdtimeh.w\t%[val],%[tid]\n\t" + : [val]"=&r"(rdtime.value),[tid]"=&r"(rdtime.timeid) + :); + return rdtime; +} +#define __rdtimel_w __builtin_loongarch_rdtimel_w + +extern __inline __rdtime_t +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_rdtimel_w (void) +{ + __rdtime_t rdtime; + __asm__ volatile ( + "rdtimel.w\t%[val],%[tid]\n\t" + : [val]"=&r"(rdtime.value),[tid]"=&r"(rdtime.timeid) + :); + return rdtime; +} +#define __rdtimeh_w __builtin_loongarch_rdtimeh_w + +/* Assembly instruction format: rj, fcsr. */ +/* Data types in instruction templates: USI, UQI. */ +#define __movfcsr2gr(/*ui5*/ _1) __builtin_loongarch_movfcsr2gr ((_1)); + +/* Assembly instruction format: 0, fcsr, rj. */ +/* Data types in instruction templates: VOID, UQI, USI. */ +#define __movgr2fcsr(/*ui5*/ _1, _2) \ + __builtin_loongarch_movgr2fcsr ((unsigned short) _1, (unsigned int) _2); + +#if defined __loongarch64 +/* Assembly instruction format: ui5, rj, si12. */ +/* Data types in instruction templates: VOID, USI, UDI, SI. */ +#define __dcacop(/*ui5*/ _1, /*unsigned long int*/ _2, /*si12*/ _3) \ + ((void) __builtin_loongarch_dcacop ((_1), (unsigned long int) (_2), (_3))) +#else +#error "Don't support this ABI." +#endif + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: USI, USI. */ +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__cpucfg (unsigned int _1) +{ + return (unsigned int) __builtin_loongarch_cpucfg ((unsigned int) _1); +} + +#ifdef __loongarch64 +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: DI, DI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__asrtle_d (long int _1, long int _2) +{ + __builtin_loongarch_asrtle_d ((long int) _1, (long int) _2); +} + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: DI, DI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__asrtgt_d (long int _1, long int _2) +{ + __builtin_loongarch_asrtgt_d ((long int) _1, (long int) _2); +} +#endif + +#if defined __loongarch64 +/* Assembly instruction format: rd, rj, ui5. */ +/* Data types in instruction templates: DI, DI, UQI. */ +#define __dlddir(/*long int*/ _1, /*ui5*/ _2) \ + ((long int) __builtin_loongarch_dlddir ((long int) (_1), (_2))) +#else +#error "Don't support this ABI." +#endif + +#if defined __loongarch64 +/* Assembly instruction format: rj, ui5. */ +/* Data types in instruction templates: VOID, DI, UQI. */ +#define __dldpte(/*long int*/ _1, /*ui5*/ _2) \ + ((void) __builtin_loongarch_dldpte ((long int) (_1), (_2))) +#else +#error "Don't support this ABI." +#endif + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, QI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crc_w_b_w (char _1, int _2) +{ + return (int) __builtin_loongarch_crc_w_b_w ((char) _1, (int) _2); +} + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, HI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crc_w_h_w (short _1, int _2) +{ + return (int) __builtin_loongarch_crc_w_h_w ((short) _1, (int) _2); +} + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, SI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crc_w_w_w (int _1, int _2) +{ + return (int) __builtin_loongarch_crc_w_w_w ((int) _1, (int) _2); +} + +#ifdef __loongarch64 +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, DI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crc_w_d_w (long int _1, int _2) +{ + return (int) __builtin_loongarch_crc_w_d_w ((long int) _1, (int) _2); +} +#endif + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, QI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crcc_w_b_w (char _1, int _2) +{ + return (int) __builtin_loongarch_crcc_w_b_w ((char) _1, (int) _2); +} + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, HI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crcc_w_h_w (short _1, int _2) +{ + return (int) __builtin_loongarch_crcc_w_h_w ((short) _1, (int) _2); +} + +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, SI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crcc_w_w_w (int _1, int _2) +{ + return (int) __builtin_loongarch_crcc_w_w_w ((int) _1, (int) _2); +} + +#ifdef __loongarch64 +/* Assembly instruction format: rd, rj, rk. */ +/* Data types in instruction templates: SI, DI, SI. */ +extern __inline int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__crcc_w_d_w (long int _1, int _2) +{ + return (int) __builtin_loongarch_crcc_w_d_w ((long int) _1, (int) _2); +} +#endif + +/* Assembly instruction format: rd, ui14. */ +/* Data types in instruction templates: USI, USI. */ +#define __csrrd(/*ui14*/ _1) ((unsigned int) __builtin_loongarch_csrrd ((_1))) + +/* Assembly instruction format: rd, ui14. */ +/* Data types in instruction templates: USI, USI, USI. */ +#define __csrwr(/*unsigned int*/ _1, /*ui14*/ _2) \ + ((unsigned int) __builtin_loongarch_csrwr ((unsigned int) (_1), (_2))) + +/* Assembly instruction format: rd, rj, ui14. */ +/* Data types in instruction templates: USI, USI, USI, USI. */ +#define __csrxchg(/*unsigned int*/ _1, /*unsigned int*/ _2, /*ui14*/ _3) \ + ((unsigned int) __builtin_loongarch_csrxchg ((unsigned int) (_1), \ + (unsigned int) (_2), (_3))) + +#ifdef __loongarch64 +/* Assembly instruction format: rd, ui14. */ +/* Data types in instruction templates: UDI, USI. */ +#define __dcsrrd(/*ui14*/ _1) \ + ((unsigned long int) __builtin_loongarch_dcsrrd ((_1))) + +/* Assembly instruction format: rd, ui14. */ +/* Data types in instruction templates: UDI, UDI, USI. */ +#define __dcsrwr(/*unsigned long int*/ _1, /*ui14*/ _2) \ + ((unsigned long int) __builtin_loongarch_dcsrwr ((unsigned long int) (_1), \ + (_2))) + +/* Assembly instruction format: rd, rj, ui14. */ +/* Data types in instruction templates: UDI, UDI, UDI, USI. */ +#define __dcsrxchg(/*unsigned long int*/ _1, /*unsigned long int*/ _2, \ + /*ui14*/ _3) \ + ((unsigned long int) __builtin_loongarch_dcsrxchg ( \ + (unsigned long int) (_1), (unsigned long int) (_2), (_3))) +#endif + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: UQI, USI. */ +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrrd_b (unsigned int _1) +{ + return (unsigned char) __builtin_loongarch_iocsrrd_b ((unsigned int) _1); +} + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: UHI, USI. */ +extern __inline unsigned char +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrrd_h (unsigned int _1) +{ + return (unsigned short) __builtin_loongarch_iocsrrd_h ((unsigned int) _1); +} + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: USI, USI. */ +extern __inline unsigned int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrrd_w (unsigned int _1) +{ + return (unsigned int) __builtin_loongarch_iocsrrd_w ((unsigned int) _1); +} + +#ifdef __loongarch64 +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: UDI, USI. */ +extern __inline unsigned long int +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrrd_d (unsigned int _1) +{ + return (unsigned long int) __builtin_loongarch_iocsrrd_d ((unsigned int) _1); +} +#endif + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: VOID, UQI, USI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrwr_b (unsigned char _1, unsigned int _2) +{ + return (void) __builtin_loongarch_iocsrwr_b ((unsigned char) _1, + (unsigned int) _2); +} + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: VOID, UHI, USI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrwr_h (unsigned short _1, unsigned int _2) +{ + return (void) __builtin_loongarch_iocsrwr_h ((unsigned short) _1, + (unsigned int) _2); +} + +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: VOID, USI, USI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrwr_w (unsigned int _1, unsigned int _2) +{ + return (void) __builtin_loongarch_iocsrwr_w ((unsigned int) _1, + (unsigned int) _2); +} + +#ifdef __loongarch64 +/* Assembly instruction format: rd, rj. */ +/* Data types in instruction templates: VOID, UDI, USI. */ +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__iocsrwr_d (unsigned long int _1, unsigned int _2) +{ + return (void) __builtin_loongarch_iocsrwr_d ((unsigned long int) _1, + (unsigned int) _2); +} +#endif + +/* Assembly instruction format: ui15. */ +/* Data types in instruction templates: UQI. */ +#define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar ((_1)) + +/* Assembly instruction format: ui15. */ +/* Data types in instruction templates: UQI. */ +#define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar ((_1)) + +#define __builtin_loongarch_syscall(a) \ + { \ + __asm__ volatile ("syscall %0\n\t" ::"I"(a)); \ + } +#define __syscall __builtin_loongarch_syscall + +#define __builtin_loongarch_break(a) \ + { \ + __asm__ volatile ("break %0\n\t" ::"I"(a)); \ + } +#define __break __builtin_loongarch_break + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbsrch (void) +{ + __asm__ volatile ("tlbsrch\n\t"); +} +#define __tlbsrch __builtin_loongarch_tlbsrch + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbrd (void) +{ + __asm__ volatile ("tlbrd\n\t"); +} +#define __tlbrd __builtin_loongarch_tlbrd + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbwr (void) +{ + __asm__ volatile ("tlbwr\n\t"); +} +#define __tlbwr __builtin_loongarch_tlbwr + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbfill (void) +{ + __asm__ volatile ("tlbfill\n\t"); +} +#define __tlbfill __builtin_loongarch_tlbfill + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbclr (void) +{ + __asm__ volatile ("tlbclr\n\t"); +} +#define __tlbclr __builtin_loongarch_tlbclr + +extern __inline void +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +__builtin_loongarch_tlbflush (void) +{ + __asm__ volatile ("tlbflush\n\t"); +} +#define __tlbflush __builtin_loongarch_tlbflush + +#ifdef __cplusplus +} +#endif +#endif /* _GCC_LOONGARCH_BASE_INTRIN_H */ diff --git a/elfloader-tool/include/arch-loongarch/machine.h b/elfloader-tool/include/arch-loongarch/machine.h new file mode 100644 index 00000000..d9e95b7f --- /dev/null +++ b/elfloader-tool/include/arch-loongarch/machine.h @@ -0,0 +1,383 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#pragma once + +#define PASTE(a, b) a ## b + +#ifdef __ASSEMBLER__ + +#define UL_CONST(x) x +#define ULL_CONST(x) x +#define NULL 0 + +#else /* not __ASSEMBLER__ */ + +#define UL_CONST(x) PASTE(x, ul) +#define ULL_CONST(x) PASTE(x, llu) +#define NULL ((void *)0) + +#endif + +#define LOONGARCH_CSR_CRMD 0x0 /* Current mode info */ +#define LOONGARCH_CSR_PRMD 0x1 /* Prev-exception mode info */ +#define LOONGARCH_CSR_EUEN 0x2 /* Extended unit enable */ +#define LOONGARCH_CSR_MISC 0x3 /* Misc config */ +#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */ +#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */ +#define LOONGARCH_CSR_ERA 0x6 /* ERA */ +#define LOONGARCH_CSR_BADV 0x7 /* Bad virtual address */ +#define LOONGARCH_CSR_BADI 0x8 /* Bad instruction */ +#define LOONGARCH_CSR_EENTRY 0xc /* Exception entry */ + +/* TLB related CSR registers */ +#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */ +#define CSR_TLBIDX_EHINV_SHIFT 31 +#define CSR_TLBIDX_EHINV (UL_CONST(1) << CSR_TLBIDX_EHINV_SHIFT) +#define CSR_TLBIDX_PS_SHIFT 24 +#define CSR_TLBIDX_PS_WIDTH 6 +#define CSR_TLBIDX_PS (UL_CONST(0x3f) << CSR_TLBIDX_PS_SHIFT) +#define CSR_TLBIDX_IDX_SHIFT 0 +#define CSR_TLBIDX_IDX_WIDTH 12 +#define CSR_TLBIDX_IDX (UL_CONST(0xfff) << CSR_TLBIDX_IDX_SHIFT) +#define CSR_TLBIDX_SIZEM 0x3f000000 +#define CSR_TLBIDX_SIZE CSR_TLBIDX_PS_SHIFT +#define CSR_TLBIDX_IDXM 0xfff +#define CSR_INVALID_ENTRY(e) (CSR_TLBIDX_EHINV | e) + +#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */ +#define LOONGARCH_CSR_TLBELO0 0x12 /* TLB EntryLo0 */ +#define CSR_TLBLO0_RPLV_SHIFT 63 +#define CSR_TLBLO0_RPLV (UL_CONST(0x1) << CSR_TLBLO0_RPLV_SHIFT) +#define CSR_TLBLO0_NX_SHIFT 62 +#define CSR_TLBLO0_NX (UL_CONST(0x1) << CSR_TLBLO0_NX_SHIFT) +#define CSR_TLBLO0_NR_SHIFT 61 +#define CSR_TLBLO0_NR (UL_CONST(0x1) << CSR_TLBLO0_NR_SHIFT) +#define CSR_TLBLO0_PFN_SHIFT 12 +#define CSR_TLBLO0_PFN_WIDTH 36 +#define CSR_TLBLO0_PFN (UL_CONST(0xfffffffff) << CSR_TLBLO0_PFN_SHIFT) +#define CSR_TLBLO0_GLOBAL_SHIFT 6 +#define CSR_TLBLO0_GLOBAL (UL_CONST(0x1) << CSR_TLBLO0_GLOBAL_SHIFT) +#define CSR_TLBLO0_CCA_SHIFT 4 +#define CSR_TLBLO0_CCA_WIDTH 2 +#define CSR_TLBLO0_CCA (UL_CONST(0x3) << CSR_TLBLO0_CCA_SHIFT) +#define CSR_TLBLO0_PLV_SHIFT 2 +#define CSR_TLBLO0_PLV_WIDTH 2 +#define CSR_TLBLO0_PLV (UL_CONST(0x3) << CSR_TLBLO0_PLV_SHIFT) +#define CSR_TLBLO0_WE_SHIFT 1 +#define CSR_TLBLO0_WE (UL_CONST(0x1) << CSR_TLBLO0_WE_SHIFT) +#define CSR_TLBLO0_V_SHIFT 0 +#define CSR_TLBLO0_V (UL_CONST(0x1) << CSR_TLBLO0_V_SHIFT) + +#define LOONGARCH_CSR_TLBELO1 0x13 /* TLB EntryLo1 */ +#define CSR_TLBLO1_RPLV_SHIFT 63 +#define CSR_TLBLO1_RPLV (UL_CONST(0x1) << CSR_TLBLO1_RPLV_SHIFT) +#define CSR_TLBLO1_NX_SHIFT 62 +#define CSR_TLBLO1_NX (UL_CONST(0x1) << CSR_TLBLO1_NX_SHIFT) +#define CSR_TLBLO1_NR_SHIFT 61 +#define CSR_TLBLO1_NR (UL_CONST(0x1) << CSR_TLBLO1_NR_SHIFT) +#define CSR_TLBLO1_PFN_SHIFT 12 +#define CSR_TLBLO1_PFN_WIDTH 36 +#define CSR_TLBLO1_PFN (UL_CONST(0xfffffffff) << CSR_TLBLO1_PFN_SHIFT) +#define CSR_TLBLO1_GLOBAL_SHIFT 6 +#define CSR_TLBLO1_GLOBAL (UL_CONST(0x1) << CSR_TLBLO1_GLOBAL_SHIFT) +#define CSR_TLBLO1_CCA_SHIFT 4 +#define CSR_TLBLO1_CCA_WIDTH 2 +#define CSR_TLBLO1_CCA (UL_CONST(0x3) << CSR_TLBLO1_CCA_SHIFT) +#define CSR_TLBLO1_PLV_SHIFT 2 +#define CSR_TLBLO1_PLV_WIDTH 2 +#define CSR_TLBLO1_PLV (UL_CONST(0x3) << CSR_TLBLO1_PLV_SHIFT) +#define CSR_TLBLO1_WE_SHIFT 1 +#define CSR_TLBLO1_WE (UL_CONST(0x1) << CSR_TLBLO1_WE_SHIFT) +#define CSR_TLBLO1_V_SHIFT 0 +#define CSR_TLBLO1_V (UL_CONST(0x1) << CSR_TLBLO1_V_SHIFT) + +#define LOONGARCH_CSR_GTLBC 0x15 /* Guest TLB control */ +#define LOONGARCH_CSR_TRGP 0x16 /* TLBR read guest info */ + +#define LOONGARCH_CSR_ASID 0x18 /* ASID */ +#define LOONGARCH_CSR_PGDL 0x19 /* Page table base address when VA[47] = 0 */ +#define LOONGARCH_CSR_PGDH 0x1a /* Page table base address when VA[47] = 1 */ +#define LOONGARCH_CSR_PGD 0x1b /* Page table base */ +#define LOONGARCH_CSR_PWCL 0x1c /* PWCL */ +#define LOONGARCH_CSR_PWCH 0x1d /* PWCH */ +#define LOONGARCH_CSR_STLBPGSIZE 0x1e +#define LOONGARCH_CSR_RVACFG 0x1f + +/* Config CSR registers */ +#define LOONGARCH_CSR_CPUID 0x20 /* CPU core id */ +#define LOONGARCH_CSR_PRCFG1 0x21 /* Config1 */ +#define LOONGARCH_CSR_PRCFG2 0x22 /* Config2 */ +#define LOONGARCH_CSR_PRCFG3 0x23 /* Config3 */ + +/* Kscratch registers */ +#define LOONGARCH_CSR_KS0 0x30 +#define LOONGARCH_CSR_KS1 0x31 +#define LOONGARCH_CSR_KS2 0x32 +#define LOONGARCH_CSR_KS3 0x33 +#define LOONGARCH_CSR_KS4 0x34 +#define LOONGARCH_CSR_KS5 0x35 +#define LOONGARCH_CSR_KS6 0x36 +#define LOONGARCH_CSR_KS7 0x37 +#define LOONGARCH_CSR_KS8 0x38 + +/* Timer registers */ +#define LOONGARCH_CSR_TMID 0x40 /* Timer ID */ +#define LOONGARCH_CSR_TCFG 0x41 /* Timer config */ +#define LOONGARCH_CSR_TVAL 0x42 /* Timer value */ +#define LOONGARCH_CSR_CNTC 0x43 /* Timer offset */ +#define LOONGARCH_CSR_TINTCLR 0x44 /* Timer interrupt clear */ + +/* Guest registers */ +#define LOONGARCH_CSR_GSTAT 0x50 /* Guest status */ +#define LOONGARCH_CSR_GCFG 0x51 /* Guest config */ +#define LOONGARCH_CSR_GINTC 0x52 /* Guest interrupt control */ +#define LOONGARCH_CSR_GCNTC 0x53 /* Guest timer offset */ + +/* LLBCTL register */ +#define LOONGARCH_CSR_LLBCTL 0x60 /* LLBit control */ + +/* Implement dependent */ +#define LOONGARCH_CSR_IMPCTL1 0x80 /* Loongson config1 */ +#define LOONGARCH_CSR_IMPCTL2 0x81 /* Loongson config2 */ +#define LOONGARCH_CSR_GNMI 0x82 + +/* TLB Refill registers */ +#define LOONGARCH_CSR_TLBRENTRY 0x88 /* TLB refill exception entry */ +#define LOONGARCH_CSR_TLBRBADV 0x89 /* TLB refill badvaddr */ +#define LOONGARCH_CSR_TLBRERA 0x8a /* TLB refill ERA */ +#define LOONGARCH_CSR_TLBRSAVE 0x8b /* KScratch for TLB refill exception */ +#define LOONGARCH_CSR_TLBRELO0 0x8c /* TLB refill entrylo0 */ +#define LOONGARCH_CSR_TLBRELO1 0x8d /* TLB refill entrylo1 */ +#define LOONGARCH_CSR_TLBREHI 0x8e /* TLB refill entryhi */ +#define CSR_TLBREHI_PS_SHIFT 0 +#define CSR_TLBREHI_PS (UL_CONST(0x3f) << CSR_TLBREHI_PS_SHIFT) +#define LOONGARCH_CSR_TLBRPRMD 0x8f /* TLB refill mode info */ + +/* Machine Error registers */ +#define LOONGARCH_CSR_MERRCTL 0x90 /* MERRCTL */ +#define LOONGARCH_CSR_MERRINFO1 0x91 /* MError info1 */ +#define LOONGARCH_CSR_MERRINFO2 0x92 /* MError info2 */ +#define LOONGARCH_CSR_MERRENTRY 0x93 /* MError exception entry */ +#define LOONGARCH_CSR_MERRERA 0x94 /* MError exception ERA */ +#define LOONGARCH_CSR_MERRSAVE 0x95 /* KScratch for machine error exception */ + +#define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */ + +#define LOONGARCH_CSR_PRID 0xc0 + +/* Shadow MCSR : 0xc0 ~ 0xff */ +#define LOONGARCH_CSR_MCSR0 0xc0 /* CPUCFG0 and CPUCFG1 */ +#define LOONGARCH_CSR_MCSR1 0xc1 /* CPUCFG2 and CPUCFG3 */ +#define LOONGARCH_CSR_MCSR2 0xc2 /* CPUCFG4 and CPUCFG5 */ +#define LOONGARCH_CSR_MCSR3 0xc3 /* CPUCFG6 */ +#define LOONGARCH_CSR_MCSR8 0xc8 /* CPUCFG16 and CPUCFG17 */ +#define LOONGARCH_CSR_MCSR9 0xc9 /* CPUCFG18 and CPUCFG19 */ +#define LOONGARCH_CSR_MCSR10 0xca /* CPUCFG20 */ +#define LOONGARCH_CSR_MCSR24 0xf0 /* cpucfg48 */ + +/* Uncached accelerate windows registers */ +#define LOONGARCH_CSR_UCAWIN 0x100 +#define LOONGARCH_CSR_UCAWIN0_LO 0x102 +#define LOONGARCH_CSR_UCAWIN0_HI 0x103 +#define LOONGARCH_CSR_UCAWIN1_LO 0x104 +#define LOONGARCH_CSR_UCAWIN1_HI 0x105 +#define LOONGARCH_CSR_UCAWIN2_LO 0x106 +#define LOONGARCH_CSR_UCAWIN2_HI 0x107 +#define LOONGARCH_CSR_UCAWIN3_LO 0x108 +#define LOONGARCH_CSR_UCAWIN3_HI 0x109 + +/* Direct Map windows registers */ +#define LOONGARCH_CSR_DMWIN0 0x180 /* 64 direct map win0: MEM & IF */ +#define LOONGARCH_CSR_DMWIN1 0x181 /* 64 direct map win1: MEM & IF */ +#define LOONGARCH_CSR_DMWIN2 0x182 /* 64 direct map win2: MEM */ +#define LOONGARCH_CSR_DMWIN3 0x183 /* 64 direct map win3: MEM */ + +/* Performance Counter registers */ +#define LOONGARCH_CSR_PERFCTRL0 0x200 /* 32 perf event 0 config */ +#define LOONGARCH_CSR_PERFCNTR0 0x201 /* 64 perf event 0 count value */ +#define LOONGARCH_CSR_PERFCTRL1 0x202 /* 32 perf event 1 config */ +#define LOONGARCH_CSR_PERFCNTR1 0x203 /* 64 perf event 1 count value */ +#define LOONGARCH_CSR_PERFCTRL2 0x204 /* 32 perf event 2 config */ +#define LOONGARCH_CSR_PERFCNTR2 0x205 /* 64 perf event 2 count value */ +#define LOONGARCH_CSR_PERFCTRL3 0x206 /* 32 perf event 3 config */ +#define LOONGARCH_CSR_PERFCNTR3 0x207 /* 64 perf event 3 count value */ + +/* Debug registers */ +#define LOONGARCH_CSR_MWPC 0x300 /* data breakpoint config */ +#define LOONGARCH_CSR_MWPS 0x301 /* data breakpoint status */ + +#define LOONGARCH_CSR_DB0ADDR 0x310 /* data breakpoint 0 address */ +#define LOONGARCH_CSR_DB0MASK 0x311 /* data breakpoint 0 mask */ +#define LOONGARCH_CSR_DB0CTL 0x312 /* data breakpoint 0 control */ +#define LOONGARCH_CSR_DB0ASID 0x313 /* data breakpoint 0 asid */ + +#define LOONGARCH_CSR_DB1ADDR 0x318 /* data breakpoint 1 address */ +#define LOONGARCH_CSR_DB1MASK 0x319 /* data breakpoint 1 mask */ +#define LOONGARCH_CSR_DB1CTL 0x31a /* data breakpoint 1 control */ +#define LOONGARCH_CSR_DB1ASID 0x31b /* data breakpoint 1 asid */ + +#define LOONGARCH_CSR_DB2ADDR 0x320 /* data breakpoint 2 address */ +#define LOONGARCH_CSR_DB2MASK 0x321 /* data breakpoint 2 mask */ +#define LOONGARCH_CSR_DB2CTL 0x322 /* data breakpoint 2 control */ +#define LOONGARCH_CSR_DB2ASID 0x323 /* data breakpoint 2 asid */ + +#define LOONGARCH_CSR_DB3ADDR 0x328 /* data breakpoint 3 address */ +#define LOONGARCH_CSR_DB3MASK 0x329 /* data breakpoint 3 mask */ +#define LOONGARCH_CSR_DB3CTL 0x32a /* data breakpoint 3 control */ +#define LOONGARCH_CSR_DB3ASID 0x32b /* data breakpoint 3 asid */ + +#define LOONGARCH_CSR_DB4ADDR 0x330 /* data breakpoint 4 address */ +#define LOONGARCH_CSR_DB4MASK 0x331 /* data breakpoint 4 maks */ +#define LOONGARCH_CSR_DB4CTL 0x332 /* data breakpoint 4 control */ +#define LOONGARCH_CSR_DB4ASID 0x333 /* data breakpoint 4 asid */ + +#define LOONGARCH_CSR_DB5ADDR 0x338 /* data breakpoint 5 address */ +#define LOONGARCH_CSR_DB5MASK 0x339 /* data breakpoint 5 mask */ +#define LOONGARCH_CSR_DB5CTL 0x33a /* data breakpoint 5 control */ +#define LOONGARCH_CSR_DB5ASID 0x33b /* data breakpoint 5 asid */ + +#define LOONGARCH_CSR_DB6ADDR 0x340 /* data breakpoint 6 address */ +#define LOONGARCH_CSR_DB6MASK 0x341 /* data breakpoint 6 mask */ +#define LOONGARCH_CSR_DB6CTL 0x342 /* data breakpoint 6 control */ +#define LOONGARCH_CSR_DB6ASID 0x343 /* data breakpoint 6 asid */ + +#define LOONGARCH_CSR_DB7ADDR 0x348 /* data breakpoint 7 address */ +#define LOONGARCH_CSR_DB7MASK 0x349 /* data breakpoint 7 mask */ +#define LOONGARCH_CSR_DB7CTL 0x34a /* data breakpoint 7 control */ +#define LOONGARCH_CSR_DB7ASID 0x34b /* data breakpoint 7 asid */ + +#define LOONGARCH_CSR_FWPC 0x380 /* instruction breakpoint config */ +#define LOONGARCH_CSR_FWPS 0x381 /* instruction breakpoint status */ + +#define LOONGARCH_CSR_IB0ADDR 0x390 /* inst breakpoint 0 address */ +#define LOONGARCH_CSR_IB0MASK 0x391 /* inst breakpoint 0 mask */ +#define LOONGARCH_CSR_IB0CTL 0x392 /* inst breakpoint 0 control */ +#define LOONGARCH_CSR_IB0ASID 0x393 /* inst breakpoint 0 asid */ + +#define LOONGARCH_CSR_IB1ADDR 0x398 /* inst breakpoint 1 address */ +#define LOONGARCH_CSR_IB1MASK 0x399 /* inst breakpoint 1 mask */ +#define LOONGARCH_CSR_IB1CTL 0x39a /* inst breakpoint 1 control */ +#define LOONGARCH_CSR_IB1ASID 0x39b /* inst breakpoint 1 asid */ + +#define LOONGARCH_CSR_IB2ADDR 0x3a0 /* inst breakpoint 2 address */ +#define LOONGARCH_CSR_IB2MASK 0x3a1 /* inst breakpoint 2 mask */ +#define LOONGARCH_CSR_IB2CTL 0x3a2 /* inst breakpoint 2 control */ +#define LOONGARCH_CSR_IB2ASID 0x3a3 /* inst breakpoint 2 asid */ + +#define LOONGARCH_CSR_IB3ADDR 0x3a8 /* inst breakpoint 3 address */ +#define LOONGARCH_CSR_IB3MASK 0x3a9 /* breakpoint 3 mask */ +#define LOONGARCH_CSR_IB3CTL 0x3aa /* inst breakpoint 3 control */ +#define LOONGARCH_CSR_IB3ASID 0x3ab /* inst breakpoint 3 asid */ + +#define LOONGARCH_CSR_IB4ADDR 0x3b0 /* inst breakpoint 4 address */ +#define LOONGARCH_CSR_IB4MASK 0x3b1 /* inst breakpoint 4 mask */ +#define LOONGARCH_CSR_IB4CTL 0x3b2 /* inst breakpoint 4 control */ +#define LOONGARCH_CSR_IB4ASID 0x3b3 /* inst breakpoint 4 asid */ + +#define LOONGARCH_CSR_IB5ADDR 0x3b8 /* inst breakpoint 5 address */ +#define LOONGARCH_CSR_IB5MASK 0x3b9 /* inst breakpoint 5 mask */ +#define LOONGARCH_CSR_IB5CTL 0x3ba /* inst breakpoint 5 control */ +#define LOONGARCH_CSR_IB5ASID 0x3bb /* inst breakpoint 5 asid */ + +#define LOONGARCH_CSR_IB6ADDR 0x3c0 /* inst breakpoint 6 address */ +#define LOONGARCH_CSR_IB6MASK 0x3c1 /* inst breakpoint 6 mask */ +#define LOONGARCH_CSR_IB6CTL 0x3c2 /* inst breakpoint 6 control */ +#define LOONGARCH_CSR_IB6ASID 0x3c3 /* inst breakpoint 6 asid */ + +#define LOONGARCH_CSR_IB7ADDR 0x3c8 /* inst breakpoint 7 address */ +#define LOONGARCH_CSR_IB7MASK 0x3c9 /* inst breakpoint 7 mask */ +#define LOONGARCH_CSR_IB7CTL 0x3ca /* inst breakpoint 7 control */ +#define LOONGARCH_CSR_IB7ASID 0x3cb /* inst breakpoint 7 asid */ + +#define LOONGARCH_CSR_DEBUG 0x500 /* debug config */ +#define LOONGARCH_CSR_DERA 0x501 /* debug era */ +#define LOONGARCH_CSR_DESAVE 0x502 /* debug save */ + +#ifndef __ASSEMBLER__ +#include +#include + +static inline uint32_t csr_readl(uint32_t reg) +{ + return __csrrd(reg); +} + +static inline uint64_t csr_readq(uint32_t reg) +{ + return __dcsrrd(reg); +} + +static inline void csr_writel(uint32_t val, uint32_t reg) +{ + __csrwr(val, reg); +} + +static inline void csr_writeq(unsigned long val, unsigned int reg) +{ + __dcsrwr(val, reg); +} + +static inline void enable_pg(unsigned long val) +{ + asm volatile("csrwr %0, 0x0" : : "r"(val)); +} + +static inline void write_csr_pgdl(unsigned long val) +{ + asm volatile("csrwr %0, 0x19" : : "r" (val)); +} + +static inline void write_csr_pgdh(unsigned long val) +{ + asm volatile("csrwr %0, 0x1a" : : "r" (val)); +} + +static inline void write_csr_pwcl(unsigned long val) +{ + asm volatile("csrwr %0, 0x1c" : : "r" (val)); +} + +static inline void write_csr_pwch(unsigned long val) +{ + asm volatile("csrwr %0, 0x1d" : : "r" (val)); +} + +static inline void write_csr_tlbrentry(unsigned long val) +{ + asm volatile("csrwr %0, 0x88" : : "r" (val)); +} + +static inline void write_csr_elf_debug_eentry(unsigned long val) +{ + asm volatile("csrwr %0, 0xc"::"r"(val)); +} + +static inline unsigned int read_csr_pagesize(void) +{ + return (__csrrd(LOONGARCH_CSR_TLBIDX) & CSR_TLBIDX_SIZEM) >> CSR_TLBIDX_SIZE; +} + +static inline void write_csr_pagesize(unsigned int size) +{ + __csrxchg(size << CSR_TLBIDX_SIZE, CSR_TLBIDX_SIZEM, LOONGARCH_CSR_TLBIDX); +} + +static inline unsigned int read_csr_tlbrefill_pagesize(void) +{ + return (__dcsrrd(LOONGARCH_CSR_TLBREHI) & CSR_TLBREHI_PS) >> CSR_TLBREHI_PS_SHIFT; +} + +static inline void write_csr_tlbrefill_pagesize(unsigned int size) +{ + __dcsrxchg(size << CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI); +} + +#define read_csr_stlbpgsize() __csrrd(LOONGARCH_CSR_STLBPGSIZE) +#define write_csr_stlbpgsize(val) __csrwr(val, LOONGARCH_CSR_STLBPGSIZE) + +#endif \ No newline at end of file diff --git a/elfloader-tool/include/elfloader_common.h b/elfloader-tool/include/elfloader_common.h index 7a54c316..3d952e20 100644 --- a/elfloader-tool/include/elfloader_common.h +++ b/elfloader-tool/include/elfloader_common.h @@ -12,9 +12,14 @@ typedef uintptr_t paddr_t; typedef uintptr_t vaddr_t; +#ifdef CONFIG_ARCH_LOONGARCH +#define PAGE_BITS 14 +#define BIT(x) (1UL<<(x)) +#else #define PAGE_BITS 12 - #define BIT(x) (1 << (x)) +#endif + #define MASK(n) (BIT(n) - 1) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define IS_ALIGNED(n, b) (!((n) & MASK(b))) diff --git a/elfloader-tool/src/arch-loongarch/boot.c b/elfloader-tool/src/arch-loongarch/boot.c new file mode 100644 index 00000000..257e075e --- /dev/null +++ b/elfloader-tool/src/arch-loongarch/boot.c @@ -0,0 +1,276 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * Derived from: + * Copyright 2020, DornerWorks + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * Copyright 2021, HENSOLDT Cyber + * + * SPDX-License-Identifier: GPL-2.0-only + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PT_LEVELS 3 + +#define PS_DEFAULT_64GSIZE 36 +#define PS_DEFAULT_32MSIZE 25 + +#define PT_LEVEL_1 1 +#define PT_LEVEL_2 2 +#define PT_LEVEL_3 3 + +#define PT_LEVEL_1_BITS 36 +#define PT_LEVEL_2_BITS 25 +#define PT_LEVEL_3_BITS 14 + +#define LOONGARCH_L1PGSHIFT PT_LEVEL_1_BITS +#define LOONGARCH_L2PGSHIFT PT_LEVEL_2_BITS +#define LOONGARCH_L3PGSHIFT PT_LEVEL_3_BITS + +#define PT_INDEX_BITS 11 + +#define PTES_PER_PT BIT(PT_INDEX_BITS) + +#define PTE_HUGE_PA_SHIFT 24 + +#define PTE_64GHUGE_PA(PT_BASE) (unsigned long)(((PT_BASE) >> LOONGARCH_L1PGSHIFT) << LOONGARCH_L1PGSHIFT) +#define PTE_HUGE_PA(PT_BASE) (unsigned long)(((PT_BASE) >> LOONGARCH_L2PGSHIFT) << LOONGARCH_L2PGSHIFT) +#define PTE_GSRWXV 0x11D3 + +#define PTE_CREATE_NEXT(PT_BASE) (unsigned long)PT_BASE +#define PTE_CREATE_64GHUGE_LEAF(PT_BASE) (unsigned long)(PTE_64GHUGE_PA(PT_BASE)|PTE_GSRWXV) +#define PTE_CREATE_HUGE_LEAF(PT_BASE) (unsigned long)(PTE_HUGE_PA(PT_BASE) | PTE_GSRWXV) + +#define GET_PT_INDEX(addr, n) (((addr) >> (((PT_INDEX_BITS) * ((PT_LEVELS) - (n))) + LOONGARCH_L3PGSHIFT)) % PTES_PER_PT) + +#define VIRT_PHYS_ALIGNED(virt, phys, level_bits) (IS_ALIGNED((virt), (level_bits)) && IS_ALIGNED((phys), (level_bits))) + +unsigned long l1pt[PTES_PER_PT] __attribute__((aligned(16384))); +unsigned long l2pt[PTES_PER_PT] __attribute__((aligned(16384))); + +struct image_info kernel_info; +struct image_info user_info; + +char elfloader_stack_alloc[BIT(CONFIG_KERNEL_STACK_BITS)]; + +/* first HART will initialise these */ +void const *dtb = NULL; +size_t dtb_size = 0; + +// unsigned long tlbrentry; + + +void NORETURN elfloader_panic(){ + printf("Oh man, entered trap in elfloader!\n"); + abort(); +} + + +/* + * overwrite the default implementation for abort() + */ +void NORETURN abort(void) +{ + printf("HALT due to call to abort()\n"); + + /* We could call the SBI shutdown now. However, it's likely there is an + * issue that needs to be debugged. Instead of doing a busy loop, spinning + * over a wfi is the better choice here, as it allows the core to enter an + * idle state until something happens. + */ + for (;;) { + asm volatile("idle 0" ::: "memory"); + } + + UNREACHABLE(); +} + +static void setup_pw(void) +{ + unsigned long pt_b, pt_w; + unsigned long dir1_b, dir1_w; + unsigned long dir2_b, dir2_w; + + pt_b = PT_LEVEL_3_BITS; + dir1_b = PT_LEVEL_2_BITS; + dir2_b = PT_LEVEL_1_BITS; + pt_w = dir1_w = dir2_w = PT_INDEX_BITS; + + write_csr_pwcl(dir1_w << 15 | dir1_b << 10 | pt_w << 5 | pt_b); + write_csr_pwch(dir2_w << 6 | dir2_b); + + write_csr_pgdh((unsigned long)l1pt); +} + +static inline void invtlb(void) +{ + asm volatile("invtlb 0x1, $r0, $r0" :::); +} + +static inline void dbar(void) +{ + asm volatile("dbar 0" ::: "memory"); +} + +static inline void ibar(void) +{ + asm volatile("ibar 0" ::: "memory"); +} + +extern void handle_tlb_refill(void); +extern void elfloader_trap_entry(void); + +static void setup_tlb_handler(void) +{ + write_csr_tlbrentry((unsigned long)handle_tlb_refill); +} + +static void init_tlb(void) +{ + write_csr_pagesize(PS_DEFAULT_32MSIZE); + write_csr_stlbpgsize(PS_DEFAULT_32MSIZE); + write_csr_tlbrefill_pagesize(PS_DEFAULT_32MSIZE); + + if (read_csr_pagesize() != PS_DEFAULT_32MSIZE) + printf("MMU doesn't support PAGE_SIZE\n"); + + setup_tlb_handler(); + // invtlb(); +} + +static int map_kernel_window(struct image_info *kernel_info) +{ + uint32_t index; + + /* Map the kernel into the new address space */ + + if (!VIRT_PHYS_ALIGNED((unsigned long)(kernel_info->virt_region_start), + (unsigned long)(kernel_info->phys_region_start), PT_LEVEL_2_BITS)) { + printf("ERROR: Kernel not properly aligned\n"); + return -1; + } + + + index = GET_PT_INDEX(kernel_info->virt_region_start, PT_LEVEL_1); + + // l1pt[index] =PTE_CREATE_64GHUGE_LEAF(kernel_info->phys_region_start); + + l1pt[index] = PTE_CREATE_NEXT((uintptr_t)l2pt); + index = GET_PT_INDEX(kernel_info->virt_region_start, PT_LEVEL_2); + + for (unsigned int page = 0; index < PTES_PER_PT; index++, page++) { + l2pt[index] = PTE_CREATE_HUGE_LEAF(kernel_info->phys_region_start + + (page << PT_LEVEL_2_BITS)); + } + + return 0; +} + +static inline void enable_virtual_memory(void) +{ + setup_pw(); + init_tlb(); + enable_pg(0xb0); +} + +static int run_elfloader(UNUSED int hart_id, void *bootloader_dtb) +{ + int ret; + + /* Unpack ELF images into memory. */ + unsigned int num_apps = 0; + ret = load_images(&kernel_info, &user_info, 1, &num_apps, + bootloader_dtb, &dtb, &dtb_size); + if (0 != ret) { + printf("ERROR: image loading failed, code %d\n", ret); + return -1; + } + + if (num_apps != 1) { + printf("ERROR: expected to load just 1 app, actually loaded %u apps\n", + num_apps); + return -1; + } + + ret = map_kernel_window(&kernel_info); + if (0 != ret) { + printf("ERROR: could not map kernel window, code %d\n", ret); + return -1; + } + + printf("Enabling MMU and paging\n"); + enable_virtual_memory(); + + printf("setting trap entry\n"); + write_csr_elf_debug_eentry((unsigned long)elfloader_trap_entry); + + printf("Jumping to kernel-image entry point...\n\n"); + printf("kernel_phys_region_start: %p\n", kernel_info.phys_region_start); + printf("kernel_phys_region_end: %p\n", kernel_info.phys_region_end); + printf("kernel_phys_virt_offset: %p\n", kernel_info.phys_virt_offset); + printf("kernel_virt_entry: %p\n", kernel_info.virt_entry); + printf("ui_phys_region_start: %p\n", user_info.phys_region_start); + printf("ui_phys_region_end: %p\n", user_info.phys_region_end); + printf("ui_phys_virt_offset: %p\n", user_info.phys_virt_offset); + printf("ui_virt_entry: %p\n", user_info.virt_entry); + printf("dtb physical address: %p\n", (word_t)dtb); + printf("dtb size: %d\n", dtb_size); + + ((init_loongarch_kernel_t)kernel_info.virt_entry)(user_info.phys_region_start, + user_info.phys_region_end, + user_info.phys_virt_offset, + user_info.virt_entry, + (word_t)dtb, + dtb_size +#if CONFIG_MAX_NUM_NODES > 1 + , + hart_id, + 0 +#endif + ); + + /* We should never get here. */ + printf("ERROR: Kernel returned back to the ELF Loader\n"); + return -1; +} + +void main(int hart_id, void *bootloader_dtb) +{ + /* initialize platform so that we can print to a UART */ + initialise_devices(); + + /* Printing uses UART*/ + printf("ELF-loader started on (HART %d) (NODES %d)\n", + hart_id, CONFIG_MAX_NUM_NODES); + + printf(" paddr=[%p..%p]\n", _text, _end - 1); + + /* Run the actual ELF loader, this is not expected to return unless there + * was an error. + */ + int ret = run_elfloader(hart_id, bootloader_dtb); + if (0 != ret) { + printf("ERROR: ELF-loader failed, code %d\n", ret); + /* There is nothing we can do to recover. */ + abort(); + UNREACHABLE(); + } + + /* We should never get here. */ + printf("ERROR: ELF-loader didn't hand over control\n"); + abort(); + UNREACHABLE(); +} diff --git a/elfloader-tool/src/arch-loongarch/crt0.S b/elfloader-tool/src/arch-loongarch/crt0.S new file mode 100644 index 00000000..7f4fe124 --- /dev/null +++ b/elfloader-tool/src/arch-loongarch/crt0.S @@ -0,0 +1,71 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * Derived from: + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include +#include + +.extern main +.extern elfloader_stack_alloc + +#define BIT(n) (1 << (n)) + +.section ".text.start" + +.global _start +_start: + + csrrd $t0, LOONGARCH_CSR_CPUID + move $s0, $t0 + li.d $t1, CONFIG_FIRST_HART_ID + bne $t0, $t1, spin_hart + +#ifdef CONFIG_IMAGE_BINARY +/* Clear the BSS before we get to do anything more specific */ + jal clear_bss +#endif + + move $a0, $t0 + b _start1 + +_start1: /* a0 must hold current hard ID passed by bootloader */ + /* a1 must hold dtb address passed by bootloader */ + li.d $t0, 0x6000000000000009 # no cache for uart, PLV0|PLV3, for hardware platforms + csrwr $t0, LOONGARCH_CSR_DMWIN0 + li.d $t0, 0x9000000000000011 # CA, PLV0, 0x9000 xxxx xxxx xxxx + csrwr $t0, LOONGARCH_CSR_DMWIN1 + # li.d $t0, 0x0000000000000011 # CA, PLV0, 0x9000 xxxx xxxx xxxx + # csrwr $t0, LOONGARCH_CSR_DMWIN2 + + li.w $t0, 0xb0 # PLV=0, IE=0, PG=1 + csrwr $t0, LOONGARCH_CSR_CRMD + li.w $t0, 0x04 # PLV=0, PIE=1, PWE=0 + csrwr $t0, LOONGARCH_CSR_PRMD + li.w $t0, 0x00 # FPE=0, SXE=0, ASXE=0, BTE=0 + csrwr $t0, LOONGARCH_CSR_EUEN + + la.abs $t0, 0f + jirl $zero, $t0, 0 + +0: + /* Attach the stack to sp before calling any C functions */ + la $sp, elfloader_stack_alloc + li.w $t0, 1 + slli.w $t0, $t0, 12 + add.d $sp, $sp, $t0 + /* The C code expects the registers to be set up as: + * a0 = hart id + * a1 = dtb + */ + b main + +spin_hart: + idle 0 + b spin_hart diff --git a/elfloader-tool/src/arch-loongarch/linker.lds b/elfloader-tool/src/arch-loongarch/linker.lds new file mode 100644 index 00000000..aca80e47 --- /dev/null +++ b/elfloader-tool/src/arch-loongarch/linker.lds @@ -0,0 +1,68 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * Derived from: + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + */ + + +#include +#include +#include "image_start_addr.h" + +ENTRY( _start ) + +SECTIONS +{ + . = IMAGE_START_ADDR; + _text = .; + .start : + { + *(.text.start) + } + .text : + { + *(.text) + . = ALIGN(16K); + elfloader_tlbrefillentry = .; + *(elfloader_tlbrefillentry) + . = ALIGN(16K); + elfloader_debug_eentry = .; + *(elfloader_debug_eentry) + } + . = ALIGN(16K); + .rodata : + { + *(.srodata*) + . = ALIGN(16K); + *(.rodata) + *(.rodata.*) + /* + * ld crashes when we add this here: *(_driver_list) + */ + . = ALIGN(16K); + _archive_start = .; + *(._archive_cpio) + _archive_end = .; + } + . = ALIGN(16K); + .data : + { + *(.sdata*) + *(.data) + *(.data.*) + } + . = ALIGN(16K); + .bss : + { + _bss = .; + *(.sbss*) + *(.bss) + *(.bss.*) + _bss_end = .; + } + _end = .; +} diff --git a/elfloader-tool/src/arch-loongarch/tlbex.S b/elfloader-tool/src/arch-loongarch/tlbex.S new file mode 100644 index 00000000..ad3dbdf2 --- /dev/null +++ b/elfloader-tool/src/arch-loongarch/tlbex.S @@ -0,0 +1,38 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * qtliu@mail.ustc.edu.cn, le24@mail.ustc.edu.cn, chenyangcs@mail.ustc.edu.cn + * + * Derived from: + * Copyright (C) 2020-2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: GPL-2.0 + */ + +# The level2 page directory base we designed is 36, which can`t be filled +# in csr.pwcl.Dir2_base. Because csr.pwcl.Dir2_base is 5 bit length(0~2^5-1). +# Instead, we write 36 into csr.pwch.Dir3_base, which is 6 bit length(2^6-1 = 63 > 36). +# See LoongArch manual for details. +#include + .section elfloader_tlbrefillentry + .global handle_tlb_refill +handle_tlb_refill: + csrwr $t0, LOONGARCH_CSR_TLBRSAVE + csrwr $t1, LOONGARCH_CSR_KS6 /* use t1 for debugging */ + csrrd $t1, LOONGARCH_CSR_TLBREHI + csrrd $t0, LOONGARCH_CSR_PGD + csrrd $t1, LOONGARCH_CSR_TLBREHI + lddir $t0, $t0, 3 + csrrd $t1, LOONGARCH_CSR_TLBREHI + lddir $t0, $t0, 1 + csrrd $t1, LOONGARCH_CSR_TLBREHI + ldpte $t0, 0 + csrrd $t1, LOONGARCH_CSR_TLBREHI + ldpte $t0, 1 + csrrd $t1, LOONGARCH_CSR_TLBREHI + tlbfill + csrrd $t1, LOONGARCH_CSR_TLBREHI + csrrd $t1, LOONGARCH_CSR_TLBRELO0 + csrrd $t1, LOONGARCH_CSR_TLBRELO1 + csrwr $t1, LOONGARCH_CSR_KS6 + csrwr $t0, LOONGARCH_CSR_TLBRSAVE + ertn \ No newline at end of file diff --git a/elfloader-tool/src/arch-loongarch/traps.S b/elfloader-tool/src/arch-loongarch/traps.S new file mode 100644 index 00000000..2b83ad6b --- /dev/null +++ b/elfloader-tool/src/arch-loongarch/traps.S @@ -0,0 +1,22 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * + * Derived from: + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * Copyright 2015, 2016 Hesham Almatary + * + * SPDX-License-Identifier: GPL-2.0-only + */ +#include +#define REGBYTES 8 + +.section elfloader_debug_eentry + +.global elfloader_trap_entry +.extern elfloader_panic + +elfloader_trap_entry: + + csrrd $s0, LOONGARCH_CSR_ESTAT // read csr_estat to s0 + + b elfloader_panic \ No newline at end of file diff --git a/elfloader-tool/src/common.c b/elfloader-tool/src/common.c index c3fa882b..86976f6b 100644 --- a/elfloader-tool/src/common.c +++ b/elfloader-tool/src/common.c @@ -127,7 +127,7 @@ static int unpack_elf_to_paddr( } /* Zero out all memory in the region, as the ELF file may be sparse. */ - memset((void *)dest_paddr, 0, image_size); + memset((void *)(dest_paddr | 0x9000000000000000), 0, image_size); /* Load each segment in the ELF file. */ for (unsigned int i = 0; i < elf_getNumProgramHeaders(elf); i++) { @@ -160,7 +160,7 @@ static int unpack_elf_to_paddr( } /* Load data into memory. */ - memcpy((void *)seg_dest_paddr, seg_src_addr, seg_size); + memcpy((void *)(seg_dest_paddr | 0x9000000000000000), seg_src_addr, seg_size); } return 0; @@ -338,9 +338,9 @@ static int load_elf( * memcpy to a bunch of magic offsets. Explicit numbers for sizes * and offsets are used so that it is clear exactly what the layout * is */ - memcpy((void *)dest_paddr, &phnum, 4); - memcpy((void *)(dest_paddr + 4), &phsize, 4); - memcpy((void *)(dest_paddr + 8), (void *)source_paddr, phsize * phnum); + memcpy((void *)(dest_paddr | 0x9000000000000000), &phnum, 4); + memcpy((void *)((dest_paddr + 4) | 0x9000000000000000), &phsize, 4); + memcpy((void *)((dest_paddr + 8) | 0x9000000000000000), (void *)source_paddr, phsize * phnum); /* return the frame after our headers */ dest_paddr += KEEP_HEADERS_SIZE; } @@ -461,6 +461,7 @@ int load_images( dtb = bootloader_dtb; } + *chosen_dtb_size = 0; /* * Move the DTB out of the way, if it's present. */ @@ -482,7 +483,7 @@ int load_images( return -1; } - memmove((void *)next_phys_addr, dtb, dtb_size); + memmove((void *)(next_phys_addr | 0x9000000000000000), dtb, dtb_size); next_phys_addr += dtb_size; next_phys_addr = ROUND_UP(next_phys_addr, PAGE_BITS); dtb_phys_end = next_phys_addr; @@ -572,6 +573,8 @@ int load_images( #endif /* CONFIG_ELFLOADER_ROOTSERVERS_LAST */ + // next_phys_addr = ROUND_UP(kernel_phys_end, PAGE_BITS); + *num_images = 0; for (unsigned int i = 0; i < max_user_images; i++) { /* Fetch info about the next ELF file in the archive. */ diff --git a/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c b/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c new file mode 100644 index 00000000..83cac2a6 --- /dev/null +++ b/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c @@ -0,0 +1,65 @@ +/* + * Copyright 2022, tyyteam(Qingtao Liu, Yang Lei, Yang Chen) + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include +#include +#include + +#include + +#define UART_REG_DAT 0x00 +#define UART_REG_IER 0x01 +#define UART_REG_IIR 0x02 +#define UART_REG_FCR 0x02 +#define UART_REG_LCR 0x03 +#define UART_REG_MCR 0x04 +#define UART_REG_LSR 0x05 +#define UART_REG_MSR 0x06 + +#define UART_REG_LSR_TE BIT(6) +#define UART_REG_LSR_TFE BIT(5) + +#define UART_REG(mmio, x) ((volatile uint8_t *)(((unsigned long)(mmio) + (x)) | 0x6000000000000000)) + +static int loongson3A5000_uart_putchar(struct elfloader_device *dev, unsigned int c) +{ + volatile void *mmio = dev->region_bases[0]; + while (!(*UART_REG(mmio, UART_REG_LSR) & UART_REG_LSR_TE)); + asm volatile( + "csrwr $t0, 0x34 \n" + "csrwr $t1, 0x35 \n" + "li.d $t1, 0x1fe001e5 \n" + "iocsrrd.b $t0, $t1 \n" + "csrrd $t0, 0x34 \n" + "csrrd $t1, 0x35 \n"); + *UART_REG(mmio, UART_REG_DAT) = (c & 0xff); + + return 0; +} + +static int loongson3A5000_uart_init(struct elfloader_device *dev, UNUSED void *match_data) +{ + uart_set_out(dev); + return 0; +} + +static const struct dtb_match_table loongson3A5000_uart_matches[] = { + { .compatible = "3A5000,loongson3A5000-uart" }, + { .compatible = NULL /* sentinel */ }, +}; + +static const struct elfloader_uart_ops loongson3A5000_uart_ops = { + .putc = &loongson3A5000_uart_putchar, +}; + +static const struct elfloader_driver loongson3A5000_uart = { + .match_table = loongson3A5000_uart_matches, + .type = DRIVER_UART, + .init = &loongson3A5000_uart_init, + .ops = &loongson3A5000_uart_ops, +}; + +ELFLOADER_DRIVER(loongson3A5000_uart); From a3209535f7966c003af67110e8fdf09eead6f766 Mon Sep 17 00:00:00 2001 From: Yang Chen Date: Mon, 22 May 2023 16:57:32 +0800 Subject: [PATCH 2/3] uart: clean debug code --- elfloader-tool/src/drivers/uart/loongson3A5000-uart.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c b/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c index 83cac2a6..157510c2 100644 --- a/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c +++ b/elfloader-tool/src/drivers/uart/loongson3A5000-uart.c @@ -28,13 +28,6 @@ static int loongson3A5000_uart_putchar(struct elfloader_device *dev, unsigned in { volatile void *mmio = dev->region_bases[0]; while (!(*UART_REG(mmio, UART_REG_LSR) & UART_REG_LSR_TE)); - asm volatile( - "csrwr $t0, 0x34 \n" - "csrwr $t1, 0x35 \n" - "li.d $t1, 0x1fe001e5 \n" - "iocsrrd.b $t0, $t1 \n" - "csrrd $t0, 0x34 \n" - "csrrd $t1, 0x35 \n"); *UART_REG(mmio, UART_REG_DAT) = (c & 0xff); return 0; From c67380c702876db5a6d0c921850919cc777227cf Mon Sep 17 00:00:00 2001 From: Chen Yang Date: Thu, 19 Oct 2023 15:46:43 +0800 Subject: [PATCH 3/3] style --- cmake-tool/helpers/application_settings.cmake | 2 +- elfloader-tool/src/arch-loongarch/boot.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake-tool/helpers/application_settings.cmake b/cmake-tool/helpers/application_settings.cmake index 7a358633..2d4ad6e8 100644 --- a/cmake-tool/helpers/application_settings.cmake +++ b/cmake-tool/helpers/application_settings.cmake @@ -269,7 +269,7 @@ function(correct_platform_strings) set(KernelSel4Arch "riscv64" CACHE STRING "" FORCE) elseif(RISCV32) set(KernelSel4Arch "riscv32" CACHE STRING "" FORCE) - elseif(Loongarch64) + elseif(LOONGARCH64) set(KernelSel4Arch "loongarch64" CACHE STRING "" FORCE) else() set(_REWRITE OFF) diff --git a/elfloader-tool/src/arch-loongarch/boot.c b/elfloader-tool/src/arch-loongarch/boot.c index 257e075e..e7ea5113 100644 --- a/elfloader-tool/src/arch-loongarch/boot.c +++ b/elfloader-tool/src/arch-loongarch/boot.c @@ -51,7 +51,7 @@ #define PTE_GSRWXV 0x11D3 #define PTE_CREATE_NEXT(PT_BASE) (unsigned long)PT_BASE -#define PTE_CREATE_64GHUGE_LEAF(PT_BASE) (unsigned long)(PTE_64GHUGE_PA(PT_BASE)|PTE_GSRWXV) +#define PTE_CREATE_64GHUGE_LEAF(PT_BASE) (unsigned long)(PTE_64GHUGE_PA(PT_BASE) | PTE_GSRWXV) #define PTE_CREATE_HUGE_LEAF(PT_BASE) (unsigned long)(PTE_HUGE_PA(PT_BASE) | PTE_GSRWXV) #define GET_PT_INDEX(addr, n) (((addr) >> (((PT_INDEX_BITS) * ((PT_LEVELS) - (n))) + LOONGARCH_L3PGSHIFT)) % PTES_PER_PT) @@ -117,7 +117,7 @@ static void setup_pw(void) static inline void invtlb(void) { - asm volatile("invtlb 0x1, $r0, $r0" :::); + asm volatile("invtlb 0x0, $r0, $r0" :::); } static inline void dbar(void) @@ -148,7 +148,7 @@ static void init_tlb(void) printf("MMU doesn't support PAGE_SIZE\n"); setup_tlb_handler(); - // invtlb(); + invtlb(); } static int map_kernel_window(struct image_info *kernel_info)