diff --git a/.github/ALL_BSP_COMPILE.json b/.github/ALL_BSP_COMPILE.json index 2ecdfbf41548..9bb9240d0e72 100644 --- a/.github/ALL_BSP_COMPILE.json +++ b/.github/ALL_BSP_COMPILE.json @@ -529,7 +529,6 @@ "xuantie/smartl/e907", "xuantie/xiaohui/c906", "xuantie/xiaohui/c907", - "xuantie/xiaohui/c908", "xuantie/xiaohui/c908x", "xuantie/xiaohui/c920", "xuantie/xiaohui/r908", @@ -542,7 +541,8 @@ "RTT_TOOL_CHAIN": "sourcery-Xuantie-900-gcc-linux-musl", "SUB_RTT_BSP": [ "xuantie/virt64/c906", - "xuantie/virt64/c908" + "xuantie/virt64/c908", + "xuantie/xiaohui/c908" ] }, { diff --git a/bsp/xuantie/xiaohui/c908/.config b/bsp/xuantie/xiaohui/c908/.config index 99ff2affe142..758d5627caf3 100644 --- a/bsp/xuantie/xiaohui/c908/.config +++ b/bsp/xuantie/xiaohui/c908/.config @@ -1,4 +1,5 @@ CONFIG_XUANTIAN_XIAOHUI_C908=y +CONFIG___STACKSIZE__=65536 # # CPU Architecture Features @@ -114,10 +115,10 @@ CONFIG_ENABLE_VECTOR=y # end of rt_strnlen options # end of klibc options -CONFIG_RT_NAME_MAX=12 +CONFIG_RT_NAME_MAX=16 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set # CONFIG_RT_USING_NANO is not set -# CONFIG_RT_USING_SMART is not set +CONFIG_RT_USING_SMART=y # CONFIG_RT_USING_AMP is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_CPUS_NR=1 @@ -133,12 +134,13 @@ CONFIG_RT_HOOK_USING_FUNC_PTR=y # CONFIG_RT_USING_HOOKLIST is not set CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 -CONFIG_IDLE_THREAD_STACK_SIZE=8192 +CONFIG_IDLE_THREAD_STACK_SIZE=16384 CONFIG_RT_USING_TIMER_SOFT=y CONFIG_RT_TIMER_THREAD_PRIO=4 -CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384 # CONFIG_RT_USING_TIMER_ALL_SOFT is not set -# CONFIG_RT_USING_CPU_USAGE_TRACER is not set +CONFIG_RT_USING_CPU_USAGE_TRACER=y +CONFIG_RT_CPU_USAGE_CALC_INTERVAL_MS=200 # # kservice options @@ -162,19 +164,19 @@ CONFIG_RT_USING_EVENT=y CONFIG_RT_USING_MAILBOX=y CONFIG_RT_USING_MESSAGEQUEUE=y # CONFIG_RT_USING_MESSAGEQUEUE_PRIORITY is not set -# CONFIG_RT_USING_SIGNALS is not set +CONFIG_RT_USING_SIGNALS=y # end of Inter-Thread communication # # Memory Management # -# CONFIG_RT_USING_MEMPOOL is not set +CONFIG_RT_USING_MEMPOOL=y CONFIG_RT_USING_SMALL_MEM=y -# CONFIG_RT_USING_SLAB is not set +CONFIG_RT_USING_SLAB=y # CONFIG_RT_USING_MEMHEAP is not set -CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y +# CONFIG_RT_USING_SMALL_MEM_AS_HEAP is not set # CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set -# CONFIG_RT_USING_SLAB_AS_HEAP is not set +CONFIG_RT_USING_SLAB_AS_HEAP=y # CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_NOHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set @@ -183,20 +185,23 @@ CONFIG_RT_USING_HEAP=y # end of Memory Management CONFIG_RT_USING_DEVICE=y -# CONFIG_RT_USING_DEVICE_OPS is not set +CONFIG_RT_USING_DEVICE_OPS=y # CONFIG_RT_USING_INTERRUPT_INFO is not set -# CONFIG_RT_USING_THREADSAFE_PRINTF is not set +CONFIG_RT_USING_THREADSAFE_PRINTF=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=512 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" CONFIG_RT_USING_CONSOLE_OUTPUT_CTL=y CONFIG_RT_VER_NUM=0x50300 -# CONFIG_RT_USING_STDC_ATOMIC is not set +CONFIG_RT_USING_STDC_ATOMIC=y CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 # end of RT-Thread Kernel CONFIG_ARCH_CPU_64BIT=y +CONFIG_RT_USING_CACHE=y CONFIG_RT_USING_HW_ATOMIC=y +CONFIG_ARCH_MM_MMU=y +CONFIG_KERNEL_VADDR_START=0xffffffc000000000 CONFIG_ARCH_RISCV=y CONFIG_ARCH_RISCV_FPU=y CONFIG_ARCH_RISCV_VECTOR=y @@ -209,13 +214,14 @@ CONFIG_ARCH_VECTOR_VLEN_128=y CONFIG_ARCH_RISCV_FPU_D=y CONFIG_ARCH_RISCV64=y CONFIG_ARCH_USING_NEW_CTX_SWITCH=y +CONFIG_ARCH_REMAP_KERNEL=y # # RT-Thread Components # CONFIG_RT_USING_COMPONENTS_INIT=y CONFIG_RT_USING_USER_MAIN=y -CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192 +CONFIG_RT_MAIN_THREAD_STACK_SIZE=16384 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set CONFIG_RT_USING_MSH=y @@ -223,7 +229,7 @@ CONFIG_RT_USING_FINSH=y CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_THREAD_NAME="tshell" CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=8192 +CONFIG_FINSH_THREAD_STACK_SIZE=16384 CONFIG_FINSH_USING_HISTORY=y CONFIG_FINSH_HISTORY_LINES=5 # CONFIG_FINSH_USING_WORD_OPERATION is not set @@ -240,7 +246,56 @@ CONFIG_FINSH_USING_OPTION_COMPLETION=y # # DFS: device virtual file system # -# CONFIG_RT_USING_DFS is not set +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FD_MAX=32 +CONFIG_RT_USING_DFS_V2=y +CONFIG_RT_USING_DFS_ELMFAT=y + +# +# elm-chan's FatFs, Generic FAT Filesystem Module +# +CONFIG_RT_DFS_ELM_CODE_PAGE=437 +CONFIG_RT_DFS_ELM_WORD_ACCESS=y +# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set +# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set +CONFIG_RT_DFS_ELM_USE_LFN_3=y +CONFIG_RT_DFS_ELM_USE_LFN=3 +CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y +# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set +# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set +CONFIG_RT_DFS_ELM_LFN_UNICODE=0 +CONFIG_RT_DFS_ELM_MAX_LFN=255 +CONFIG_RT_DFS_ELM_DRIVES=2 +CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 +# CONFIG_RT_DFS_ELM_USE_ERASE is not set +CONFIG_RT_DFS_ELM_REENTRANT=y +CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000 +# CONFIG_RT_DFS_ELM_USE_EXFAT is not set +# end of elm-chan's FatFs, Generic FAT Filesystem Module + +CONFIG_RT_USING_DFS_DEVFS=y +CONFIG_RT_USING_DFS_ROMFS=y +CONFIG_RT_USING_DFS_PTYFS=y +CONFIG_RT_USING_DFS_PROCFS=y +# CONFIG_RT_USING_DFS_CROMFS is not set +CONFIG_RT_USING_DFS_TMPFS=y +CONFIG_RT_USING_DFS_MQUEUE=y +CONFIG_RT_USING_PAGECACHE=y + +# +# page cache config +# +CONFIG_RT_PAGECACHE_COUNT=4096 +CONFIG_RT_PAGECACHE_ASPACE_COUNT=1024 +CONFIG_RT_PAGECACHE_PRELOAD=4 +CONFIG_RT_PAGECACHE_HASH_NR=1024 +CONFIG_RT_PAGECACHE_GC_WORK_LEVEL=90 +CONFIG_RT_PAGECACHE_GC_STOP_LEVEL=70 +# end of page cache config # end of DFS: device virtual file system # CONFIG_RT_USING_FAL is not set @@ -249,33 +304,39 @@ CONFIG_FINSH_USING_OPTION_COMPLETION=y # Device Drivers # # CONFIG_RT_USING_DM is not set -# CONFIG_RT_USING_DEV_BUS is not set +CONFIG_RT_USING_DEV_BUS=y CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_UNAMED_PIPE_NUMBER=64 -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=8192 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set # CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 -# CONFIG_RT_USING_SERIAL_BYPASS is not set +CONFIG_RT_USING_SERIAL_BYPASS=y # CONFIG_RT_USING_CAN is not set -# CONFIG_RT_USING_CLOCK_TIME is not set +# CONFIG_RT_USING_ADC is not set +CONFIG_RT_USING_CLOCK_TIME=y +# CONFIG_RT_USING_CLOCK_TIMER_TRIGGER is not set +CONFIG_CLOCK_TIMER_FREQ=0 # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set # CONFIG_RT_USING_PHY_V2 is not set -# CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set -# CONFIG_RT_USING_NULL is not set -# CONFIG_RT_USING_ZERO is not set -# CONFIG_RT_USING_RANDOM is not set +CONFIG_RT_USING_NULL=y +CONFIG_RT_USING_ZERO=y +CONFIG_RT_USING_RANDOM=y # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_PULSE_ENCODER is not set # CONFIG_RT_USING_INPUT_CAPTURE is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set # CONFIG_RT_USING_PM is not set -# CONFIG_RT_USING_RTC is not set +CONFIG_RT_USING_RTC=y +# CONFIG_RT_USING_ALARM is not set +CONFIG_RT_USING_SOFT_RTC=y # CONFIG_RT_USING_SDIO is not set # CONFIG_RT_USING_SPI is not set # CONFIG_RT_USING_WDT is not set @@ -285,10 +346,10 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_LCD is not set # CONFIG_RT_USING_HWCRYPTO is not set # CONFIG_RT_USING_WIFI is not set +# CONFIG_RT_USING_RPMSG is not set # CONFIG_RT_USING_BLK is not set # CONFIG_RT_USING_REGULATOR is not set # CONFIG_RT_USING_POWER_SUPPLY is not set -# CONFIG_RT_USING_VIRTIO is not set # CONFIG_RT_USING_PIN is not set # CONFIG_RT_USING_CHERRYUSB is not set # end of Device Drivers @@ -315,17 +376,31 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # # POSIX (Portable Operating System Interface) layer # -# CONFIG_RT_USING_POSIX_FS is not set -# CONFIG_RT_USING_POSIX_DELAY is not set -# CONFIG_RT_USING_POSIX_CLOCK is not set -# CONFIG_RT_USING_POSIX_TIMER is not set +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +CONFIG_RT_USING_POSIX_STDIO=y +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y +CONFIG_RT_USING_POSIX_EVENTFD=y +CONFIG_RT_USING_POSIX_EPOLL=y +CONFIG_RT_USING_POSIX_SIGNALFD=y +CONFIG_RT_SIGNALFD_MAX_NUM=10 +CONFIG_RT_USING_POSIX_TIMERFD=y +# CONFIG_RT_USING_POSIX_SOCKET is not set +CONFIG_RT_USING_POSIX_TERMIOS=y +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_POSIX_MMAN is not set +CONFIG_RT_USING_POSIX_DELAY=y +CONFIG_RT_USING_POSIX_CLOCK=y +CONFIG_RT_USING_POSIX_TIMER=y # CONFIG_RT_USING_PTHREADS is not set # CONFIG_RT_USING_MODULE is not set # # Interprocess Communication (IPC) # -# CONFIG_RT_USING_POSIX_PIPE is not set +CONFIG_RT_USING_POSIX_PIPE=y +CONFIG_RT_USING_POSIX_PIPE_SIZE=512 # CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set # CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set @@ -361,11 +436,47 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set # CONFIG_RT_USING_VAR_EXPORT is not set -# CONFIG_RT_USING_RESOURCE_ID is not set -# CONFIG_RT_USING_ADT is not set +CONFIG_RT_USING_RESOURCE_ID=y +CONFIG_RT_USING_ADT=y +CONFIG_RT_USING_ADT_AVL=y +CONFIG_RT_USING_ADT_BITMAP=y +CONFIG_RT_USING_ADT_HASHMAP=y +CONFIG_RT_USING_ADT_REF=y # CONFIG_RT_USING_RT_LINK is not set # end of Utilities +# +# Memory management +# +# CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC is not set +CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000 +CONFIG_RT_PAGE_MAX_ORDER=11 +# CONFIG_RT_USING_MEMBLOCK is not set + +# +# Debugging +# +# CONFIG_RT_DEBUGGING_ALIASING is not set +# CONFIG_RT_DEBUGING_PAGE_LEAK is not set +# CONFIG_RT_DEBUGGING_PAGE_POISON is not set +# end of Debugging +# end of Memory management + +CONFIG_RT_USING_LWP=y +# CONFIG_LWP_DEBUG is not set +CONFIG_LWP_USING_RUNTIME=y +CONFIG_RT_LWP_MAX_NR=30 +CONFIG_LWP_TASK_STACK_SIZE=16384 +CONFIG_RT_CH_MSG_MAX_NR=1024 +CONFIG_LWP_TID_MAX_NR=64 +CONFIG_RT_LWP_SHM_MAX_NR=64 +CONFIG_RT_USING_LDSO=y +# CONFIG_ELF_DEBUG_ENABLE is not set +# CONFIG_ELF_LOAD_RANDOMIZE is not set +CONFIG_LWP_USING_TERMINAL=y +CONFIG_LWP_PTY_MAX_PARIS_LIMIT=32 +CONFIG_RT_USING_VDSO=y + # # Using USB legacy version # @@ -374,6 +485,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # end of Using USB legacy version # CONFIG_RT_USING_FDT is not set +# CONFIG_RT_USING_LEGACY_VIRTIO is not set # CONFIG_RT_USING_RUST is not set # end of RT-Thread Components @@ -481,6 +593,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_ABUP_FOTA is not set # CONFIG_PKG_USING_LIBCURL2RTT is not set # CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_ERPC is not set # CONFIG_PKG_USING_AGILE_TELNET is not set # CONFIG_PKG_USING_NMEALIB is not set # CONFIG_PKG_USING_PDULIB is not set @@ -655,6 +768,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_UORB is not set # CONFIG_PKG_USING_RT_TUNNEL is not set # CONFIG_PKG_USING_VIRTUAL_TERMINAL is not set +# CONFIG_PKG_USING_FEE is not set # end of tools packages # @@ -836,7 +950,21 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_NUCLEI_SDK is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_RP2350_SDK is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set -# CONFIG_PKG_USING_MM32 is not set + +# +# MM32 HAL & SDK Drivers +# +# CONFIG_PKG_USING_MM32F103XX_CMSIS is not set +# CONFIG_PKG_USING_MM32F3270X_CMSIS is not set +# CONFIG_PKG_USING_MM32F5260X_CMSIS is not set +# CONFIG_PKG_USING_MM32L0XX_CMSIS is not set +# CONFIG_PKG_USING_MM32L3XX_CMSIS is not set +# CONFIG_PKG_USING_MM32F103XX_HAL_DRIVER is not set +# CONFIG_PKG_USING_MM32F3270X_HAL_DRIVER is not set +# CONFIG_PKG_USING_MM32F5260X_HAL_DRIVER is not set +# CONFIG_PKG_USING_MM32L0XX_HAL_DRIVER is not set +# CONFIG_PKG_USING_MM32L3XX_HAL_DRIVER is not set +# end of MM32 HAL & SDK Drivers # # WCH HAL & SDK Drivers @@ -924,6 +1052,23 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_FT32F4_STD_DRIVER is not set # CONFIG_PKG_USING_FT32F4_CMSIS_DRIVER is not set # end of FT32 HAL & SDK Drivers + +# +# NOVOSNS Drivers +# +# CONFIG_PKG_USING_NOVOSNS_SERIES_DRIVER is not set +# end of NOVOSNS Drivers + +# +# N32 Drivers +# +# CONFIG_PKG_USING_N32H7XX_STD_DRIVER is not set +# CONFIG_PKG_USING_N32H7XX_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_N32H49X_STD_DRIVER is not set +# CONFIG_PKG_USING_N32H49X_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_N32H47X_48X_STD_DRIVER is not set +# CONFIG_PKG_USING_N32H47X_48X_CMSIS_DRIVER is not set +# end of N32 Drivers # end of HAL & SDK Drivers # @@ -1057,6 +1202,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_WK2124 is not set # CONFIG_PKG_USING_LY68L6400 is not set # CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_CH390 is not set # CONFIG_PKG_USING_SSD1306 is not set # CONFIG_PKG_USING_QKEY is not set # CONFIG_PKG_USING_RS485 is not set @@ -1107,6 +1253,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_IRUART is not set # CONFIG_PKG_USING_ST7305 is not set # CONFIG_PKG_USING_TM1668 is not set +# CONFIG_PKG_USING_TCA9548A is not set # CONFIG_PKG_USING_SPI_TOOLS is not set # end of peripheral libraries and drivers @@ -1206,6 +1353,7 @@ CONFIG_RT_LIBC_TZ_DEFAULT_SEC=0 # CONFIG_PKG_USING_QPARAM is not set # CONFIG_PKG_USING_CorevMCU_CLI is not set # CONFIG_PKG_USING_DRMP is not set +# CONFIG_PKG_USING_AUTOGEN_PARAMETER_MANAGER is not set # end of miscellaneous packages # diff --git a/bsp/xuantie/xiaohui/c908/Kconfig b/bsp/xuantie/xiaohui/c908/Kconfig index 2bd764435d33..9db49b13ff1e 100644 --- a/bsp/xuantie/xiaohui/c908/Kconfig +++ b/bsp/xuantie/xiaohui/c908/Kconfig @@ -11,8 +11,15 @@ PKGS_DIR := packages select ARCH_RISCV64 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN + select ARCH_MM_MMU + select RT_USING_CACHE + select ARCH_REMAP_KERNEL if RT_USING_SMART default y + config __STACKSIZE__ + int "stack size for interrupt" + default 65536 + menu "CPU Architecture Features" menuconfig ENABLE_FPU diff --git a/bsp/xuantie/xiaohui/c908/SConstruct b/bsp/xuantie/xiaohui/c908/SConstruct index d4dd24f330ee..bdbb61be614a 100644 --- a/bsp/xuantie/xiaohui/c908/SConstruct +++ b/bsp/xuantie/xiaohui/c908/SConstruct @@ -1,54 +1,58 @@ import os import sys import rtconfig -from SCons.Script import * +import platform +import subprocess -if os.getenv('RTT_ROOT'): - RTT_ROOT = os.getenv('RTT_ROOT') -else: - RTT_ROOT = os.path.normpath(os.getcwd() + '/../../../..') +from rtconfig import RTT_ROOT +import sys -sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +def generate_ldscript(input, output): + if not os.path.exists(input): + print('Error: file', input, 'not found') + return + + if os.path.exists(output): + os.remove(output) + + if rtconfig.PLATFORM == 'gcc': + + gcc_cmd = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC) + + # gcc -E -P -x c $input -o $output + if (platform.system() == 'Windows'): + child = subprocess.Popen([gcc_cmd, '-E', '-P', '-x', 'c', input, '-o', output], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + else: + child = subprocess.Popen(gcc_cmd + f' -E -P -x c {input} -o {output}', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + + child.communicate() + + print(output, 'is generated from', input) -try: - from building import * -except: - print('Cannot found RT-Thread root directory, please check RTT_ROOT') - print(RTT_ROOT) - exit(-1) +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * TARGET = 'rtthread.' + rtconfig.TARGET_EXT DefaultEnvironment(tools=[]) env = Environment(tools = ['mingw'], AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, - CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS, - AR = rtconfig.AR, ARFLAGS = '-rc', + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] Export('RTT_ROOT') Export('rtconfig') -SDK_ROOT = os.path.abspath('./') - -if os.path.exists(SDK_ROOT + '/libraries'): - libraries_path_prefix = SDK_ROOT + '../libraries' -else: - libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/../libraries' +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) -SDK_LIB = libraries_path_prefix -Export('SDK_LIB') - -# prepare building environment -objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True) - -bsp_vdir = 'build' -library_vdir = 'build/libraries' - -# common include drivers -objs.extend(SConscript(os.path.join(libraries_path_prefix, 'SConscript'), variant_dir=library_vdir, duplicate=0)) +generate_ldscript('link.lds', 'link.lds.generated') # make a building DoBuilding(TARGET, objs) + +Clean(TARGET, 'link.lds.generated') +Clean(TARGET, 'build') diff --git a/bsp/xuantie/xiaohui/c908/applications/SConscript b/bsp/xuantie/xiaohui/c908/applications/SConscript index f129b3262457..05bd1ba15dbb 100644 --- a/bsp/xuantie/xiaohui/c908/applications/SConscript +++ b/bsp/xuantie/xiaohui/c908/applications/SConscript @@ -3,7 +3,14 @@ import os cwd = GetCurrentDir() CPPPATH = [cwd] -src = ['main.c'] +src = ['main.c', 'mnt.c', 'mmu_demo.c'] + +# romfs_data.c is generated by tools/mkromfs.py. +# Fall back to the placeholder image when it is absent. +if os.path.exists(os.path.join(cwd, 'romfs_data.c')): + src += ['romfs_data.c'] +else: + src += ['romfs.c'] group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) diff --git a/bsp/xuantie/xiaohui/c908/applications/main.c b/bsp/xuantie/xiaohui/c908/applications/main.c index b8ea541b9574..8eb5a90f1451 100644 --- a/bsp/xuantie/xiaohui/c908/applications/main.c +++ b/bsp/xuantie/xiaohui/c908/applications/main.c @@ -8,17 +8,11 @@ * 2025-04-21 Wangshun first version */ - #include - #include - #include "pre_main.h" +#include - int main(void) - { - rt_kprintf("Hello RT-Thread!\r\n"); -#ifdef RT_USING_SMP - extern void smp_example(void); - smp_example(); -#endif - return 0; - } +int main(void) +{ + rt_kprintf("Hello RT-Thread!\r\n"); + return 0; +} diff --git a/bsp/xuantie/xiaohui/c908/applications/mmu_demo.c b/bsp/xuantie/xiaohui/c908/applications/mmu_demo.c new file mode 100644 index 000000000000..703292776636 --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/applications/mmu_demo.c @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#if defined(RT_USING_SMART) && defined(ARCH_MM_MMU) + +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef RT_USING_DFS +#include +#include +#include +#include +#include +#endif /* RT_USING_DFS */ + +#define DEMO_MAGIC_A 0x5a5aa5a5c908c908ULL +#define DEMO_MAGIC_B 0xdeadbeef1234abcdULL + +/* satp.PPN is 44 bits wide on RV64 */ +#define SATP_PPN_MASK ((1UL << 44) - 1) + +/* returned by _walk_v2p() when the walk stops on an invalid PTE */ +#define WALK_LEVEL_NONE (-1) + +static int _pass; +static int _fail; +static int _skip; + +#define CHECK(expr, ...) \ + do \ + { \ + if (expr) \ + { \ + _pass++; \ + rt_kprintf(" [ OK ] "); \ + } \ + else \ + { \ + _fail++; \ + rt_kprintf(" [FAIL] "); \ + } \ + rt_kprintf(__VA_ARGS__); \ + rt_kprintf("\n"); \ + } while (0) + +#define SKIP(...) \ + do \ + { \ + _skip++; \ + rt_kprintf(" [SKIP] "); \ + rt_kprintf(__VA_ARGS__); \ + rt_kprintf("\n"); \ + } while (0) + +/* + * Translate vaddr by hand, starting from a given top level page table. This + * deliberately does not go through rt_hw_mmu_v2p() so that the two results can + * be cross-checked. + */ +static void *_walk_table(rt_pte_t *tbl, void *vaddr, int *level_out, rt_size_t *pgsize_out) +{ + rt_ubase_t pvoff = PV_OFFSET; + int level; + + *level_out = WALK_LEVEL_NONE; + *pgsize_out = 0; + + for (level = 1; level <= ARCH_PAGE_TBL_LEVELS; level++) + { + rt_pte_t pte = tbl[GET_LVL_INDEX(vaddr, level)]; + + if (!PTE_USED(pte)) + { + break; + } + if (PAGE_IS_LEAF(pte)) + { + rt_size_t pgsize = 1UL << (ARCH_PAGE_SHIFT + + (ARCH_PAGE_TBL_LEVELS - level) * ARCH_INDEX_WIDTH); + + *level_out = level; + *pgsize_out = pgsize; + return (void *)(GET_PADDR(pte) | ((rt_ubase_t)vaddr & (pgsize - 1))); + } + tbl = (rt_pte_t *)PPN_TO_VPN(GET_PADDR(pte), pvoff); + } + + return ARCH_MAP_FAILED; +} + +/* + * Walk the page table the hardware is actually using (rooted at satp). + * + * With RT_USING_SMP each hart runs its own copy of the top level table, so the + * walk is done with scheduling disabled to stay on the hart whose satp was + * sampled. + */ +static void *_walk_v2p(void *vaddr, int *level_out, rt_size_t *pgsize_out) +{ + void *paddr; + rt_pte_t *root; + + rt_enter_critical(); + root = (rt_pte_t *)PPN_TO_VPN((read_csr(satp) & SATP_PPN_MASK) << PAGE_OFFSET_BIT, PV_OFFSET); + paddr = _walk_table(root, vaddr, level_out, pgsize_out); + rt_exit_critical(); + + return paddr; +} + +/* per-hart copy of the kernel top level page table */ +static rt_pte_t *_kernel_hart_table(int hartid) +{ + return (rt_pte_t *)((rt_ubase_t)rt_kernel_space.page_table + hartid * ARCH_PAGE_SIZE); +} + +/* + * Every hart runs its own copy of the top level table, so a VA must translate + * to the very same PA on all of them (the .percpu section aside, which is + * mapped per hart on purpose and is not probed here). + */ +static int _hart_tables_agree(void *vaddr, void *expect) +{ + for (int hartid = 0; hartid < RT_CPUS_NR; hartid++) + { + int level; + rt_size_t pgsize; + + if (_walk_table(_kernel_hart_table(hartid), vaddr, &level, &pgsize) != expect) + { + return 0; + } + } + return 1; +} + +/* [1] translation mode actually programmed into satp */ +static void _tc_satp_mode(void) +{ + rt_ubase_t satp = read_csr(satp); + rt_ubase_t mode = (satp >> SATP_MODE_OFFSET) & 0xfUL; + + rt_kprintf("[1] satp translation mode\n"); + rt_kprintf(" satp 0x%lx, mode %ld, levels %d, recorded 0x%lx\n", + satp, mode, ARCH_PAGE_TBL_LEVELS, g_mmu_modes_supported); + + CHECK(mode != SATP_MODE_BARE, "MMU is enabled (satp.mode != Bare)"); + CHECK(mode == SATP_MODE, "satp.mode matches the built-in SATP_MODE (%d)", SATP_MODE); + CHECK((g_mmu_modes_supported >> mode) & 1UL, + "the BSP recorded the same active mode in g_mmu_modes_supported"); +} + +/* [2] kernel linear mapping: PA == VA + PV_OFFSET for every kernel section */ +static void _tc_kernel_linear_map(void) +{ + rt_ubase_t pvoff = PV_OFFSET; + volatile int on_stack = 0; + void *heap; + + rt_kprintf("[2] kernel linear mapping (PA = VA + PV_OFFSET)\n"); + rt_kprintf(" PV_OFFSET 0x%lx, KERNEL_VADDR_START 0x%lx\n", + pvoff, (rt_ubase_t)KERNEL_VADDR_START); + + CHECK((rt_ubase_t)(0 - pvoff) == (rt_ubase_t)KERNEL_VADDR_START, + "PV_OFFSET == -KERNEL_VADDR_START"); + + struct + { + const char *name; + void *vaddr; + } samples[] = { + { ".text", (void *)(rt_ubase_t)_tc_kernel_linear_map }, + { ".bss ", (void *)&_pass }, + { "stack", (void *)&on_stack }, + }; + + for (rt_size_t i = 0; i < sizeof(samples) / sizeof(samples[0]); i++) + { + void *va = samples[i].vaddr; + void *pa = rt_kmem_v2p(va); + + CHECK(pa == (void *)((rt_ubase_t)va + pvoff), + "%s VA 0x%lx -> PA 0x%lx", samples[i].name, + (rt_ubase_t)va, (rt_ubase_t)pa); + } + + heap = rt_malloc(64); + if (heap) + { + void *pa = rt_kmem_v2p(heap); + + CHECK(pa == (void *)((rt_ubase_t)heap + pvoff), + "heap VA 0x%lx -> PA 0x%lx", (rt_ubase_t)heap, (rt_ubase_t)pa); + rt_free(heap); + } + else + { + SKIP("heap rt_malloc() failed"); + } +} + +/* [3] hand-written page table walk vs. rt_hw_mmu_v2p() */ +static void _tc_page_table_walk(void) +{ + void *root_pa; + int level; + rt_size_t pgsize; + void *samples[2]; + const char *names[2] = { ".text", "stack" }; + volatile int on_stack = 0; + + rt_kprintf("[3] hardware page table walk\n"); + + root_pa = rt_kmem_v2p(rt_kernel_space.page_table); + rt_kprintf(" kernel page table VA 0x%lx / PA 0x%lx\n", + (rt_ubase_t)rt_kernel_space.page_table, (rt_ubase_t)root_pa); + + samples[0] = (void *)(rt_ubase_t)_tc_page_table_walk; + samples[1] = (void *)&on_stack; + + for (rt_size_t i = 0; i < sizeof(samples) / sizeof(samples[0]); i++) + { + void *walked = _walk_v2p(samples[i], &level, &pgsize); + void *queried = rt_kmem_v2p(samples[i]); + + CHECK(walked != ARCH_MAP_FAILED && walked == queried, + "%s VA 0x%lx: walk PA 0x%lx (leaf at L%d, page %ldKB) == v2p PA 0x%lx", + names[i], (rt_ubase_t)samples[i], (rt_ubase_t)walked, + level, (rt_size_t)(pgsize >> 10), (rt_ubase_t)queried); + CHECK(_hart_tables_agree(samples[i], queried), + "%s VA 0x%lx resolves identically in all %d per-hart tables", + names[i], (rt_ubase_t)samples[i], RT_CPUS_NR); + } +} + +/* [4] page allocator + two cacheable aliases of the same physical page */ +static void _tc_page_alias(void) +{ + void *page; + void *paddr; + void *alias; + + rt_kprintf("[4] page allocation and VA alias coherency\n"); + + page = rt_pages_alloc(0); + if (page == RT_NULL) + { + SKIP("rt_pages_alloc() failed"); + return; + } + + paddr = rt_kmem_v2p(page); + CHECK(paddr != ARCH_MAP_FAILED, + "page VA 0x%lx is mapped, PA 0x%lx", (rt_ubase_t)page, (rt_ubase_t)paddr); + + *(volatile rt_uint64_t *)page = DEMO_MAGIC_A; + + alias = rt_ioremap_cached(paddr, ARCH_PAGE_SIZE); + if (alias == RT_NULL) + { + SKIP("rt_ioremap_cached() failed, alias test not run"); + rt_pages_free(page, 0); + return; + } + + CHECK(alias != page, "alias VA 0x%lx differs from the linear VA", (rt_ubase_t)alias); + CHECK(rt_kmem_v2p(alias) == paddr, "alias VA translates back to the same PA"); + CHECK(*(volatile rt_uint64_t *)alias == DEMO_MAGIC_A, + "value written through the linear VA is visible through the alias"); + + *(volatile rt_uint64_t *)alias = DEMO_MAGIC_B; + CHECK(*(volatile rt_uint64_t *)page == DEMO_MAGIC_B, + "value written through the alias is visible through the linear VA"); + + rt_iounmap(alias); + CHECK(rt_kmem_v2p(alias) == ARCH_MAP_FAILED, "alias VA is gone after rt_iounmap()"); + CHECK(_hart_tables_agree(alias, ARCH_MAP_FAILED), + "alias VA is gone in all %d per-hart tables", RT_CPUS_NR); + + rt_pages_free(page, 0); +} + +/* [5] device mapping through ioremap */ +static void _tc_ioremap_device(void) +{ + void *paddr = (void *)XIAOHUI_UART0_PHY_ADDR; + void *vaddr; + int level; + rt_size_t pgsize; + + rt_kprintf("[5] device mapping (UART0 @ 0x%lx)\n", (rt_ubase_t)paddr); + + vaddr = rt_ioremap(paddr, ARCH_PAGE_SIZE); + if (vaddr == RT_NULL) + { + SKIP("rt_ioremap() failed"); + return; + } + + CHECK(rt_kmem_v2p(vaddr) == paddr, + "VA 0x%lx translates to the requested PA", (rt_ubase_t)vaddr); + CHECK(_walk_v2p(vaddr, &level, &pgsize) == paddr, + "page table walk agrees (leaf at L%d, page %ldKB)", level, (rt_size_t)(pgsize >> 10)); + CHECK(_hart_tables_agree(vaddr, paddr), + "mapping is present in all %d per-hart tables", RT_CPUS_NR); + + rt_iounmap(vaddr); + CHECK(rt_kmem_v2p(vaddr) == ARCH_MAP_FAILED, "VA is unmapped after rt_iounmap()"); + CHECK(_hart_tables_agree(vaddr, ARCH_MAP_FAILED), + "VA is unmapped in all %d per-hart tables", RT_CPUS_NR); +} + +#ifdef RT_USING_DFS +/* [6] rootfs carries the user applications (romfs -> elmfat root) */ +static void _tc_rootfs(void) +{ + static const char *paths[] = { "/rom/bin/hello", "/bin/hello" }; + char magic[4]; + int fd; + + rt_kprintf("[6] RT-Smart rootfs\n"); + + for (rt_size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) + { + struct stat st; + + CHECK(stat(paths[i], &st) == 0 && st.st_size > 0, + "%s exists, %ld bytes", paths[i], (long)st.st_size); + } + + fd = open("/bin/hello", O_RDONLY); + if (fd < 0) + { + SKIP("open(/bin/hello) failed, ELF header not checked"); + return; + } + CHECK(read(fd, magic, sizeof(magic)) == sizeof(magic) && + magic[0] == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F', + "/bin/hello starts with the ELF magic"); + close(fd); +} + +/* [7] user process: private address space, isolated from the kernel one */ +static void _tc_user_process(void) +{ + const char *path = "/bin/hello"; + char *argv[] = { RT_NULL, RT_NULL }; + struct rt_lwp *lwp; + void *entry = RT_NULL; + void *entry_pa = ARCH_MAP_FAILED; + pid_t pid; + int alive; + int i; + + rt_kprintf("[7] RT-Smart user process\n"); + + argv[0] = (char *)path; + pid = exec((char *)path, 0, 1, argv); + CHECK(pid > 0, "exec(%s) returned pid %d", path, (int)pid); + if (pid <= 0) + { + return; + } + + lwp = lwp_from_pid_and_lock(pid); + if (lwp == RT_NULL) + { + SKIP("pid %d already reaped, address space not inspected", (int)pid); + return; + } + + entry = lwp->text_entry; + CHECK(lwp->aspace != RT_NULL && lwp->aspace != &rt_kernel_space, + "process owns a private address space"); + CHECK(lwp->aspace != RT_NULL && lwp->aspace->page_table != rt_kernel_space.page_table, + "process owns a private page table"); + CHECK(rt_hw_mmu_v2p(&rt_kernel_space, entry) == ARCH_MAP_FAILED, + "text entry 0x%lx is NOT visible from the kernel space", (rt_ubase_t)entry); + lwp_from_pid_release_lock(lwp); + + /* + * The text pages are faulted in on demand, so poll the process page table + * until the entry page shows up, then keep polling until the process is + * gone (it prints on its own while running). + */ + for (i = 0, alive = 1; i < 200 && alive; i++) + { + rt_thread_mdelay(10); + + lwp = lwp_from_pid_and_lock(pid); + if (lwp == RT_NULL) + { + alive = 0; + break; + } + if (entry_pa == ARCH_MAP_FAILED) + { + entry_pa = rt_hw_mmu_v2p(lwp->aspace, entry); + } + lwp_from_pid_release_lock(lwp); + } + + if (entry_pa == ARCH_MAP_FAILED) + { + SKIP("entry page was never observed mapped (process too short-lived)"); + } + else + { + CHECK(entry_pa != ARCH_MAP_FAILED, "text entry 0x%lx was demand-mapped to PA 0x%lx", + (rt_ubase_t)entry, (rt_ubase_t)entry_pa); + } + CHECK(!alive, "process exited and was reaped within %d ms", (i + 1) * 10); +} +#endif /* RT_USING_DFS */ + +void mmu_example(void) +{ + _pass = 0; + _fail = 0; + _skip = 0; + + rt_kprintf("mmu demo start!\n"); + + _tc_satp_mode(); + _tc_kernel_linear_map(); + _tc_page_table_walk(); + _tc_page_alias(); + _tc_ioremap_device(); +#ifdef RT_USING_DFS + _tc_rootfs(); + _tc_user_process(); +#else + rt_kprintf("[6] RT-Smart rootfs / user process: skipped, RT_USING_DFS is off\n"); +#endif /* RT_USING_DFS */ + + rt_kprintf("mmu demo done: %d passed, %d failed, %d skipped\n", _pass, _fail, _skip); +} + +static int mmu_demo(int argc, char **argv) +{ + mmu_example(); + return _fail == 0 ? 0 : -RT_ERROR; +} +MSH_CMD_EXPORT(mmu_demo, MMU and RT - Smart runtime checks); + +#endif /* RT_USING_SMART && ARCH_MM_MMU */ diff --git a/bsp/xuantie/xiaohui/c908/applications/mnt.c b/bsp/xuantie/xiaohui/c908/applications/mnt.c new file mode 100644 index 000000000000..e993e5ff195b --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/applications/mnt.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef RT_USING_DFS +#include +#include +#include +#include +#include + +static int _copy_file(const char *src, const char *dst) +{ + static char buf[2048]; + int rfd, wfd, len, ret = 0; + + rfd = open(src, O_RDONLY); + if (rfd < 0) + { + return -1; + } + wfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (wfd < 0) + { + close(rfd); + return -1; + } + while ((len = read(rfd, buf, sizeof(buf))) > 0) + { + if (write(wfd, buf, len) != len) + { + ret = -1; + break; + } + } + close(rfd); + close(wfd); + return ret; +} + +int mnt_init(void) +{ + /* FAT on ramdisk as root: the ELF loader needs mmap support */ + if (dfs_mkfs("elm", "ramdisk0") != 0) + { + rt_kprintf("mkfs elm on ramdisk0 failed!\n"); + return -1; + } + if (dfs_mount("ramdisk0", "/", "elm", 0, 0) != 0) + { + rt_kprintf("elmfat mounted on / failed!\n"); + return -1; + } + + mkdir("/rom", 0777); + mkdir("/bin", 0777); + mkdir("/etc", 0777); + mkdir("/dev", 0777); + mkdir("/dev/shm", 0777); + + /* built-in romfs image holds the user applications */ + if (dfs_mount(RT_NULL, "/rom", "rom", 0, &romfs_root) != 0) + { + rt_kprintf("romfs mounted on /rom failed!\n"); + return -1; + } + + /* copy user applications to the writable root so they can be mmap-ed */ + if (_copy_file("/rom/bin/hello", "/bin/hello") != 0) + { + rt_kprintf("no user application in the built-in romfs image\n"); + } + + rt_kprintf("file system initialization done!\n"); + + return 0; +} +INIT_ENV_EXPORT(mnt_init); + +#endif /* RT_USING_DFS */ diff --git a/bsp/xuantie/xiaohui/c908/applications/romfs.c b/bsp/xuantie/xiaohui/c908/applications/romfs.c new file mode 100644 index 000000000000..b5a23ef4e0c5 --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/applications/romfs.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static const struct romfs_dirent _romfs_root[] = { + { ROMFS_DIRENT_DIR, "bin", RT_NULL, 0 } +}; + +const struct romfs_dirent romfs_root = { + ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, + sizeof(_romfs_root) / sizeof(_romfs_root[0]) +}; diff --git a/bsp/xuantie/xiaohui/c908/board/SConscript b/bsp/xuantie/xiaohui/c908/board/SConscript index 9d71865e962a..471e80f4e573 100644 --- a/bsp/xuantie/xiaohui/c908/board/SConscript +++ b/bsp/xuantie/xiaohui/c908/board/SConscript @@ -1,52 +1,11 @@ -import os -import re -import rtconfig -from building import * - -Import('SDK_LIB') - -cwd = GetCurrentDir() - -# add general drivers -src = ['board.c'] +# RT-Thread building script for component -path = [cwd] - -CPPDEFINES = [ - 'CONFIG_KERNEL_RTTHREAD=1 ', - '__RT_KERNEL_SOURCE__=1 ', - 'CONFIG_CSI_V2=1 ', - 'CONFIG_CSI="csi2" ', - 'CONFIG_XIP=1 ', - 'CONFIG_ARCH_MAINSTACK=8192 ', - 'CONFIG_ARCH_INTERRUPTSTACK=8192 ', - 'CONFIG_BOARD_XIAOHUI_EVB=1 ', - 'CLI_CONFIG_STACK_SIZE=8192 ', - 'CONFIG_PLIC_BASE=134217728 ', - 'CONFIG_VIC_TSPDR=201326592 ', - 'CONFIG_CLINT_BASE=201326592 ', - 'CONFIG_INTC_PLIC=1 ', - 'CONFIG_INIT_TASK_STACK_SIZE=8192 ', - 'CONFIG_APP_TASK_STACK_SIZE=8192 ', - 'CONFIG_DEBUG=1 ', - 'CONFIG_CPU_XUANTIE_C908V=1 ' -] - -CPPDEFINES += ['CONFIG_SYSTICK_HZ=RT_TICK_PER_SECOND '] +from building import * -def read_rtconfig_macro(macro): - try: - with open('rtconfig.h', 'r') as f: - for line in f: - if re.search(r'#define\s+' + macro + r'\b', line): - return True - except FileNotFoundError: - pass - return False +cwd = GetCurrentDir() +src = ['board.c', 'drv_uart.c', 'drv_ramdisk.c'] +CPPPATH = [cwd] -if read_rtconfig_macro('RT_USING_SMP'): - CPPDEFINES += ['CONFIG_SMP=1 '] -CPPDEFINES += ['CONFIG_NR_CPUS=RT_CPUS_NR '] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) -group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group') diff --git a/bsp/xuantie/xiaohui/c908/board/board.c b/bsp/xuantie/xiaohui/c908/board/board.c index 409508a2adf9..db546f0e431e 100644 --- a/bsp/xuantie/xiaohui/c908/board/board.c +++ b/bsp/xuantie/xiaohui/c908/board/board.c @@ -1,144 +1,237 @@ /* - * Copyright (c) 2006-2025, RT-Thread Development Team + * Copyright (c) 2006-2026, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2025-04-23 Wangshun first version + * 2026-08-13 chenguohao add xiaohui C908 rt-smart support */ -#include #include #include -#include +#include + +#include "board.h" +#include "tick.h" +#include "drv_uart.h" +#include +#include + +#ifdef RT_USING_SMART +#include +#include +#include +#include +#include +#include +#endif -extern unsigned long __heap_start; -extern unsigned long __heap_end; +#ifdef RT_USING_SMART -/** - * This function will initialize your board. - */ -void rt_hw_board_init() -{ - rt_hw_interrupt_init(); +rt_region_t init_page_region = { (rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END }; -#ifdef RT_USING_HEAP - rt_system_heap_init((void *)&__heap_start, (void *)&__heap_end); -#endif +extern size_t MMUTable[]; -#ifdef BSP_USING_UART - rt_hw_usart_init(); -#endif +/* map the whole rt-smart managed physical range */ +struct mem_desc platform_mem_desc[] = { + { KERNEL_VADDR_START + MEM_PHYS_BASE, + KERNEL_VADDR_START + MEM_PHYS_BASE + MEM_RTSMART_SIZE - 1, + (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM }, +}; -#ifdef RT_USING_CONSOLE - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); -#endif +#define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0])) -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); +#endif /* RT_USING_SMART */ + +#ifndef ARCH_REMAP_KERNEL +#define IOREMAP_VEND USER_VADDR_START +#else +#define IOREMAP_VEND 0ul #endif + +#define IOREMAP_SIZE (1ul << 30) + +/* + * satp translation mode the kernel is actually running with, as a bitmask + * indexed by the satp MODE encoding + */ +unsigned long g_mmu_modes_supported = 0; + +static void _record_satp_mode(void) +{ + rt_ubase_t satp; + + __asm__ volatile("csrr %0, satp" : "=r"(satp)); + g_mmu_modes_supported = 1UL << ((satp >> 60) & 0xF); } #ifdef RT_USING_SMP -#include - -extern void Reset_Handler(void); - -static struct c9xx_regs_struct { - uint64_t pmpaddr0; - uint64_t pmpaddr1; - uint64_t pmpaddr2; - uint64_t pmpaddr3; - uint64_t pmpaddr4; - uint64_t pmpaddr5; - uint64_t pmpaddr6; - uint64_t pmpaddr7; - uint64_t pmpcfg0; - uint64_t mcor; - uint64_t mhcr; - uint64_t mccr2; - uint64_t mhint; - uint64_t msmpr; - uint64_t mie; - uint64_t mxstatus; - uint64_t mtvec; - uint64_t plic_base_addr; - uint64_t clint_base_addr; -} c9xx_regs; - -#define C9xx_PLIC_CLINT_OFFSET 0x04000000 /* 64M */ -#define C9xx_PLIC_DELEG_OFFSET 0x001ffffc -#define C9xx_PLIC_DELEG_ENABLE 0x1 - -#define XIAOHUI_SRESET_BASE 0x18030000 -#define XIAOHUI_SRESET_ADDR_OFFSET 0x10 -#define PRIMARY_STARTUP_CORE_ID 0 - -static void c9xx_csr_copy(void) +/* IPI handler on the remote hart: flush local TLB and instruction stream */ +static void _tlb_flush_ipi(int vector, void *param) +{ + __asm__ volatile("sfence.vma" ::: "memory"); + __asm__ volatile("fence.i" ::: "memory"); +} +#endif /* RT_USING_SMP */ + +rt_uint64_t rt_hw_get_clock_timer_freq(void) +{ + /* xiaohui coretim runs at 25MHz */ + return 25000000ULL; +} + +void init_bss(void) { - if (PRIMARY_STARTUP_CORE_ID == csi_get_cpu_id()) { - /* Load from boot core */ - c9xx_regs.pmpaddr0 = rv_csr_read(CSR_PMPADDR0); - c9xx_regs.pmpaddr1 = rv_csr_read(CSR_PMPADDR1); - c9xx_regs.pmpaddr2 = rv_csr_read(CSR_PMPADDR2); - c9xx_regs.pmpaddr3 = rv_csr_read(CSR_PMPADDR3); - c9xx_regs.pmpaddr4 = rv_csr_read(CSR_PMPADDR4); - c9xx_regs.pmpaddr5 = rv_csr_read(CSR_PMPADDR5); - c9xx_regs.pmpaddr6 = rv_csr_read(CSR_PMPADDR6); - c9xx_regs.pmpaddr7 = rv_csr_read(CSR_PMPADDR7); - c9xx_regs.pmpcfg0 = rv_csr_read(CSR_PMPCFG0); - c9xx_regs.mcor = rv_csr_read(CSR_MCOR); - c9xx_regs.msmpr = rv_csr_read(CSR_MSMPR); - c9xx_regs.mhcr = rv_csr_read(CSR_MHCR); - c9xx_regs.mccr2 = rv_csr_read(CSR_MCCR2); - c9xx_regs.mhint = rv_csr_read(CSR_MHINT); - c9xx_regs.mtvec = rv_csr_read(CSR_MTVEC); - c9xx_regs.mie = rv_csr_read(CSR_MIE); - c9xx_regs.mxstatus = rv_csr_read(CSR_MXSTATUS); - - c9xx_regs.plic_base_addr = rv_csr_read(CSR_MAPBADDR); - c9xx_regs.clint_base_addr = c9xx_regs.plic_base_addr + C9xx_PLIC_CLINT_OFFSET; - } else { - /* Store to other core */ - // rv_csr_write(CSR_PMPADDR0, c9xx_regs.pmpaddr0); - // rv_csr_write(CSR_PMPADDR1, c9xx_regs.pmpaddr1); - // rv_csr_write(CSR_PMPADDR2, c9xx_regs.pmpaddr2); - // rv_csr_write(CSR_PMPADDR3, c9xx_regs.pmpaddr3); - // rv_csr_write(CSR_PMPADDR4, c9xx_regs.pmpaddr4); - // rv_csr_write(CSR_PMPADDR5, c9xx_regs.pmpaddr5); - // rv_csr_write(CSR_PMPADDR6, c9xx_regs.pmpaddr6); - // rv_csr_write(CSR_PMPADDR7, c9xx_regs.pmpaddr7); - // rv_csr_write(CSR_PMPCFG0, c9xx_regs.pmpcfg0); - rv_csr_write(CSR_MCOR, c9xx_regs.mcor); - rv_csr_write(CSR_MSMPR, c9xx_regs.msmpr); - rv_csr_write(CSR_MHCR, c9xx_regs.mhcr); - rv_csr_write(CSR_MHINT, c9xx_regs.mhint); - // rv_csr_write(CSR_MTVEC, c9xx_regs.mtvec); - // rv_csr_write(CSR_MIE, c9xx_regs.mie); - rv_csr_write(CSR_MXSTATUS, c9xx_regs.mxstatus); + unsigned int *dst; + + dst = &__bss_start; + while ((rt_ubase_t)dst < (rt_ubase_t)&__bss_end) + { + *dst++ = 0; } } -void riscv_soc_start_cpu(int cpu_num) +/* lock-free UART output for the assert path: rt_kprintf may block on the + * console lock, which can be part of the failure being reported */ +static volatile rt_uint32_t *raw_uart = RT_NULL; + +static void _raw_putc(char c) { - if (cpu_num < 1) { + if (raw_uart == RT_NULL) + { return; } + while ((raw_uart[5] & 0x20) == 0); + raw_uart[0] = (rt_uint32_t)(rt_uint8_t)c; +} + +static void _raw_puts(const char *s) +{ + while (*s) + { + if (*s == '\n') + { + _raw_putc('\r'); + } + _raw_putc(*s++); + } +} + +static void _raw_putdec(rt_size_t v) +{ + char buf[24]; + int i = 0; + + do + { + buf[i++] = (char)('0' + v % 10); + v /= 10; + } while (v && i < (int)sizeof(buf)); + while (i > 0) + { + _raw_putc(buf[--i]); + } +} + +static void __rt_assert_handler(const char *ex_string, const char *func, rt_size_t line) +{ + _raw_puts("("); + _raw_puts(ex_string); + _raw_puts(") assertion failed at function:"); + _raw_puts(func); + _raw_puts(", line number:"); + _raw_putdec(line); + _raw_puts(" (cpu"); + _raw_putdec((rt_size_t)rt_hw_cpu_id()); + _raw_puts(")\n"); + asm volatile("ebreak" ::: "memory"); +} + +// static void __rt_assert_handler(const char *ex_string, const char *func, rt_size_t line) +// { +// rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line); +// asm volatile("ebreak":::"memory"); +// } + +/* BSP C entry, called from common64 startup_gcc.S */ +void primary_cpu_entry(void) +{ + /* disable global interrupt */ + rt_hw_interrupt_disable(); + rt_assert_set_hook(__rt_assert_handler); + entry(); +} + +void rt_hw_board_init(void) +{ + sbi_init(); + +#ifdef RT_USING_SMART + /* init data structure */ + rt_hw_mmu_map_init(&rt_kernel_space, (void *)(IOREMAP_VEND - IOREMAP_SIZE), IOREMAP_SIZE, (rt_size_t *)MMUTable, PV_OFFSET); + + /* init page allocator */ + rt_page_init(init_page_region); + + /* setup region, and enable MMU */ + rt_hw_mmu_setup(&rt_kernel_space, platform_mem_desc, NUM_MEM_DESC); +#endif + +#ifdef RT_USING_HEAP + /* initialize memory system */ + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); +#endif - c9xx_csr_copy(); + /* initialize interrupt controller */ + rt_hw_interrupt_init(); + +#ifdef RT_USING_SMP + /* boot hart IPI init (maps the CLINT SSIP page); secondary harts call + * rt_hw_ipi_init() themselves in secondary_cpu_entry() */ + rt_hw_ipi_init(); + rt_hw_ipi_handler_install(RT_MAX_IPI - 1, _tlb_flush_ipi); +#endif + +#ifdef RT_USING_SMART + /* private UART mapping for the lock-free assert output path */ + raw_uart = (volatile rt_uint32_t *)rt_ioremap((void *)XIAOHUI_UART0_PHY_ADDR, 0x1000); + + /* record the satp mode the kernel ended up running with */ + _record_satp_mode(); +#endif + + /* uart driver */ + rt_hw_uart_init(); + + /* tick timer */ + rt_hw_tick_init(); - *(unsigned long *)((unsigned long)XIAOHUI_SRESET_BASE + XIAOHUI_SRESET_ADDR_OFFSET + ((cpu_num - 1) << 3)) = (unsigned long)Reset_Handler; -#if __riscv_xtheadsync - __ASM("sync"); +#ifdef RT_USING_CONSOLE + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif /* RT_USING_CONSOLE */ + +#ifdef RT_USING_SMART + /* report the active MMU translation mode */ + { + rt_ubase_t satp; + + __asm__ volatile("csrr %0, satp" : "=r"(satp)); + rt_kprintf("MMU: active Sv%d (boot via OpenSBI)\n", + ((satp >> 60) & 0xF) == 8 ? 39 : ((satp >> 60) & 0xF) == 9 ? 48 + : ((satp >> 60) & 0xF) == 10 ? 57 + : 0); + } #endif - /* Release secondary cpus, Determined by the xiaohui FPGA platform */ - *(uint32_t *)(XIAOHUI_SRESET_BASE) = 0x7f; - // uint32_t mrmr = *(uint32_t *)(XIAOHUI_SRESET_BASE); - // *(uint32_t *)(XIAOHUI_SRESET_BASE) = mrmr | (0x1 << (cpu_num - 1)); -#if __riscv_xtheadsync - __ASM("sync"); +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); #endif } -#endif /* RT_USING_SMP */ + +void rt_hw_cpu_reset(void) +{ + while (1); +} +MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); diff --git a/bsp/xuantie/xiaohui/c908/board/board.h b/bsp/xuantie/xiaohui/c908/board/board.h index 9f95ecd3e58e..1ce896f1ea05 100644 --- a/bsp/xuantie/xiaohui/c908/board/board.h +++ b/bsp/xuantie/xiaohui/c908/board/board.h @@ -23,7 +23,6 @@ #ifndef __BOARD_H__ #define __BOARD_H__ -#include #ifdef __cplusplus extern "C" { @@ -364,6 +363,36 @@ extern "C" { /* other board specific defines */ //#define CUSTOM_BOARD_xxx +/* ---- xiaohui C908 RT-Thread Smart ---- */ + +#include +#include "mem_layout.h" + +extern unsigned int __bss_start; +extern unsigned int __bss_end; +extern unsigned int __sram_end; +extern unsigned int _end; + +/* heap starts after the whole kernel image */ +#define RT_HW_HEAP_BEGIN ((void *)&_end) +#define RT_HW_HEAP_END ((void *)(((rt_size_t)RT_HW_HEAP_BEGIN) + MEM_HEAP_SIZE)) + +#define RT_HW_PAGE_START ((void *)((rt_size_t)RT_HW_HEAP_END + sizeof(rt_size_t))) +#define RT_HW_PAGE_END ((void *)&__sram_end) + +/* xiaohui peripherals */ +#define XIAOHUI_UART0_PHY_ADDR 0x1900D000UL +#define XIAOHUI_UART0_IRQ 20 +#define XIAOHUI_CLINT_PHY_ADDR 0x0C000000UL +#define XIAOHUI_STIMECMP_OFF 0xD000UL + +/* satp translation modes supported by hardware, probed by the M-mode + * boot shim */ +extern unsigned long g_mmu_modes_supported; + +void rt_hw_board_init(void); + + /****************************************************************************/ /** * @brief init the board for default: pin mux, etc. diff --git a/bsp/xuantie/xiaohui/c908/board/drv_ramdisk.c b/bsp/xuantie/xiaohui/c908/board/drv_ramdisk.c new file mode 100644 index 000000000000..25f6ac7bd08c --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/board/drv_ramdisk.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define DBG_TAG "drv.ramdisk" +#define DBG_LVL DBG_INFO +#include + +#define RAMDISK_SECTOR_SIZE 512 +#define RAMDISK_SIZE (8 * 1024 * 1024) +#define RAMDISK_SECTOR_NR (RAMDISK_SIZE / RAMDISK_SECTOR_SIZE) + +static struct rt_device _ramdisk_dev; +static rt_uint8_t *_ramdisk_data; + +static rt_ssize_t _ramdisk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + if (pos + size > RAMDISK_SECTOR_NR) + { + return 0; + } + rt_memcpy(buffer, _ramdisk_data + pos * RAMDISK_SECTOR_SIZE, size * RAMDISK_SECTOR_SIZE); + return size; +} + +static rt_ssize_t _ramdisk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + if (pos + size > RAMDISK_SECTOR_NR) + { + return 0; + } + rt_memcpy(_ramdisk_data + pos * RAMDISK_SECTOR_SIZE, buffer, size * RAMDISK_SECTOR_SIZE); + return size; +} + +static rt_err_t _ramdisk_control(rt_device_t dev, int cmd, void *args) +{ + if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) + { + struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args; + + if (geometry == RT_NULL) + { + return -RT_ERROR; + } + geometry->bytes_per_sector = RAMDISK_SECTOR_SIZE; + geometry->block_size = RAMDISK_SECTOR_SIZE; + geometry->sector_count = RAMDISK_SECTOR_NR; + } + return RT_EOK; +} + +#ifdef RT_USING_DEVICE_OPS +static const struct rt_device_ops ramdisk_ops = { + RT_NULL, + RT_NULL, + RT_NULL, + _ramdisk_read, + _ramdisk_write, + _ramdisk_control, +}; +#endif + +int rt_hw_ramdisk_init(void) +{ + rt_device_t dev = &_ramdisk_dev; + + _ramdisk_data = rt_malloc(RAMDISK_SIZE); + if (_ramdisk_data == RT_NULL) + { + LOG_E("no memory for the ramdisk"); + return -RT_ENOMEM; + } + rt_memset(_ramdisk_data, 0, RAMDISK_SIZE); + + dev->type = RT_Device_Class_Block; +#ifdef RT_USING_DEVICE_OPS + dev->ops = &ramdisk_ops; +#else + dev->read = _ramdisk_read; + dev->write = _ramdisk_write; + dev->control = _ramdisk_control; +#endif + + return rt_device_register(dev, "ramdisk0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); +} +INIT_DEVICE_EXPORT(rt_hw_ramdisk_init); diff --git a/bsp/xuantie/xiaohui/c908/board/drv_uart.c b/bsp/xuantie/xiaohui/c908/board/drv_uart.c new file mode 100644 index 000000000000..3495af50e72f --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/board/drv_uart.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "board.h" +#include "drv_uart.h" + +#ifdef RT_USING_SMART +#include +#endif + +struct device_uart +{ + rt_ubase_t hw_base; + rt_uint32_t irqno; +}; + +static void *uart0_base = (void *)XIAOHUI_UART0_PHY_ADDR; +static struct rt_serial_device serial0; +static struct device_uart uart0; + +/* 32-bit stride register access */ +rt_inline rt_uint32_t uart_read(int reg) +{ + return *(volatile rt_uint32_t *)((rt_ubase_t)uart0_base + ((rt_ubase_t)reg << 2)); +} + +rt_inline void uart_write(int reg, rt_uint32_t val) +{ + *(volatile rt_uint32_t *)((rt_ubase_t)uart0_base + ((rt_ubase_t)reg << 2)) = val; +} + +static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + /* the boot firmware/QEMU model already configured the line; enable FIFO */ + uart_write(UART_FCR, UART_FCR_FIFO_ENABLE | UART_FCR_FIFO_CLEAR); + return RT_EOK; +} + +static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + if ((size_t)arg == RT_DEVICE_FLAG_INT_RX) + { + uart_write(UART_IER, uart_read(UART_IER) & ~UART_IER_RX_ENABLE); + } + break; + + case RT_DEVICE_CTRL_SET_INT: + if ((size_t)arg == RT_DEVICE_FLAG_INT_RX) + { + uart_write(UART_IER, uart_read(UART_IER) | UART_IER_RX_ENABLE); + } + break; + } + + return RT_EOK; +} + +static int _uart_putc(struct rt_serial_device *serial, char c) +{ + while ((uart_read(UART_LSR) & UART_LSR_TX_IDLE) == 0); + uart_write(UART_THR, (rt_uint32_t)(rt_uint8_t)c); + + return 1; +} + +static int _uart_getc(struct rt_serial_device *serial) +{ + int ch = -1; + + if (uart_read(UART_LSR) & UART_LSR_RX_READY) + { + ch = (int)(uart_read(UART_RHR) & 0xFF); + } + return ch; +} + +static const struct rt_uart_ops _uart_ops = { + _uart_configure, + _uart_control, + _uart_putc, + _uart_getc, + RT_NULL, +}; + +static void _uart_isr(int irqno, void *param) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)param; + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); +} + +/* + * UART Initiation + */ +int rt_hw_uart_init(void) +{ + struct rt_serial_device *serial; + struct device_uart *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_SMART + uart0_base = rt_ioremap((void *)XIAOHUI_UART0_PHY_ADDR, 4096); +#endif + + serial = &serial0; + uart = &uart0; + + serial->ops = &_uart_ops; + serial->config = config; + serial->config.baud_rate = 115200; + uart->hw_base = (rt_ubase_t)uart0_base; + uart->irqno = XIAOHUI_UART0_IRQ; + + rt_hw_serial_register(serial, + RT_CONSOLE_DEVICE_NAME, + RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); + rt_hw_interrupt_install(uart->irqno, _uart_isr, serial, RT_CONSOLE_DEVICE_NAME); + rt_hw_interrupt_umask(uart->irqno); + return 0; +} diff --git a/bsp/xuantie/xiaohui/c908/board/drv_uart.h b/bsp/xuantie/xiaohui/c908/board/drv_uart.h new file mode 100644 index 000000000000..5027deeedf8f --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/board/drv_uart.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +/* DW apb uart: 16550-compatible registers with 32-bit stride */ +#define UART_RHR 0 /* receive holding register (read) */ +#define UART_THR 0 /* transmit holding register (write) */ +#define UART_DLL 0 /* divisor latch low (LCR[7]=1) */ +#define UART_IER 1 /* interrupt enable register */ +#define UART_DLH 1 /* divisor latch high (LCR[7]=1) */ +#define UART_IIR 2 /* interrupt identify register (read) */ +#define UART_FCR 2 /* fifo control register (write) */ +#define UART_LCR 3 /* line control register */ +#define UART_MCR 4 /* modem control register */ +#define UART_LSR 5 /* line status register */ +#define UART_USR 31 /* DW uart status register (0x7c) */ + +#define UART_IER_RX_ENABLE (1 << 0) +#define UART_IER_TX_ENABLE (1 << 1) +#define UART_FCR_FIFO_ENABLE (1 << 0) +#define UART_FCR_FIFO_CLEAR (3 << 1) +#define UART_LCR_EIGHT_BITS (3 << 0) +#define UART_LCR_BAUD_LATCH (1 << 7) +#define UART_LSR_RX_READY (1 << 0) +#define UART_LSR_TX_IDLE (1 << 5) + +int rt_hw_uart_init(void); + +#endif /* __DRV_UART_H__ */ diff --git a/bsp/xuantie/xiaohui/c908/board/mem_layout.h b/bsp/xuantie/xiaohui/c908/board/mem_layout.h new file mode 100644 index 000000000000..32b33355e408 --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/board/mem_layout.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MEM_LAYOUT_H__ +#define __MEM_LAYOUT_H__ + +#include "../rtconfig.h" + +/* + * Physical memory layout (xiaohui: DRAM 4GB @ 0x50000000): + * + * +---------------+ <- MEM_PHYS_BASE + MEM_TOTAL_SIZE (0x150000000) + * | ...... | (unused by kernel, reserved) + * +---------------+ <- MEM_PHYS_BASE + MEM_RTSMART_SIZE + * | guard | MEM_GUARD_SIZE + * +---------------+ <- end of kernel image + heap + page pool + * | page pool | (till RTSMART end, managed by rt_page) + * +---------------+ + * | heap | MEM_HEAP_SIZE (after .bss) + * +---------------+ + * | kernel | linked at KERNEL_VADDR_START + MEM_PHYS_BASE + MEM_OPENSBI_SIZE + * +---------------+ <- MEM_PHYS_BASE + MEM_OPENSBI_SIZE (0x50200000) + * | opensbi | MEM_OPENSBI_SIZE, fw_dynamic.bin is loaded here by QEMU + * +---------------+ <- MEM_PHYS_BASE (0x50000000) + * + */ + +#define MEM_PHYS_BASE 0x50000000 +#define MEM_TOTAL_SIZE 0x100000000 +#define MEM_GUARD_SIZE 0x1000 + +/* + * Region reserved for the OpenSBI firmware at the bottom of DRAM. + */ +#define MEM_OPENSBI_SIZE 0x200000 + +/* memory managed by rt-smart kernel (kernel image + heap + page pool) */ +#ifndef MEM_RTSMART_SIZE +#define MEM_RTSMART_SIZE 0x10000000 +#endif + +/* system heap size, placed right after .bss */ +#ifndef MEM_HEAP_SIZE +#define MEM_HEAP_SIZE 0x2000000 +#endif + +#define MEM_KERNEL_SIZE (MEM_RTSMART_SIZE - MEM_OPENSBI_SIZE - MEM_GUARD_SIZE) + +#endif /* __MEM_LAYOUT_H__ */ diff --git a/bsp/xuantie/xiaohui/c908/link.lds b/bsp/xuantie/xiaohui/c908/link.lds new file mode 100644 index 000000000000..b22df7dfcd9d --- /dev/null +++ b/bsp/xuantie/xiaohui/c908/link.lds @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2017-2024 Alibaba Group Holding Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "board/mem_layout.h" + +OUTPUT_ARCH( "riscv" ) + +MEMORY +{ + KERNEL : ORIGIN = KERNEL_VADDR_START + MEM_PHYS_BASE + MEM_OPENSBI_SIZE, LENGTH = MEM_KERNEL_SIZE +} + +/* __STACKSIZE__ comes from rtconfig.h as a preprocessor macro */ + +ENTRY(_start) +SECTIONS +{ + . = ORIGIN(KERNEL); + + __sram_base = ORIGIN(KERNEL); + __sram_size = LENGTH(KERNEL); + __sram_end = __sram_base + __sram_size; + + __text_start = .; + .start : AT(ADDR(.start) - KERNEL_VADDR_START) + { + KEEP(*(.start)); + } > KERNEL + + . = ALIGN(8); + + .text : AT(ADDR(.text) - KERNEL_VADDR_START) + { + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.srodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(8); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(8); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(8); + + /* section information for initial. */ + . = ALIGN(8); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(8); + + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + . = ALIGN(8); + _etext = .; + } > KERNEL + + .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VADDR_START) + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } > KERNEL + .eh_frame : AT(ADDR(.eh_frame) - KERNEL_VADDR_START) ONLY_IF_RO { KEEP (*(.eh_frame)) } > KERNEL + + . = ALIGN(8); + __text_end = .; + __text_size = __text_end - __text_start; + + .data : AT(ADDR(.data) - KERNEL_VADDR_START) + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + *(.got) + *(.got.plt) + + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + + *(.sdata) + *(.sdata.*) + } > KERNEL + + /* stack for dual core */ + .stack : AT(ADDR(.stack) - KERNEL_VADDR_START) + { + . = ALIGN(64); + __stack_start__ = .; + + . += __STACKSIZE__; + __stack_cpu0 = .; + + . += __STACKSIZE__; + __stack_cpu1 = .; + } > KERNEL + + . = ALIGN(8); + + .osdebug : AT(ADDR(.osdebug) - KERNEL_VADDR_START) + { + _osdebug_start = .; + . += 87K; + _osdebug_end = .; + } > KERNEL + + . = ALIGN(8); + + .sbss : AT(ADDR(.sbss) - KERNEL_VADDR_START) + { + __bss_start = .; + *(.sbss) + *(.sbss.*) + *(.dynsbss) + *(.scommon) + } > KERNEL + + .bss : AT(ADDR(.bss) - KERNEL_VADDR_START) + { + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + __bss_end = .; + } > KERNEL + +#ifdef RT_USING_SMP + .percpu (NOLOAD) : + { + /* 2MB Align for MMU early map */ + . = ALIGN(0x200000); + PROVIDE(__percpu_start = .); + + *(.percpu) + + /* 2MB Align for MMU early map */ + . = ALIGN(0x200000); + + PROVIDE(__percpu_end = .); + + /* Clone the area */ + . = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1); + PROVIDE(__percpu_real_end = .); + } > KERNEL +#endif + + _end = .; + + /* Stabs debugging sections.s */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/xuantie/xiaohui/c908/rtconfig.h b/bsp/xuantie/xiaohui/c908/rtconfig.h index f5b427636b29..744eae8b0ee6 100644 --- a/bsp/xuantie/xiaohui/c908/rtconfig.h +++ b/bsp/xuantie/xiaohui/c908/rtconfig.h @@ -2,6 +2,7 @@ #define RT_CONFIG_H__ #define XUANTIAN_XIAOHUI_C908 +#define __STACKSIZE__ 65536 /* CPU Architecture Features */ @@ -69,21 +70,24 @@ /* end of rt_strnlen options */ /* end of klibc options */ -#define RT_NAME_MAX 12 -#define RT_CPUS_NR 1 +#define RT_NAME_MAX 16 +#define RT_USING_SMART +#define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 1000 +#define RT_TICK_PER_SECOND 1000 #define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_HOOK_USING_FUNC_PTR #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 8192 +#define IDLE_THREAD_STACK_SIZE 16384 #define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 8192 +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 16384 +#define RT_USING_CPU_USAGE_TRACER +#define RT_CPU_USAGE_CALC_INTERVAL_MS 200 /* kservice options */ @@ -100,24 +104,33 @@ #define RT_USING_EVENT #define RT_USING_MAILBOX #define RT_USING_MESSAGEQUEUE +#define RT_USING_SIGNALS /* end of Inter-Thread communication */ /* Memory Management */ +#define RT_USING_MEMPOOL #define RT_USING_SMALL_MEM -#define RT_USING_SMALL_MEM_AS_HEAP +#define RT_USING_SLAB +#define RT_USING_SLAB_AS_HEAP #define RT_USING_HEAP /* end of Memory Management */ #define RT_USING_DEVICE +#define RT_USING_DEVICE_OPS +#define RT_USING_THREADSAFE_PRINTF #define RT_USING_CONSOLE -#define RT_CONSOLEBUF_SIZE 512 +#define RT_CONSOLEBUF_SIZE 512 #define RT_CONSOLE_DEVICE_NAME "uart0" #define RT_USING_CONSOLE_OUTPUT_CTL #define RT_VER_NUM 0x50300 +#define RT_USING_STDC_ATOMIC #define RT_BACKTRACE_LEVEL_MAX_NR 32 /* end of RT-Thread Kernel */ #define ARCH_CPU_64BIT +#define RT_USING_CACHE #define RT_USING_HW_ATOMIC +#define ARCH_MM_MMU +#define KERNEL_VADDR_START 0xffffffc000000000 #define ARCH_RISCV #define ARCH_RISCV_FPU #define ARCH_RISCV_VECTOR @@ -125,19 +138,20 @@ #define ARCH_RISCV_FPU_D #define ARCH_RISCV64 #define ARCH_USING_NEW_CTX_SWITCH +#define ARCH_REMAP_KERNEL /* RT-Thread Components */ #define RT_USING_COMPONENTS_INIT #define RT_USING_USER_MAIN -#define RT_MAIN_THREAD_STACK_SIZE 8192 -#define RT_MAIN_THREAD_PRIORITY 10 +#define RT_MAIN_THREAD_STACK_SIZE 16384 +#define RT_MAIN_THREAD_PRIORITY 10 #define RT_USING_MSH #define RT_USING_FINSH #define FINSH_USING_MSH -#define FINSH_THREAD_NAME "tshell" -#define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 8192 +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 16384 #define FINSH_USING_HISTORY #define FINSH_HISTORY_LINES 5 #define FINSH_USING_SYMTAB @@ -149,15 +163,65 @@ /* DFS: device virtual file system */ +#define RT_USING_DFS +#define DFS_USING_POSIX +#define DFS_USING_WORKDIR +#define DFS_FD_MAX 32 +#define RT_USING_DFS_V2 +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_LFN_UNICODE_0 +#define RT_DFS_ELM_LFN_UNICODE 0 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +#define RT_DFS_ELM_REENTRANT +#define RT_DFS_ELM_MUTEX_TIMEOUT 3000 +/* end of elm-chan's FatFs, Generic FAT Filesystem Module */ +#define RT_USING_DFS_DEVFS +#define RT_USING_DFS_ROMFS +#define RT_USING_DFS_PTYFS +#define RT_USING_DFS_PROCFS +#define RT_USING_DFS_TMPFS +#define RT_USING_DFS_MQUEUE +#define RT_USING_PAGECACHE + +/* page cache config */ + +#define RT_PAGECACHE_COUNT 4096 +#define RT_PAGECACHE_ASPACE_COUNT 1024 +#define RT_PAGECACHE_PRELOAD 4 +#define RT_PAGECACHE_HASH_NR 1024 +#define RT_PAGECACHE_GC_WORK_LEVEL 90 +#define RT_PAGECACHE_GC_STOP_LEVEL 70 +/* end of page cache config */ /* end of DFS: device virtual file system */ /* Device Drivers */ +#define RT_USING_DEV_BUS #define RT_USING_DEVICE_IPC #define RT_UNAMED_PIPE_NUMBER 64 +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 8192 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_SERIAL_BYPASS +#define RT_USING_CLOCK_TIME +#define CLOCK_TIMER_FREQ 0 +#define RT_USING_NULL +#define RT_USING_ZERO +#define RT_USING_RANDOM +#define RT_USING_RTC +#define RT_USING_SOFT_RTC /* end of Device Drivers */ /* C/C++ and POSIX layer */ @@ -168,16 +232,32 @@ #define RT_LIBC_USING_LIGHT_TZ_DST #define RT_LIBC_TZ_DEFAULT_HOUR 8 -#define RT_LIBC_TZ_DEFAULT_MIN 0 -#define RT_LIBC_TZ_DEFAULT_SEC 0 +#define RT_LIBC_TZ_DEFAULT_MIN 0 +#define RT_LIBC_TZ_DEFAULT_SEC 0 /* end of Timezone and Daylight Saving Time */ /* end of ISO-ANSI C layer */ /* POSIX (Portable Operating System Interface) layer */ +#define RT_USING_POSIX_FS +#define RT_USING_POSIX_DEVIO +#define RT_USING_POSIX_STDIO +#define RT_USING_POSIX_POLL +#define RT_USING_POSIX_SELECT +#define RT_USING_POSIX_EVENTFD +#define RT_USING_POSIX_EPOLL +#define RT_USING_POSIX_SIGNALFD +#define RT_SIGNALFD_MAX_NUM 10 +#define RT_USING_POSIX_TIMERFD +#define RT_USING_POSIX_TERMIOS +#define RT_USING_POSIX_DELAY +#define RT_USING_POSIX_CLOCK +#define RT_USING_POSIX_TIMER /* Interprocess Communication (IPC) */ +#define RT_USING_POSIX_PIPE +#define RT_USING_POSIX_PIPE_SIZE 512 /* Socket is in the 'Network' category */ @@ -195,8 +275,35 @@ /* Utilities */ +#define RT_USING_RESOURCE_ID +#define RT_USING_ADT +#define RT_USING_ADT_AVL +#define RT_USING_ADT_BITMAP +#define RT_USING_ADT_HASHMAP +#define RT_USING_ADT_REF /* end of Utilities */ +/* Memory management */ + +#define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000 +#define RT_PAGE_MAX_ORDER 11 + +/* Debugging */ + +/* end of Debugging */ +/* end of Memory management */ +#define RT_USING_LWP +#define LWP_USING_RUNTIME +#define RT_LWP_MAX_NR 30 +#define LWP_TASK_STACK_SIZE 16384 +#define RT_CH_MSG_MAX_NR 1024 +#define LWP_TID_MAX_NR 64 +#define RT_LWP_SHM_MAX_NR 64 +#define RT_USING_LDSO +#define LWP_USING_TERMINAL +#define LWP_PTY_MAX_PARIS_LIMIT 32 +#define RT_USING_VDSO + /* Using USB legacy version */ /* end of Using USB legacy version */ @@ -304,6 +411,10 @@ /* end of Kendryte SDK */ +/* MM32 HAL & SDK Drivers */ + +/* end of MM32 HAL & SDK Drivers */ + /* WCH HAL & SDK Drivers */ /* end of WCH HAL & SDK Drivers */ @@ -335,6 +446,14 @@ /* FT32 HAL & SDK Drivers */ /* end of FT32 HAL & SDK Drivers */ + +/* NOVOSNS Drivers */ + +/* end of NOVOSNS Drivers */ + +/* N32 Drivers */ + +/* end of N32 Drivers */ /* end of HAL & SDK Drivers */ /* sensors drivers */ diff --git a/bsp/xuantie/xiaohui/c908/rtconfig.py b/bsp/xuantie/xiaohui/c908/rtconfig.py index aed5dea9e099..f390a230d3f7 100644 --- a/bsp/xuantie/xiaohui/c908/rtconfig.py +++ b/bsp/xuantie/xiaohui/c908/rtconfig.py @@ -1,21 +1,24 @@ import os import re -ARCH = 'risc-v' -CPU = 'c908' + # toolchains options +ARCH = 'risc-v' +VENDOR = 't-head' +CPU = 'c908' CROSS_TOOL = 'gcc' -#------- toolchains path ------------------------------------------------------- +RTT_ROOT = os.getenv('RTT_ROOT', r'../../../..') + if os.getenv('RTT_CC'): CROSS_TOOL = os.getenv('RTT_CC') if CROSS_TOOL == 'gcc': PLATFORM = 'gcc' - EXEC_PATH = r'D:\RT-ThreadStudio\repo\Extract\ToolChain_Support_Packages\RISC-V\XTGccElfNewlib\V3.0.1\R\bin' + EXEC_PATH = os.getenv('RTT_EXEC_PATH') or os.path.expanduser('~/tools/Xuantie-900-gcc-linux-6.6.0-musl64-x86_64-V3.0.2/bin') else: print('Please make sure your toolchains is GNU GCC!') exit(0) - + if os.getenv('RTT_EXEC_PATH'): EXEC_PATH = os.getenv('RTT_EXEC_PATH') @@ -24,15 +27,13 @@ CORE = 'risc-v' MAP_FILE = 'rtthread.map' -LINK_FILE = '../../libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld' -if os.path.exists('./libraries'): - LINK_FILE = './libraries/xuantie_libraries/chip_riscv_dummy/gcc_flash_xiaohui.ld' +LINK_FILE = 'link.lds.generated' TARGET_NAME = 'rtthread.bin' #------- GCC settings ---------------------------------------------------------- if PLATFORM == 'gcc': # toolchains - PREFIX = 'riscv64-unknown-elf-' + PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-linux-musl-' CC = PREFIX + 'gcc' CXX= PREFIX + 'g++' AS = PREFIX + 'gcc' @@ -42,56 +43,15 @@ SIZE = PREFIX + 'size' OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - - MCPU = ' -mcpu=c908v ' # Modify here based on CPU architecture. - MCPU_DEFINE = ' -DCONFIG_CPU_XUANTIE_C908V=1 ' # Modify here based on CPU architecture. - DEVICE = MCPU + MCPU_DEFINE + ' -Wno-main -mcmodel=medany -MP -MMD ' - - GLOBAL_DEFINES = ( - ' -DCONFIG_KERNEL_RTTHREAD=1 ' - ' -D__RT_KERNEL_SOURCE__=1 ' - ' -DCONFIG_CSI_V2=1 ' - ' -DCONFIG_CSI="csi2" ' - ' -DCONFIG_XIP=1 ' - ' -DCONFIG_ARCH_MAINSTACK=8192 ' - ' -DCONFIG_ARCH_INTERRUPTSTACK=8192 ' - ' -DCONFIG_BOARD_XIAOHUI_EVB=1 ' - ' -DCLI_CONFIG_STACK_SIZE=8192 ' - ' -DCONFIG_PLIC_BASE=134217728 ' - ' -DCONFIG_VIC_TSPDR=201326592 ' - ' -DCONFIG_CLINT_BASE=201326592 ' - ' -DCONFIG_INTC_PLIC=1 ' - ' -DCONFIG_INIT_TASK_STACK_SIZE=8192 ' - ' -DCONFIG_APP_TASK_STACK_SIZE=8192 ' - ' -DCONFIG_DEBUG=1 ' - ) - - GLOBAL_DEFINES += ' -DCONFIG_SYSTICK_HZ=RT_TICK_PER_SECOND ' - ################################################################################ - # check smp macro in rtconfig.h - def read_rtconfig_macro(macro): - try: - with open('rtconfig.h', 'r') as f: - for line in f: - if re.search(r'#define\s+' + macro + r'\b', line): - return True - except FileNotFoundError: - pass - return False - - if read_rtconfig_macro('RT_USING_SMP'): - GLOBAL_DEFINES += ' -DCONFIG_SMP=1 ' - GLOBAL_DEFINES += ' -DCONFIG_NR_CPUS=RT_CPUS_NR ' - ################################################################################ - - CFLAGS = DEVICE + ' -c -Wno-unused-function -g -Wpointer-arith -Wno-undef -Wall -ffunction-sections -fdata-sections -fno-inline-functions \ - -fno-builtin -fno-strict-aliasing -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast' + GLOBAL_DEFINES - - AFLAGS = DEVICE + GLOBAL_DEFINES - - LFLAGS = DEVICE + ' -Wl,-zmax-page-size=1024 -Wl,-Map=' + MAP_FILE + ' -nostartfiles -Wl,--gc-sections ' - LFLAGS += ' -T ' + LINK_FILE - + + DEVICE = ' -mcmodel=medany -march=rv64imafdcv_zicsr_zifencei -mabi=lp64d ' + + GLOBAL_DEFINES = ' -DC908_PLIC_PHY_ADDR=0x08000000UL ' + + CFLAGS = DEVICE + GLOBAL_DEFINES + ' -fno-pie -fno-pic -Wno-cpp -fvar-tracking -ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields ' + AFLAGS = ' -c' + DEVICE + ' -fno-pie -fno-pic -x assembler-with-cpp -D__ASSEMBLY__' + LFLAGS = DEVICE + ' -no-pie -nostartfiles -Wl,--gc-sections,-Map=' + MAP_FILE + ',-cref,-u,Reset_Handler -T ' + LINK_FILE + ' -lsupc++ -lgcc -static' + CPATH = '' LPATH = '' diff --git a/libcpu/risc-v/common64/mmu.c b/libcpu/risc-v/common64/mmu.c index 2dc82320f593..1b25aff79c6a 100644 --- a/libcpu/risc-v/common64/mmu.c +++ b/libcpu/risc-v/common64/mmu.c @@ -8,6 +8,7 @@ * 2021-01-30 lizhirui first version * 2022-12-13 WangXiaoyao Port to new mm * 2023-10-12 Shell Add permission control API + * 2026-08-25 chenguohao Add SV48/SV57 support */ #include @@ -52,7 +53,7 @@ static void *current_mmu_table[RT_CPUS_NR] = { RT_NULL }; #endif /* RT_USING_SMP */ volatile __attribute__((aligned(4 * 1024))) -rt_ubase_t MMUTable[__SIZE(VPN2_BIT) * RT_CPUS_NR]; +rt_ubase_t MMUTable[ARCH_INDEX_SIZE * RT_CPUS_NR]; /** * @brief Switch the current address space to the specified one. @@ -114,16 +115,12 @@ void *rt_hw_mmu_tbl_get() static int _map_one_page(struct rt_aspace *aspace, void *va, void *pa, size_t attr) { - rt_ubase_t l1_off, l2_off, l3_off; - rt_ubase_t *mmu_l1, *mmu_l2, *mmu_l3; + rt_ubase_t *table, *next_table; + rt_ubase_t off, leaf_off; int nr_cpus = RT_CPUS_NR; - l1_off = GET_L1((size_t)va); - l2_off = GET_L2((size_t)va); - l3_off = GET_L3((size_t)va); - #if defined(RT_USING_SMP) - /* For user address spaces, all harts share the same L2/L3 page tables. + /* For user address spaces, all harts share the same L2/L3/L4 page tables. * Only build the page table tree for hart 0, then sync L1 to other harts. */ if (aspace != &rt_kernel_space) { @@ -131,71 +128,58 @@ static int _map_one_page(struct rt_aspace *aspace, void *va, void *pa, } #endif - /* Create a separate page table for each hart to facilitate access to the .percpu section. */ for (int hartid = 0; hartid < nr_cpus; hartid++) { - mmu_l1 = (rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(hartid * ARCH_PAGE_SIZE)) + l1_off; + table = (rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(hartid * ARCH_PAGE_SIZE)); - if (PTE_USED(*mmu_l1)) - { - mmu_l2 = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*mmu_l1), PV_OFFSET); - } - else + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS; level++) { - mmu_l2 = (rt_ubase_t *)rt_pages_alloc(0); + off = GET_LVL_INDEX((rt_ubase_t)va, level); - if (mmu_l2) + if (PTE_USED(*(table + off))) { - rt_memset(mmu_l2, 0, PAGE_SIZE); - rt_hw_cpu_dcache_clean(mmu_l2, PAGE_SIZE); - *mmu_l1 = COMBINEPTE((rt_ubase_t)VPN_TO_PPN(mmu_l2, PV_OFFSET), - PAGE_DEFAULT_ATTR_NEXT); - rt_hw_cpu_dcache_clean(mmu_l1, sizeof(*mmu_l1)); + RT_ASSERT(!PAGE_IS_LEAF(*(table + off))); + table = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*(table + off)), PV_OFFSET); } else { - return -1; - } - } + next_table = (rt_ubase_t *)rt_pages_alloc(0); - if (PTE_USED(*(mmu_l2 + l2_off))) - { - RT_ASSERT(!PAGE_IS_LEAF(*(mmu_l2 + l2_off))); - mmu_l3 = - (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*(mmu_l2 + l2_off)), PV_OFFSET); - } - else - { - mmu_l3 = (rt_ubase_t *)rt_pages_alloc(0); - - if (mmu_l3) - { - rt_memset(mmu_l3, 0, PAGE_SIZE); - rt_hw_cpu_dcache_clean(mmu_l3, PAGE_SIZE); - *(mmu_l2 + l2_off) = - COMBINEPTE((rt_ubase_t)VPN_TO_PPN(mmu_l3, PV_OFFSET), - PAGE_DEFAULT_ATTR_NEXT); - rt_hw_cpu_dcache_clean(mmu_l2, sizeof(*mmu_l2)); - /* declares a reference to parent page table */ - rt_page_ref_inc((void *)mmu_l2, 0); - } - else - { - return -1; + if (next_table) + { + rt_memset(next_table, 0, PAGE_SIZE); + rt_hw_cpu_dcache_clean(next_table, PAGE_SIZE); + *(table + off) = COMBINEPTE((rt_ubase_t)VPN_TO_PPN(next_table, PV_OFFSET), + PAGE_DEFAULT_ATTR_NEXT); + rt_hw_cpu_dcache_clean(table + off, sizeof(*(table + off))); + /* declares a reference to parent page table */ + if (level > 1) + { + rt_page_ref_inc((void *)table, 0); + } + table = next_table; + } + else + { + return -1; + } } } - RT_ASSERT(!PTE_USED(*(mmu_l3 + l3_off))); - /* declares a reference to parent page table */ - rt_page_ref_inc((void *)mmu_l3, 0); - *(mmu_l3 + l3_off) = COMBINEPTE((rt_ubase_t)pa, attr); - rt_hw_cpu_dcache_clean(mmu_l3 + l3_off, sizeof(*(mmu_l3 + l3_off))); + /* Write the leaf PTE at the last level */ + leaf_off = GET_LVL_INDEX((rt_ubase_t)va, ARCH_PAGE_TBL_LEVELS); + RT_ASSERT(!PTE_USED(*(table + leaf_off))); + /* declares a reference to leaf page table */ + rt_page_ref_inc((void *)table, 0); + *(table + leaf_off) = COMBINEPTE((rt_ubase_t)pa, attr); + rt_hw_cpu_dcache_clean(table + leaf_off, sizeof(*(table + leaf_off))); } #if defined(RT_USING_SMP) /* For user address spaces, sync L1 entry from hart 0 to all other harts */ if (aspace != &rt_kernel_space) { + rt_ubase_t l1_off = GET_LVL_INDEX((rt_ubase_t)va, 1); rt_ubase_t *mmu_l1_0 = (rt_ubase_t *)aspace->page_table + l1_off; for (int h = 1; h < RT_CPUS_NR; h++) { @@ -217,10 +201,10 @@ static int _map_percpu_area(rt_ubase_t *table, void *va, void *pa, int cpu_id) unsigned long page; rt_ubase_t off, level_shift; - level_shift = PPN2_SHIFT; + level_shift = ARCH_TOP_LEVEL_SHIFT; // map pages - 4KB - for (int level = 0; level < 2; ++level) + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS; ++level) { off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; if (table[off] & PTE_V) @@ -387,16 +371,18 @@ unsigned long get_free_page(void) // Perform early mapping for the .percpu section static int rt_hw_mmu_map_percpu_early(rt_ubase_t *tbl, rt_ubase_t va, rt_ubase_t pa) { - unsigned long page; rt_ubase_t off, level_shift; - level_shift = PPN2_SHIFT; + level_shift = ARCH_TOP_LEVEL_SHIFT; // page size 2MB - off = (va >> level_shift) & VPN_MASK; - // Step into the next level page table - tbl = (rt_ubase_t *)((tbl[off] >> PTE_BITS) << ARCH_PAGE_SHIFT); - level_shift -= VPN_BITS; + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS - 1; ++level) + { + off = (va >> level_shift) & VPN_MASK; + // Step into the next level page table + tbl = (rt_ubase_t *)((tbl[off] >> PTE_BITS) << ARCH_PAGE_SHIFT); + level_shift -= VPN_BITS; + } off = (va >> level_shift) & VPN_MASK; tbl[off] = ((pa >> ARCH_PAGE_SHIFT) << PTE_BITS) | MMU_MAP_K_RWCB; @@ -412,16 +398,16 @@ static int rt_hw_mmu_map_early(rt_ubase_t *tbl, rt_ubase_t va, rt_ubase_t pa, unsigned long page, *table; rt_ubase_t off, level_shift; - if ((va & (L2_PAGE_SIZE - 1)) || (pa & (L2_PAGE_SIZE - 1))) + if ((va & (EARLY_MAP_PAGE_SIZE_2M - 1)) || (pa & (EARLY_MAP_PAGE_SIZE_2M - 1))) { return MMU_MAP_ERROR_VANOTALIGN; } table = tbl; - level_shift = PPN2_SHIFT; + level_shift = ARCH_TOP_LEVEL_SHIFT; // page size 2MB - for (int level = 0; level < 1; ++level) + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS - 1; ++level) { off = (va >> level_shift) & VPN_MASK; @@ -485,22 +471,27 @@ static void _unmap_pte(rt_ubase_t *pentry, rt_ubase_t *lvl_entry[], int level) } } -/* Unmaps a virtual address range (1GB/2MB/4KB according to actual page level) from the page table. */ -static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr) +/* Unmaps a virtual address range (1GB/2MB/4KB according to actual page level) + * from one per-hart copy of the top level page table. */ +static size_t _unmap_area_one(rt_ubase_t *top_table, void *v_addr) { rt_ubase_t loop_va = __UMASKVALUE((rt_ubase_t)v_addr, PAGE_OFFSET_MASK); size_t unmapped = 0; int i = 0; - rt_ubase_t lvl_off[3]; - rt_ubase_t *lvl_entry[3]; - lvl_off[0] = (rt_ubase_t)GET_L1(loop_va); - lvl_off[1] = (rt_ubase_t)GET_L2(loop_va); - lvl_off[2] = (rt_ubase_t)GET_L3(loop_va); - unmapped = 1 << (ARCH_PAGE_SHIFT + ARCH_INDEX_WIDTH * 2ul); + rt_ubase_t lvl_off[ARCH_PAGE_TBL_LEVELS]; + rt_ubase_t *lvl_entry[ARCH_PAGE_TBL_LEVELS]; + + /* Pre-compute index at each level */ + for (int lvl = 0; lvl < ARCH_PAGE_TBL_LEVELS; lvl++) + { + lvl_off[lvl] = GET_LVL_INDEX(loop_va, lvl + 1); + } + + unmapped = 1ul << (ARCH_PAGE_SHIFT + ARCH_INDEX_WIDTH * (ARCH_PAGE_TBL_LEVELS - 1)); rt_ubase_t *pentry; - lvl_entry[i] = ((rt_ubase_t *)aspace->page_table + lvl_off[i]); + lvl_entry[i] = (top_table + lvl_off[i]); pentry = lvl_entry[i]; /* check if lvl_entry[0] is valid. if no, return 0 directly. */ @@ -514,7 +505,7 @@ static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr) { i += 1; - if (i >= 3) + if (i >= ARCH_PAGE_TBL_LEVELS) { unmapped = 0; break; @@ -536,18 +527,50 @@ static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr) unmapped = 0; /* invalid pte, return 0. */ } + return unmapped; +} + +/* Unmaps a virtual address range from the page table. */ +static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr) +{ + size_t unmapped = 0; + int nr_cpus = RT_CPUS_NR; + +#if defined(RT_USING_SMP) + /* For user address spaces, all harts share the same L2/L3/L4 page tables, as + * built by _map_one_page(). Only unmap hart 0's tree, otherwise the shared + * lower level page tables would be freed once per hart. */ + if (aspace != &rt_kernel_space) + { + nr_cpus = 1; + } +#endif + + for (int hartid = 0; hartid < nr_cpus; hartid++) + { + rt_ubase_t *top_table = + (rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(hartid * ARCH_PAGE_SIZE)); + size_t hart_unmapped = _unmap_area_one(top_table, v_addr); + + if (hartid == 0) + { + unmapped = hart_unmapped; + } + } + #if defined(RT_USING_SMP) /* For user address spaces, sync L1 entry from hart 0 to all other harts. * This ensures that if L1 was cleared (due to L2 being freed), all harts * see the updated L1 consistently. */ if (aspace != &rt_kernel_space && unmapped > 0) { - rt_ubase_t *mmu_l1_0 = (rt_ubase_t *)aspace->page_table + lvl_off[0]; + rt_ubase_t l1_off = GET_LVL_INDEX((rt_ubase_t)v_addr, 1); + rt_ubase_t *mmu_l1_0 = (rt_ubase_t *)aspace->page_table + l1_off; for (int h = 1; h < RT_CPUS_NR; h++) { rt_ubase_t *mmu_l1_h = (rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(h * ARCH_PAGE_SIZE)) + - lvl_off[0]; + l1_off; *mmu_l1_h = *mmu_l1_0; rt_hw_cpu_dcache_clean(mmu_l1_h, sizeof(*mmu_l1_h)); } @@ -634,7 +657,7 @@ static inline void _init_region(void *vaddr, size_t size) * This function initializes the MMU mapping, incluing these steps as follows: * 1. Check the validity of the input parameters, * 2. Calculate the start and end virtual addresses based on the input virtual address and size. - * 3. Convert the virtual addresses to PPN2 indices. + * 3. Convert the virtual addresses to top-level page table indices. * 4. Check the initialization of the page table. If any entry in the page table within * the specified range is non-zero, it returns -1. * 5. It initializes the kernel address space using rt_aspace_init() and initializes the specified region @@ -667,7 +690,7 @@ int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, return -1; } - /* convert address to PPN2 index */ + /* convert address to top-level page table index */ va_s = GET_L1(va_s); va_e = GET_L1(va_e); @@ -693,8 +716,7 @@ int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, return 0; } -const static int max_level = - (ARCH_VADDR_WIDTH - ARCH_PAGE_SHIFT) / ARCH_INDEX_WIDTH; +const static int max_level = ARCH_PAGE_TBL_LEVELS; static inline uintptr_t _get_level_size(int level) { @@ -703,13 +725,8 @@ static inline uintptr_t _get_level_size(int level) static rt_ubase_t *_query(struct rt_aspace *aspace, void *vaddr, int *level) { - rt_ubase_t l1_off, l2_off, l3_off; - rt_ubase_t *mmu_l1, *mmu_l2, *mmu_l3; - rt_ubase_t pa; - - l1_off = GET_L1((rt_uintptr_t)vaddr); - l2_off = GET_L2((rt_uintptr_t)vaddr); - l3_off = GET_L3((rt_uintptr_t)vaddr); + rt_ubase_t *table; + rt_ubase_t off; if (!aspace) { @@ -717,37 +734,29 @@ static rt_ubase_t *_query(struct rt_aspace *aspace, void *vaddr, int *level) return RT_NULL; } - mmu_l1 = ((rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(rt_hw_cpu_id() * ARCH_PAGE_SIZE))) + l1_off; + table = (rt_ubase_t *)((rt_ubase_t)aspace->page_table + (rt_ubase_t)(rt_hw_cpu_id() * ARCH_PAGE_SIZE)); - if (PTE_USED(*mmu_l1)) + for (int lvl = 1; lvl <= ARCH_PAGE_TBL_LEVELS; lvl++) { - if (*mmu_l1 & PTE_XWR_MASK) - { - *level = 1; - return mmu_l1; - } - - mmu_l2 = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*mmu_l1), PV_OFFSET); + off = GET_LVL_INDEX((rt_uintptr_t)vaddr, lvl); - if (PTE_USED(*(mmu_l2 + l2_off))) + if (PTE_USED(*(table + off))) { - if (*(mmu_l2 + l2_off) & PTE_XWR_MASK) + if (PAGE_IS_LEAF(*(table + off))) { - *level = 2; - return mmu_l2 + l2_off; + *level = lvl; + return table + off; } - mmu_l3 = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*(mmu_l2 + l2_off)), - PV_OFFSET); - - if (PTE_USED(*(mmu_l3 + l3_off))) - { - *level = 3; - return mmu_l3 + l3_off; - } + /* Not a leaf, step into next level page table */ + table = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*(table + off)), PV_OFFSET); + } + else + { + /* hole in the page table, no mapping for this address */ + break; } } - return RT_NULL; } @@ -956,19 +965,39 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid) /** * identical mapping, - * PC are still at lower region before relocating to high memory + * PC are still at lower region before relocating to high memory. + * Create a 1GB mapping at the correct page table level for all SV modes. */ - rt_ubase_t pg_idx; - /* Round down symb_pc to L1_PAGE_SIZE boundary to ensure proper page alignment. - * This is necessary because MMU operations work with page-aligned addresses, and - * make sure all the text region is mapped.*/ - ps = (rt_ubase_t)symb_pc & (~(L1_PAGE_SIZE - 1)); - pg_idx = GET_L1(ps); - early_pgtbl[pg_idx] = COMBINEPTE(ps, MMU_MAP_EARLY); + { + unsigned long page, *table; + rt_ubase_t off, level_shift; + + ps = (rt_ubase_t)symb_pc & (~(EARLY_MAP_PAGE_SIZE_1G - 1)); + table = (unsigned long *)early_pgtbl; + level_shift = ARCH_TOP_LEVEL_SHIFT; + + /* Traverse to the 1GB leaf level */ + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS - 2; ++level) + { + off = (ps >> level_shift) & VPN_MASK; + if (!(table[off] & PTE_V)) + { + page = get_free_page(); + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + table[off] = ((page >> ARCH_PAGE_SHIFT) << PTE_PPN_SHIFT) | PTE_V; + } + page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)page; + level_shift -= VPN_BITS; + } + + off = (ps >> level_shift) & VPN_MASK; + table[off] = ((ps >> ARCH_PAGE_SHIFT) << PTE_BITS) | MMU_MAP_EARLY; + } /* relocate text region */ __asm__ volatile("la %0, _start\n" : "=r"(ps)); - ps &= ~(L1_PAGE_SIZE - 1); + ps &= ~(EARLY_MAP_PAGE_SIZE_1G - 1); vs = ps - pv_off; /* relocate region */ @@ -977,14 +1006,37 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid) while (vs < ve) { rt_hw_mmu_map_early(early_pgtbl, vs, ps, MMU_MAP_EARLY); - vs += L2_PAGE_SIZE; - ps += L2_PAGE_SIZE; + vs += EARLY_MAP_PAGE_SIZE_2M; + ps += EARLY_MAP_PAGE_SIZE_2M; } #else - for (int i = GET_L1(vs); i < GET_L1(ve); i++) + while (vs < ve) { - early_pgtbl[i] = COMBINEPTE(ps, MMU_MAP_EARLY); - ps += L1_PAGE_SIZE; + unsigned long page, *table; + rt_ubase_t off, level_shift; + + table = (unsigned long *)early_pgtbl; + level_shift = ARCH_TOP_LEVEL_SHIFT; + + for (int level = 1; level < ARCH_PAGE_TBL_LEVELS - 2; ++level) + { + off = (vs >> level_shift) & VPN_MASK; + if (!(table[off] & PTE_V)) + { + page = get_free_page(); + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + table[off] = ((page >> ARCH_PAGE_SHIFT) << PTE_PPN_SHIFT) | PTE_V; + } + page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)page; + level_shift -= VPN_BITS; + } + + off = (vs >> level_shift) & VPN_MASK; + table[off] = ((ps >> ARCH_PAGE_SHIFT) << PTE_BITS) | MMU_MAP_EARLY; + + vs += EARLY_MAP_PAGE_SIZE_1G; + ps += EARLY_MAP_PAGE_SIZE_1G; } #endif @@ -1001,8 +1053,8 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid) { /* Map physical address per-CPU partition */ rt_hw_mmu_map_percpu_early(early_pgtbl, vs, ps); - ps += L2_PAGE_SIZE; - vs += L2_PAGE_SIZE; + ps += EARLY_MAP_PAGE_SIZE_2M; + vs += EARLY_MAP_PAGE_SIZE_2M; } #endif /* apply new mapping */ @@ -1013,6 +1065,19 @@ void rt_hw_mem_setup_early(void *pgtbl, rt_uint64_t hartid) /* return to lower text section */ } +/* Each aspace owns RT_CPUS_NR consecutive top-level page table pages (one + * per hart), as assumed by _map_one_page() and rt_hw_aspace_switch(). */ +rt_inline int _pgtbl_order(void) +{ + int order = 0; + + while ((1 << order) < RT_CPUS_NR) + { + order++; + } + return order; +} + /** * @brief Creates and initializes a new MMU page table. * @@ -1031,11 +1096,7 @@ void *rt_hw_mmu_pgtbl_create(void) /* Each hart needs its own L1 page table (for per-hart kernel .percpu mappings), * so allocate RT_CPUS_NR pages. Compute allocation order: smallest order where * 2^order >= RT_CPUS_NR. */ - int order = 0; - while ((1 << order) < RT_CPUS_NR) - { - order++; - } + int order = _pgtbl_order(); mmu_table = (rt_ubase_t *)rt_pages_alloc_ext(order, PAGE_ANY_AVAILABLE); if (!mmu_table) { @@ -1076,11 +1137,7 @@ void *rt_hw_mmu_pgtbl_create(void) void rt_hw_mmu_pgtbl_delete(void *pgtbl) { #if defined(RT_USING_SMP) - int order = 0; - while ((1 << order) < RT_CPUS_NR) - { - order++; - } + int order = _pgtbl_order(); rt_pages_free(pgtbl, order); #else rt_pages_free(pgtbl, 0); diff --git a/libcpu/risc-v/common64/mmu.h b/libcpu/risc-v/common64/mmu.h index eb4dd9a629c3..4e8e42d1a46a 100644 --- a/libcpu/risc-v/common64/mmu.h +++ b/libcpu/risc-v/common64/mmu.h @@ -7,6 +7,7 @@ * Date Author Notes * 2021-01-30 lizhirui first version * 2023-10-12 Shell Add permission control API + * 2026-08-25 chenguohao Add SV48/SV57 support */ #ifndef __MMU_H__ @@ -37,18 +38,58 @@ struct mem_desc #define GET_PF_ID(addr) ((addr) >> PAGE_OFFSET_BIT) #define GET_PF_OFFSET(addr) __MASKVALUE(addr, PAGE_OFFSET_MASK) -#define GET_L1(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT) -#define GET_L2(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT) -#define GET_L3(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT) -#define GET_PPN(pte) \ + +#ifndef ARCH_PAGE_TBL_LEVELS +#if (SATP_MODE == SATP_MODE_SV57) +#define ARCH_PAGE_TBL_LEVELS 5 +#elif (SATP_MODE == SATP_MODE_SV48) +#define ARCH_PAGE_TBL_LEVELS 4 +#else +#define ARCH_PAGE_TBL_LEVELS 3 +#endif +#endif /* ARCH_PAGE_TBL_LEVELS */ + +/* Top-level page table shift (PGD index extraction shift) */ +#ifndef ARCH_TOP_LEVEL_SHIFT +#define ARCH_TOP_LEVEL_SHIFT \ + (ARCH_PAGE_SHIFT + (ARCH_PAGE_TBL_LEVELS - 1) * ARCH_INDEX_WIDTH) +#endif + +/* Early mapping uses the fixed 1G/2M leaf size, whatever the paging mode is */ +#ifndef EARLY_MAP_PAGE_SIZE_1G +#define EARLY_MAP_PAGE_SIZE_1G __SIZE(ARCH_PAGE_SHIFT + 2 * ARCH_INDEX_WIDTH) +#endif +#ifndef EARLY_MAP_PAGE_SIZE_2M +#define EARLY_MAP_PAGE_SIZE_2M __SIZE(ARCH_PAGE_SHIFT + ARCH_INDEX_WIDTH) +#endif + +#if (ARCH_PAGE_TBL_LEVELS == 5) +#define GET_L1(addr) __PARTBIT(addr, VPN4_SHIFT, VPN4_BIT) +#define GET_L2(addr) __PARTBIT(addr, VPN3_SHIFT, VPN3_BIT) +#define GET_L3(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT) +#define GET_L4(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT) +#define GET_L5(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT) +#elif (ARCH_PAGE_TBL_LEVELS == 4) +#define GET_L1(addr) __PARTBIT(addr, VPN3_SHIFT, VPN3_BIT) +#define GET_L2(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT) +#define GET_L3(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT) +#define GET_L4(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT) +#elif (ARCH_PAGE_TBL_LEVELS == 3) +#define GET_L1(addr) __PARTBIT(addr, VPN2_SHIFT, VPN2_BIT) +#define GET_L2(addr) __PARTBIT(addr, VPN1_SHIFT, VPN1_BIT) +#define GET_L3(addr) __PARTBIT(addr, VPN0_SHIFT, VPN0_BIT) +#endif + +/* Runtime level index extraction: get the page table index at given level (1-based) */ +#define GET_LVL_INDEX(addr, level) \ + (((rt_ubase_t)(addr) >> (ARCH_PAGE_SHIFT + (ARCH_PAGE_TBL_LEVELS - (level)) * ARCH_INDEX_WIDTH)) & VPN_MASK) + +#define GET_PPN(pte) \ (__PARTBIT(pte, PTE_PPN_SHIFT, PHYSICAL_ADDRESS_WIDTH_BITS - PAGE_OFFSET_BIT)) #define GET_PADDR(pte) (GET_PPN(pte) << PAGE_OFFSET_BIT) #define VPN_TO_PPN(vaddr, pv_off) (((rt_uintptr_t)(vaddr)) + (pv_off)) #define PPN_TO_VPN(paddr, pv_off) (((rt_uintptr_t)(paddr)) - (pv_off)) -#define COMBINEVADDR(l1_off, l2_off, l3_off) \ - (((l1_off) << VPN2_SHIFT) | ((l2_off) << VPN1_SHIFT) | \ - ((l3_off) << VPN0_SHIFT)) -#define COMBINEPTE(paddr, attr) \ +#define COMBINEPTE(paddr, attr) \ ((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr)) #define MMU_MAP_ERROR_VANOTALIGN -1 @@ -56,9 +97,9 @@ struct mem_desc #define MMU_MAP_ERROR_NOPAGE -3 #define MMU_MAP_ERROR_CONFLICT -4 -#define VPN_MASK 0x1ffUL -#define PTE_BITS 10 -#define VPN_BITS 9 +#define VPN_MASK 0x1ffUL +#define PTE_BITS 10 +#define VPN_BITS 9 #if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) extern unsigned int __percpu_end, __percpu_start; diff --git a/libcpu/risc-v/t-head/c908/cache.h b/libcpu/risc-v/t-head/c908/cache.h index 09ebce6861f2..cf7b21c88a1b 100644 --- a/libcpu/risc-v/t-head/c908/cache.h +++ b/libcpu/risc-v/t-head/c908/cache.h @@ -90,22 +90,6 @@ ALWAYS_INLINE void rt_hw_cpu_icache_invalidate_all_local(void) * ======================================== */ -#ifdef RT_USING_SMP -#error "TODO: cache maintainence have not ported to RISC-V SMP yet" - -void rt_hw_cpu_dcache_clean(void *addr, int size); -void rt_hw_cpu_dcache_invalidate(void *addr, int size); -void rt_hw_cpu_dcache_clean_invalidate(void *addr, int size); - -void rt_hw_cpu_dcache_clean_all(void); -void rt_hw_cpu_dcache_invalidate_all(void); -void rt_hw_cpu_dcache_clean_invalidate_all(void); - -void rt_hw_cpu_icache_invalidate(void *addr, int size); -void rt_hw_cpu_icache_invalidate_all(void); - -#else /* !RT_USING_SMP */ - #define rt_hw_cpu_dcache_clean rt_hw_cpu_dcache_clean_local #define rt_hw_cpu_dcache_invalidate rt_hw_cpu_dcache_invalidate_local #define rt_hw_cpu_dcache_clean_and_invalidate rt_hw_cpu_dcache_clean_invalidate_local @@ -117,8 +101,6 @@ void rt_hw_cpu_icache_invalidate_all(void); #define rt_hw_cpu_icache_invalidate rt_hw_cpu_icache_invalidate_local #define rt_hw_cpu_icache_invalidate_all rt_hw_cpu_icache_invalidate_all_local -#endif /* RT_USING_SMP */ - /** * @brief Synchronize cache to Point of Unification */ diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c index 339dde808f20..3ed1cb4e0013 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ b/libcpu/risc-v/t-head/c908/interrupt.c @@ -15,9 +15,20 @@ #include "riscv.h" #include "plic.h" +#ifdef RT_USING_SMP +#include +#include +#include + +struct rt_irq_desc ipi_desc[RT_MAX_IPI]; +static volatile rt_uint8_t ipi_vectors[RT_CPUS_NR] = { 0 }; +#endif /* RT_USING_SMP */ + +#ifndef RT_USING_SMP extern rt_atomic_t rt_interrupt_nest; extern rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; extern rt_uint32_t rt_thread_switch_interrupt_flag; +#endif struct rt_irq_desc isr_table[INTERRUPTS_MAX]; @@ -42,11 +53,13 @@ void rt_hw_interrupt_init(void) isr_table[idx].handler = rt_hw_interrupt_handler; } + #ifndef RT_USING_SMP /* init interrupt nest, and context in thread sp */ rt_interrupt_nest = 0; rt_interrupt_from_thread = 0; rt_interrupt_to_thread = 0; rt_thread_switch_interrupt_flag = 0; + #endif } /** @@ -103,3 +116,120 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, return old_handler; } + +#ifdef RT_USING_SMP + +rt_bool_t rt_hw_interrupt_is_disabled(void) +{ + /* Determine the interrupt enable state */ + rt_ubase_t sstatus; + __asm__ volatile("csrr %0, sstatus" : "=r"(sstatus)); + return (sstatus & SSTATUS_SIE) == 0; +} + +void rt_hw_spin_lock_init(rt_hw_spinlock_t *_lock) +{ + _lock->slock = 0; +} + +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + /* Ticket lock on top of the AMO atomic ops: low 16 bits of slock are + * the owner, high 16 bits are the next-ticket allocator. */ + rt_atomic_t prev; + rt_atomic_t ticket; + rt_atomic_t owner; + + prev = rt_hw_atomic_add((volatile rt_atomic_t *)&lock->slock, (rt_atomic_t)(1UL << 16)); + ticket = (prev >> 16) & 0xffffUL; + + for (;;) + { + owner = rt_hw_atomic_load((volatile rt_atomic_t *)&lock->slock) & 0xffffUL; + if (owner == ticket) + { + break; + } + } + + __asm__ volatile("fence rw, rw" ::: "memory"); +} + +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + __asm__ volatile("fence rw, rw" ::: "memory"); + + if ((rt_hw_atomic_load((volatile rt_atomic_t *)&lock->slock) & (rt_atomic_t)0xffffUL) == (rt_atomic_t)0xffffUL) + { + /* owner overflow: clear the owner field, keep the ticket field */ + rt_hw_atomic_and((volatile rt_atomic_t *)&lock->slock, (rt_atomic_t)0xffff0000UL); + } + else + { + rt_hw_atomic_add((volatile rt_atomic_t *)&lock->slock, (rt_atomic_t)1); + } + + __asm__ volatile("fence rw, rw" ::: "memory"); +} + +void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask) +{ + int cpuid = __builtin_ctz(cpu_mask); // get the bit position of the lowest set bit + ipi_vectors[cpuid] |= (uint8_t)ipi_vector; + sbi_send_ipi((const unsigned long *)&cpu_mask); +} + +void rt_hw_ipi_init(void) +{ + static volatile rt_bool_t desc_inited = RT_FALSE; + int idx; + + if (!desc_inited) + { + /* first caller (boot hart, in rt_hw_board_init) resets the table */ + desc_inited = RT_TRUE; + for (idx = 0; idx < RT_MAX_IPI; idx++) + { + ipi_desc[idx].handler = RT_NULL; + ipi_desc[idx].param = RT_NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(ipi_desc[idx].name, RT_NAME_MAX - 1, "default"); + ipi_desc[idx].counter = 0; +#endif + } + } + + ipi_vectors[rt_hw_cpu_id()] = 0; + /* enable the S-mode software interrupt on the calling hart */ + set_csr(sie, SIP_SSIP); +} + +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler) +{ + if (ipi_vector < RT_MAX_IPI && ipi_isr_handler != RT_NULL) + { + ipi_desc[ipi_vector].handler = ipi_isr_handler; + ipi_desc[ipi_vector].param = RT_NULL; + } +} + +void rt_hw_ipi_handler(void) +{ + int cpuid = rt_hw_cpu_id(); + rt_uint32_t ipi_vector; + + ipi_vector = ipi_vectors[cpuid]; + while (ipi_vector) + { + int bitpos = __builtin_ctz(ipi_vector); + ipi_vector &= ~(1U << bitpos); + if (bitpos < RT_MAX_IPI && ipi_desc[bitpos].handler != RT_NULL) + { + rt_hw_atomic_and((volatile rt_atomic_t *)&ipi_vectors[rt_cpu_get_id()], ~((rt_atomic_t)(1 << bitpos))); + ipi_desc[bitpos].handler(bitpos, ipi_desc[bitpos].param); + } + } + + clear_csr(sip, SIP_SSIP); +} +#endif /* RT_USING_SMP */ diff --git a/libcpu/risc-v/t-head/c908/interrupt.h b/libcpu/risc-v/t-head/c908/interrupt.h index 2ee082483753..d1b7ea13a3be 100644 --- a/libcpu/risc-v/t-head/c908/interrupt.h +++ b/libcpu/risc-v/t-head/c908/interrupt.h @@ -45,4 +45,12 @@ void rt_hw_interrupt_mask(int vector); void rt_hw_interrupt_umask(int vector); rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); +#ifdef RT_USING_SMP +rt_bool_t rt_hw_interrupt_is_disabled(void); +void rt_hw_ipi_handler(void); +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler); +void rt_hw_ipi_init(void); +void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask); +#endif /* RT_USING_SMP */ + #endif diff --git a/libcpu/risc-v/t-head/c908/plic.c b/libcpu/risc-v/t-head/c908/plic.c index 08cb6c18d2f5..7cb313280d6d 100644 --- a/libcpu/risc-v/t-head/c908/plic.c +++ b/libcpu/risc-v/t-head/c908/plic.c @@ -156,10 +156,11 @@ rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) void plic_init(void) { int nr_irqs; - int nr_context; int i; unsigned long hwirq; - int cpu = 0; + struct plic_handler *handler; + uint32_t threshold = 0; + extern int boot_hartid; if (plic_regs) { @@ -167,8 +168,6 @@ void plic_init(void) return; } - nr_context = C908_NR_CONTEXT; - plic_regs = (void *)C908_PLIC_PHY_ADDR; if (!plic_regs) { @@ -178,41 +177,30 @@ void plic_init(void) nr_irqs = C908_PLIC_NR_EXT_IRQS; - for (i = 0; i < nr_context; i ++) - { - struct plic_handler *handler; - uint32_t threshold = 0; - - cpu = 0; - - /* skip contexts other than supervisor external interrupt */ - if (i == 0) - { - continue; - } - - // we always use CPU0 M-mode target register. - handler = &plic_handlers[cpu]; - if (handler->present) - { - threshold = 0xffffffff; - goto done; - } - - handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); - handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); + /* + * PLIC context layout: hart N owns context 2N (M-mode) and 2N + 1 + * (S-mode). The kernel only ever takes S-mode external interrupts, and + * only on the hart the firmware entered - which is not necessarily hart 0, + * as OpenSBI picks the boot hart dynamically. Binding the handler to a + * hard-coded context therefore leaves external interrupts masked whenever + * the boot hart is not 0, so derive the context from boot_hartid. + */ + i = boot_hartid * C908_NR_CONTEXT + 1; + + handler = &plic_handlers[0]; + handler->present = RT_TRUE; + handler->hart_base = (void *)((rt_size_t)plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); + handler->enable_base = (void *)((rt_size_t)plic_regs + ENABLE_BASE + i * ENABLE_PER_HART); #ifdef RT_USING_SMART - handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); - handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); + handler->hart_base = (void *)rt_ioremap(handler->hart_base, 0x1000); + handler->enable_base = (void *)rt_ioremap(handler->enable_base, 0x1000); #endif -done: - /* priority must be > threshold to trigger an interrupt */ - writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); - for (hwirq = 1; hwirq <= nr_irqs; hwirq++) - { - plic_toggle(handler, hwirq, 0); - } + + /* priority must be > threshold to trigger an interrupt */ + writel(threshold, (void *)((rt_size_t)handler->hart_base + CONTEXT_THRESHOLD)); + for (hwirq = 1; hwirq <= nr_irqs; hwirq++) + { + plic_toggle(handler, hwirq, 0); } /* Enable supervisor external interrupts. */ diff --git a/libcpu/risc-v/t-head/c908/riscv_mmu.h b/libcpu/risc-v/t-head/c908/riscv_mmu.h index c457d104c129..84d764bd7309 100644 --- a/libcpu/risc-v/t-head/c908/riscv_mmu.h +++ b/libcpu/risc-v/t-head/c908/riscv_mmu.h @@ -9,6 +9,7 @@ * 2021-05-03 lizhirui porting to C906 * 2023-10-12 Shell Add permission control API * 2026-02-25 Steven Porting to Standard Svpbmt + * 2026-08-25 chenguohao Add SV48/SV57 support */ #ifndef __RISCV_MMU_H__ @@ -34,11 +35,11 @@ #define PTE_PBMT_MASK (3UL << 61) #else /* XuanTie Extension (Bit 59-63) */ -#define PTE_SEC (1UL << 59) /* Security */ -#define PTE_SHARE (1UL << 60) /* Shareable */ -#define PTE_BUF (1UL << 61) /* Bufferable */ -#define PTE_CACHE (1UL << 62) /* Cacheable */ -#define PTE_SO (1UL << 63) /* Strong Order */ +#define PTE_SEC (1UL << 59) /* Security */ +#define PTE_SHARE (1UL << 60) /* Shareable */ +#define PTE_BUF (1UL << 61) /* Bufferable */ +#define PTE_CACHE (1UL << 62) /* Cacheable */ +#define PTE_SO (1UL << 63) /* Strong Order */ /* Compatible with Standard Svpbmt */ #define PTE_PBMT_PMA (PTE_CACHE | PTE_BUF | PTE_SHARE) #define PTE_PBMT_NC (PTE_BUF | PTE_SHARE) @@ -56,17 +57,22 @@ #define VPN1_BIT 9 #define VPN2_SHIFT (VPN1_SHIFT + VPN1_BIT) #define VPN2_BIT 9 +#define VPN3_SHIFT (VPN2_SHIFT + VPN2_BIT) +#define VPN3_BIT 9 +#define VPN4_SHIFT (VPN3_SHIFT + VPN3_BIT) +#define VPN4_BIT 9 #define PPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT) #define PPN0_BIT 9 #define PPN1_SHIFT (PPN0_SHIFT + PPN0_BIT) #define PPN1_BIT 9 #define PPN2_SHIFT (PPN1_SHIFT + PPN1_BIT) -#define PPN2_BIT 26 - -#define L1_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT + VPN0_BIT + VPN1_BIT) -#define L2_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT + VPN0_BIT) -#define L3_PAGE_SIZE __SIZE(PAGE_OFFSET_BIT) +#define PPN2_BIT 9 +#define PPN3_SHIFT (PPN2_SHIFT + PPN2_BIT) +#define PPN3_BIT 9 +#define PPN4_SHIFT (PPN3_SHIFT + PPN3_BIT) +#define PPN4_BIT 8 +#define PPN_BITS (PPN0_BIT + PPN1_BIT + PPN2_BIT + PPN3_BIT + PPN4_BIT) #define ARCH_ADDRESS_WIDTH_BITS 64 @@ -88,13 +94,13 @@ #define PAGE_DEFAULT_ATTR_LEAF \ (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G | PTE_PBMT_PMA | PTE_A | PTE_D) #else -#define PAGE_DEFAULT_ATTR_LEAF \ - (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | \ - PTE_CACHE | PTE_A | PTE_D) +#define PAGE_DEFAULT_ATTR_LEAF \ + (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | \ + PTE_CACHE | PTE_A | PTE_D) #endif #define PAGE_DEFAULT_ATTR_NEXT (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G) -#define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX) +#define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX) #define PTE_USED(pte) __MASKVALUE(pte, PTE_V) #define PTE_WRAP(attr) (attr | PTE_A | PTE_D) @@ -109,8 +115,18 @@ #define SATP_MODE_SV57 10 #define SATP_MODE_SV64 11 -#define ARCH_VADDR_WIDTH 39 -#define SATP_MODE SATP_MODE_SV39 +/* default to Sv39 */ +#ifndef SATP_MODE +#define SATP_MODE SATP_MODE_SV39 +#endif + +#if (SATP_MODE == SATP_MODE_SV57) +#define ARCH_VADDR_WIDTH 57 +#elif (SATP_MODE == SATP_MODE_SV48) +#define ARCH_VADDR_WIDTH 48 +#else +#define ARCH_VADDR_WIDTH 39 +#endif #if !CONFIG_XUANTIE_SVPBMT /* @@ -120,16 +136,16 @@ #define MMU_MAP_K_DEVICE (PTE_PBMT_IO | PTE_A | PTE_D | PTE_G | PTE_W | PTE_R | PTE_V) /* RW: Non-Cacheable (NC Mode) */ -#define MMU_MAP_K_RW (PTE_PBMT_NC | PTE_A | PTE_D | PTE_G | PAGE_ATTR_RWX | PTE_V) +#define MMU_MAP_K_RW (PTE_PBMT_NC | PTE_A | PTE_D | PTE_G | PAGE_ATTR_RWX | PTE_V) /* RWCB: Cacheable (PMA Mode) - Normal RAM */ -#define MMU_MAP_K_RWCB (PTE_PBMT_PMA | PTE_A | PTE_D | PTE_G | PAGE_ATTR_RWX | PTE_V) +#define MMU_MAP_K_RWCB (PTE_PBMT_PMA | PTE_A | PTE_D | PTE_G | PAGE_ATTR_RWX | PTE_V) /* * User Mappings */ /* User RW: Non-Cacheable */ -#define MMU_MAP_U_RW (PTE_PBMT_NC | PTE_U | PTE_A | PTE_D | PAGE_ATTR_RWX | PTE_V) +#define MMU_MAP_U_RW (PTE_PBMT_NC | PTE_U | PTE_A | PTE_D | PAGE_ATTR_RWX | PTE_V) /* User RWCB: Cacheable */ #define MMU_MAP_U_RWCB (PTE_PBMT_PMA | PTE_U | PTE_A | PTE_D | PAGE_ATTR_RWX | PTE_V) @@ -156,6 +172,7 @@ #define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1) #define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT #define ARCH_INDEX_WIDTH 9 +#define ARCH_INDEX_SIZE (1ul << ARCH_INDEX_WIDTH) #define ARCH_MAP_FAILED ((void *)0x8000000000000000) @@ -186,15 +203,15 @@ rt_inline size_t rt_hw_mmu_attr_rm_perm(size_t attr, rt_base_t prot) switch (prot) { /* remove write permission for user */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: - attr &= ~PTE_W; - break; + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + attr &= ~PTE_W; + break; /* remove write permission for kernel */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: - attr &= ~PTE_W; - break; - default: - RT_ASSERT(0); + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + attr &= ~PTE_W; + break; + default: + RT_ASSERT(0); } return attr; } @@ -211,11 +228,11 @@ rt_inline size_t rt_hw_mmu_attr_add_perm(size_t attr, rt_base_t prot) switch (prot) { /* add write permission for user */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: - attr |= (PTE_R | PTE_W | PTE_U); - break; - default: - RT_ASSERT(0); + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_USER: + attr |= (PTE_R | PTE_W | PTE_U); + break; + default: + RT_ASSERT(0); } return attr; } @@ -233,17 +250,17 @@ rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) switch (prot & ~RT_HW_MMU_PROT_USER) { /* test write permission for user */ - case RT_HW_MMU_PROT_WRITE: - rc = ((attr & PTE_W) && (attr & PTE_R)); - break; - case RT_HW_MMU_PROT_READ: - rc = !!(attr & PTE_R); - break; - case RT_HW_MMU_PROT_EXECUTE: - rc = !!(attr & PTE_X); - break; - default: - RT_ASSERT(0); + case RT_HW_MMU_PROT_WRITE: + rc = ((attr & PTE_W) && (attr & PTE_R)); + break; + case RT_HW_MMU_PROT_READ: + rc = !!(attr & PTE_R); + break; + case RT_HW_MMU_PROT_EXECUTE: + rc = !!(attr & PTE_X); + break; + default: + RT_ASSERT(0); } if (rc && (prot & RT_HW_MMU_PROT_USER))