diff --git a/bsp/qemu-virt64-riscv/.config b/bsp/qemu-virt64-riscv/.config index 67de44eef6e..a7fdcf06ea4 100644 --- a/bsp/qemu-virt64-riscv/.config +++ b/bsp/qemu-virt64-riscv/.config @@ -12,17 +12,7 @@ # # CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y -CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y -# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set -CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32 -CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32 -CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6 -CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9 -CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 +# CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD is not set # end of rt_vsnprintf options # @@ -121,10 +111,10 @@ CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 CONFIG_RT_NAME_MAX=24 # 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 +CONFIG_RT_USING_SMP=y +CONFIG_RT_CPUS_NR=4 CONFIG_RT_ALIGN_SIZE=8 # CONFIG_RT_THREAD_PRIORITY_8 is not set CONFIG_RT_THREAD_PRIORITY_32=y @@ -138,6 +128,7 @@ CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=16384 +CONFIG_SYSTEM_THREAD_STACK_SIZE=16384 CONFIG_RT_USING_TIMER_SOFT=y CONFIG_RT_TIMER_THREAD_PRIO=4 CONFIG_RT_TIMER_THREAD_STACK_SIZE=16384 @@ -155,7 +146,8 @@ CONFIG_RT_DEBUGING_ASSERT=y CONFIG_RT_DEBUGING_COLOR=y CONFIG_RT_DEBUGING_CONTEXT=y # CONFIG_RT_DEBUGING_AUTO_INIT is not set -# CONFIG_RT_DEBUGING_PAGE_LEAK is not set +# CONFIG_RT_DEBUGING_SPINLOCK is not set +CONFIG_RT_DEBUGING_CRITICAL=y # CONFIG_RT_USING_CI_ACTION is not set # @@ -173,7 +165,6 @@ CONFIG_RT_USING_SIGNALS=y # # Memory Management # -CONFIG_RT_PAGE_MAX_ORDER=11 CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_SMALL_MEM is not set CONFIG_RT_USING_SLAB=y @@ -190,24 +181,39 @@ CONFIG_RT_USING_HEAP=y CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_DEVICE_OPS=y -# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_INTERRUPT_INFO=y # CONFIG_RT_USING_THREADSAFE_PRINTF is not set CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" -CONFIG_RT_VER_NUM=0x50200 +CONFIG_RT_VER_NUM=0x50201 CONFIG_RT_USING_STDC_ATOMIC=y CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32 # end of RT-Thread Kernel +CONFIG_ARCH_TEXT_OFFSET=0x80200000 +CONFIG_ARCH_RAM_OFFSET=0 +CONFIG_ARCH_SECONDARY_CPU_STACK_SIZE=4096 +CONFIG_ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_ARCH_HEAP_SIZE=0x4000000 +CONFIG_ARCH_INIT_PAGE_SIZE=0x200000 + +# +# RISC-V Architecture Configuration +# +CONFIG_ARCH_RISCV_FPU=y +# CONFIG_ARCH_RISCV_VECTOR is not set +CONFIG_ARCH_USING_NEW_CTX_SWITCH=y +CONFIG_ARCH_USING_RISCV_COMMON64=y +# CONFIG_RT_USING_USERSPACE_32BIT_LIMIT is not set +# end of RISC-V Architecture Configuration + CONFIG_ARCH_CPU_64BIT=y CONFIG_RT_USING_CACHE=y +CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_MM_MMU=y +CONFIG_KERNEL_VADDR_START=0xfff0000000000000 CONFIG_ARCH_RISCV=y -CONFIG_ARCH_RISCV_FPU=y -CONFIG_ARCH_RISCV64=y -CONFIG_ARCH_USING_NEW_CTX_SWITCH=y -CONFIG_ARCH_USING_RISCV_COMMON64=y CONFIG_ARCH_REMAP_KERNEL=y # @@ -242,7 +248,6 @@ CONFIG_RT_USING_DFS=y CONFIG_DFS_USING_POSIX=y CONFIG_DFS_USING_WORKDIR=y CONFIG_DFS_FD_MAX=32 -# CONFIG_RT_USING_DFS_V1 is not set CONFIG_RT_USING_DFS_V2=y CONFIG_RT_USING_DFS_ELMFAT=y @@ -262,7 +267,7 @@ CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y # 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_DRIVES=8 CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512 # CONFIG_RT_DFS_ELM_USE_ERASE is not set CONFIG_RT_DFS_ELM_REENTRANT=y @@ -272,9 +277,23 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000 CONFIG_RT_USING_DFS_DEVFS=y CONFIG_RT_USING_DFS_ROMFS=y +CONFIG_RT_USING_DFS_PTYFS=y +# CONFIG_RT_USING_DFS_PROCFS is not set # CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_TMPFS is not set # CONFIG_RT_USING_DFS_MQUEUE is not set +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 @@ -282,7 +301,7 @@ CONFIG_RT_USING_DFS_ROMFS=y # # Device Drivers # -# CONFIG_RT_USING_DM is not set +CONFIG_RT_USING_DM=y # CONFIG_RT_USING_DEV_BUS is not set CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_UNAMED_PIPE_NUMBER=64 @@ -294,7 +313,13 @@ CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=64 -# CONFIG_RT_USING_SERIAL_BYPASS is not set +CONFIG_RT_USING_SERIAL_BYPASS=y +# CONFIG_RT_SERIAL_EARLY_HVC is not set +# CONFIG_RT_SERIAL_PL011 is not set +CONFIG_RT_SERIAL_8250=y +# CONFIG_RT_SERIAL_8250_DW is not set +# CONFIG_RT_SERIAL_8250_PCI is not set +CONFIG_RT_SERIAL_EARLY_SBI=y # CONFIG_RT_USING_CAN is not set CONFIG_RT_USING_CPUTIME=y CONFIG_RT_USING_CPUTIME_RISCV=y @@ -310,35 +335,203 @@ 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_NOR=y +CONFIG_RT_USING_MTD_NOR_CFI=y # CONFIG_RT_USING_MTD_NAND is not set -# CONFIG_RT_USING_PM is not set +CONFIG_RT_USING_PM=y +CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 +# CONFIG_PM_USING_CUSTOM_CONFIG is not set +# CONFIG_PM_ENABLE_DEBUG is not set +# CONFIG_PM_ENABLE_SUSPEND_SLEEP_MODE is not set +# CONFIG_PM_ENABLE_THRESHOLD_SLEEP_MODE 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_ALARM=y +CONFIG_RT_ALARM_STACK_SIZE=16384 +CONFIG_RT_ALARM_TIMESLICE=5 +CONFIG_RT_ALARM_PRIORITY=10 +# CONFIG_RT_USING_SOFT_RTC is not set +CONFIG_RT_RTC_GOLDFISH=y +# CONFIG_RT_RTC_PL031 is not set +CONFIG_RT_USING_SDIO=y +CONFIG_RT_SDIO_STACK_SIZE=16384 +CONFIG_RT_SDIO_THREAD_PRIORITY=15 +CONFIG_RT_MMCSD_STACK_SIZE=16384 +CONFIG_RT_MMCSD_THREAD_PRIORITY=22 +CONFIG_RT_MMCSD_MAX_PARTITION=16 +# CONFIG_RT_SDIO_DEBUG is not set +CONFIG_RT_USING_SDHCI=y +CONFIG_RT_SDIO_SDHCI_PCI=y # CONFIG_RT_USING_SPI is not set -# CONFIG_RT_USING_WDT is not set -# CONFIG_RT_USING_AUDIO is not set +CONFIG_RT_USING_WDT=y +# CONFIG_RT_WDT_DW is not set +CONFIG_RT_WDT_I6300ESB=y +CONFIG_RT_USING_AUDIO=y +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_SIZE=4096 +CONFIG_RT_AUDIO_REPLAY_MP_BLOCK_COUNT=2 +CONFIG_RT_AUDIO_RECORD_PIPE_SIZE=2048 +CONFIG_RT_AUDIO_INTEL_HDA=y # CONFIG_RT_USING_SENSOR is not set -# CONFIG_RT_USING_TOUCH is not set -# CONFIG_RT_USING_LCD is not set -# CONFIG_RT_USING_HWCRYPTO is not set +CONFIG_RT_USING_TOUCH=y +# CONFIG_RT_TOUCH_PIN_IRQ is not set +CONFIG_RT_USING_LCD=y +CONFIG_RT_USING_GRAPHIC=y +# CONFIG_RT_GRAPHIC_BACKLIGHT is not set +CONFIG_RT_GRAPHIC_FB=y +# CONFIG_RT_GRAPHIC_FB_FLOAT is not set +# CONFIG_RT_GRAPHIC_FB_SIMPLE is not set +CONFIG_RT_GRAPHIC_LOGO=y +# CONFIG_RT_GRAPHIC_LOGO_NONE is not set +CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_CLUT224=y +# CONFIG_RT_GRAPHIC_LOGO_RT_THREAD_WHITE_CLUT224 is not set +CONFIG_RT_USING_HWCRYPTO=y +CONFIG_RT_HWCRYPTO_DEFAULT_NAME="hwcryto" +CONFIG_RT_HWCRYPTO_IV_MAX_SIZE=16 +CONFIG_RT_HWCRYPTO_KEYBIT_MAX_SIZE=256 +# CONFIG_RT_HWCRYPTO_USING_GCM is not set +CONFIG_RT_HWCRYPTO_USING_AES=y +CONFIG_RT_HWCRYPTO_USING_AES_ECB=y +CONFIG_RT_HWCRYPTO_USING_AES_CBC=y +# CONFIG_RT_HWCRYPTO_USING_AES_CFB is not set +CONFIG_RT_HWCRYPTO_USING_AES_CTR=y +# CONFIG_RT_HWCRYPTO_USING_AES_OFB is not set +CONFIG_RT_HWCRYPTO_USING_DES=y +CONFIG_RT_HWCRYPTO_USING_DES_ECB=y +CONFIG_RT_HWCRYPTO_USING_DES_CBC=y +CONFIG_RT_HWCRYPTO_USING_3DES=y +CONFIG_RT_HWCRYPTO_USING_3DES_ECB=y +CONFIG_RT_HWCRYPTO_USING_3DES_CBC=y +CONFIG_RT_HWCRYPTO_USING_RC4=y +# CONFIG_RT_HWCRYPTO_USING_MD5 is not set +# CONFIG_RT_HWCRYPTO_USING_SHA1 is not set +# CONFIG_RT_HWCRYPTO_USING_SHA2 is not set +CONFIG_RT_HWCRYPTO_USING_RNG=y +# CONFIG_RT_HWCRYPTO_USING_CRC is not set +# CONFIG_RT_HWCRYPTO_USING_BIGNUM is not set # CONFIG_RT_USING_WIFI is not set -# CONFIG_RT_USING_BLK is not set +CONFIG_RT_USING_ETHERNET=y +# CONFIG_RT_ETHERNET_CADENCE is not set +# CONFIG_RT_ETHERNET_REALTEK is not set +# CONFIG_RT_USING_LED is not set +CONFIG_RT_USING_INPUT=y +CONFIG_RT_INPUT_POWER=y +# CONFIG_RT_INPUT_JOYSTICK is not set +# CONFIG_RT_INPUT_KEYBOARD is not set +# CONFIG_RT_INPUT_MISC is not set +CONFIG_RT_INPUT_TOUCHSCREEN=y +CONFIG_RT_USING_MBOX=y +CONFIG_RT_MBOX_PIC=y +# CONFIG_RT_USING_HWSPINLOCK is not set +CONFIG_RT_USING_RPMSG=y +CONFIG_RT_RPMSG_CHAR_MSG_MAX=64 +CONFIG_RT_RPMSG_CHAR_MSG_SIZE_MAX=256 +# CONFIG_RT_USING_PHYE is not set +CONFIG_RT_USING_ATA=y +CONFIG_RT_ATA_AHCI=y +# CONFIG_RT_ATA_AHCI_PCI is not set +CONFIG_RT_USING_NVME=y +CONFIG_RT_USING_NVME_IO_QUEUE=4 +CONFIG_RT_NVME_PCI=y +CONFIG_RT_USING_BLK=y + +# +# Partition Types +# +CONFIG_RT_BLK_PARTITION_DFS=y +CONFIG_RT_BLK_PARTITION_EFI=y +# end of Partition Types + +CONFIG_RT_USING_SCSI=y +CONFIG_RT_SCSI_SD=y +CONFIG_RT_SCSI_CDROM=y +# CONFIG_RT_USING_UFS is not set +CONFIG_RT_USING_FIRMWARE=y +CONFIG_RT_FIRMWARE_QEMU_FW_CFG=y +# CONFIG_RT_USING_HWCACHE is not set +# CONFIG_RT_USING_DVFS is not set +CONFIG_RT_USING_REGULATOR=y +CONFIG_RT_USING_RESET=y +# CONFIG_RT_RESET_SIMPLE is not set + +# +# Power Management (PM) Domains device drivers +# +# end of Power Management (PM) Domains device drivers + +CONFIG_RT_USING_POWER_RESET=y +CONFIG_RT_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_RT_POWER_RESET_SYSCON_REBOOT=y +# CONFIG_RT_USING_POWER_SUPPLY is not set +CONFIG_RT_USING_THERMAL=y + +# +# Thermal Sensors Drivers +# + +# +# Thermal Cool Drivers +# +# CONFIG_RT_USING_PTP is not set CONFIG_RT_USING_VIRTIO=y -CONFIG_RT_USING_VIRTIO10=y -# CONFIG_RT_USING_VIRTIO_MMIO_ALIGN is not set -CONFIG_RT_USING_VIRTIO_BLK=y -CONFIG_RT_USING_VIRTIO_NET=y -CONFIG_RT_USING_VIRTIO_CONSOLE=y -CONFIG_RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR=4 -CONFIG_RT_USING_VIRTIO_GPU=y -CONFIG_RT_USING_VIRTIO_INPUT=y -CONFIG_RT_USING_PIN=y +CONFIG_RT_VIRTIO_TRANSPORT_MMIO=y +CONFIG_RT_VIRTIO_TRANSPORT_PCI=y +CONFIG_RT_VIRTIO_NET=y +CONFIG_RT_VIRTIO_BLK=y +CONFIG_RT_VIRTIO_CONSOLE=y +CONFIG_RT_VIRTIO_RNG=y +CONFIG_RT_VIRTIO_RPMSG=y +CONFIG_RT_VIRTIO_SCSI=y +# CONFIG_RT_VIRTIO_9P is not set +CONFIG_RT_VIRTIO_RPROC_SERIAL=y +CONFIG_RT_VIRTIO_GPU=y +CONFIG_RT_VIRTIO_INPUT=y +CONFIG_RT_VIRTIO_CRYPTO=y +CONFIG_RT_VIRTIO_SOUND=y +# CONFIG_RT_USING_NVMEM is not set +# CONFIG_RT_USING_TEE is not set +CONFIG_RT_USING_DMA=y +# CONFIG_RT_DMA_PL330 is not set +# CONFIG_RT_USING_IOMMU is not set +CONFIG_RT_USING_MFD=y +CONFIG_RT_MFD_EDU=y +CONFIG_RT_MFD_SYSCON=y +CONFIG_RT_USING_IVSHMEM=y +CONFIG_RT_IVSHMEM_QEMU=y +CONFIG_RT_USING_OFW=y +# CONFIG_RT_USING_BUILTIN_FDT is not set +CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128 +CONFIG_RT_USING_OFW_BUS_RANGES_NUMBER=8 +CONFIG_RT_USING_PCI=y +CONFIG_RT_PCI_MSI=y +# CONFIG_RT_PCI_ENDPOINT is not set +CONFIG_RT_PCI_SYS_64BIT=y +CONFIG_RT_PCI_CACHE_LINE_SIZE=8 +# CONFIG_RT_PCI_LOCKLESS is not set + +# +# PCI Device Drivers +# +CONFIG_RT_PCI_ECAM=y +CONFIG_RT_PCI_HOST_COMMON=y +CONFIG_RT_PCI_HOST_GENERIC=y +# CONFIG_RT_PCI_DW is not set +CONFIG_RT_USING_PIC=y +# CONFIG_RT_USING_PIC_STATISTICS is not set +CONFIG_MAX_HANDLERS=512 +# CONFIG_RT_PIC_ARM_GIC is not set +# CONFIG_RT_PIC_ARM_GIC_V3 is not set +CONFIG_RT_PIC_RISCV_AIA=y +# CONFIG_RT_PIC_RISCV_CLIC is not set +CONFIG_RT_PIC_RISCV_INTC=y +CONFIG_RT_PIC_SIFIVE_PLIC=y +# CONFIG_RT_USING_PIN is not set CONFIG_RT_USING_KTIME=y -# CONFIG_RT_USING_HWTIMER is not set +CONFIG_RT_USING_CLK=y +CONFIG_RT_USING_HWTIMER=y # CONFIG_RT_USING_CHERRYUSB is not set + +# +# SoC (System on Chip) Drivers +# # end of Device Drivers # @@ -369,6 +562,9 @@ CONFIG_RT_USING_POSIX_STDIO=y CONFIG_RT_USING_POSIX_POLL=y CONFIG_RT_USING_POSIX_SELECT=y # CONFIG_RT_USING_POSIX_EVENTFD is not set +CONFIG_RT_USING_POSIX_EPOLL=y +CONFIG_RT_USING_POSIX_SIGNALFD=y +CONFIG_RT_SIGNALFD_MAX_NUM=10 # CONFIG_RT_USING_POSIX_TIMERFD is not set # CONFIG_RT_USING_POSIX_SOCKET is not set CONFIG_RT_USING_POSIX_TERMIOS=y @@ -498,9 +694,7 @@ CONFIG_RT_LWIP_USING_PING=y # # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set -CONFIG_RT_USING_UTEST=y -CONFIG_UTEST_THR_STACK_SIZE=4096 -CONFIG_UTEST_THR_PRIORITY=20 +# CONFIG_RT_USING_UTEST is not set # CONFIG_RT_USING_VAR_EXPORT is not set CONFIG_RT_USING_RESOURCE_ID=y CONFIG_RT_USING_ADT=y @@ -513,6 +707,38 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_RT_USING_VBUS is not set +# +# Memory management +# +CONFIG_RT_PAGE_MPR_SIZE_DYNAMIC=y +CONFIG_RT_PAGE_AFFINITY_BLOCK_SIZE=0x1000 +CONFIG_RT_PAGE_MAX_ORDER=11 +CONFIG_RT_USING_MEMBLOCK=y +CONFIG_RT_INIT_MEMORY_REGIONS=128 + +# +# 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=64 + # # Using USB legacy version # @@ -655,6 +881,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_LHC_MODBUS is not set # CONFIG_PKG_USING_QMODBUS is not set # CONFIG_PKG_USING_PNET is not set +# CONFIG_PKG_USING_OPENER is not set # end of IoT - internet of things # @@ -788,6 +1015,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_VOFA_PLUS is not set # CONFIG_PKG_USING_ZDEBUG is not set # CONFIG_PKG_USING_RVBACKTRACE is not set +# CONFIG_PKG_USING_HPATCHLITE is not set # end of tools packages # @@ -816,7 +1044,6 @@ CONFIG_RT_USING_ADT_REF=y # # CONFIG_PKG_USING_CMSIS_5 is not set # CONFIG_PKG_USING_CMSIS_CORE is not set -# CONFIG_PKG_USING_CMSIS_DSP is not set # CONFIG_PKG_USING_CMSIS_NN is not set # CONFIG_PKG_USING_CMSIS_RTOS1 is not set # CONFIG_PKG_USING_CMSIS_RTOS2 is not set @@ -868,7 +1095,6 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_ARM_2D is not set # CONFIG_PKG_USING_MCUBOOT is not set # CONFIG_PKG_USING_TINYUSB is not set -# CONFIG_PKG_USING_CHERRYUSB is not set # CONFIG_PKG_USING_KMULTI_RTIMER is not set # CONFIG_PKG_USING_TFDB is not set # CONFIG_PKG_USING_QPC is not set @@ -880,6 +1106,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_SFDB is not set # CONFIG_PKG_USING_RTP is not set # CONFIG_PKG_USING_REB is not set +# CONFIG_PKG_USING_RMP is not set # CONFIG_PKG_USING_R_RHEALSTONE is not set # CONFIG_PKG_USING_HEARTBEAT is not set # end of system packages @@ -895,12 +1122,40 @@ CONFIG_RT_USING_ADT_REF=y # # STM32 HAL & SDK Drivers # +# CONFIG_PKG_USING_STM32F0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F1_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F1_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F2_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F2_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F3_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F3_CMSIS_DRIVER is not set # CONFIG_PKG_USING_STM32F4_HAL_DRIVER is not set # CONFIG_PKG_USING_STM32F4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32F7_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32F7_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32G0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32G0_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32G4_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32G4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H5_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H7_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H7_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32H7RS_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32H7RS_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32L0_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32L0_CMSIS_DRIVER is not set # CONFIG_PKG_USING_STM32L4_HAL_DRIVER is not set # CONFIG_PKG_USING_STM32L4_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32L5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32L5_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_STM32U5_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32U5_CMSIS_DRIVER is not set # CONFIG_PKG_USING_STM32WB55_SDK is not set # CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_STM32WL_HAL_DRIVER is not set +# CONFIG_PKG_USING_STM32WL_CMSIS_DRIVER is not set # end of STM32 HAL & SDK Drivers # @@ -933,6 +1188,43 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_NRFX is not set # CONFIG_PKG_USING_NUCLEI_SDK is not set # CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set +# CONFIG_PKG_USING_MM32 is not set + +# +# WCH HAL & SDK Drivers +# +# CONFIG_PKG_USING_CH32V20x_SDK is not set +# CONFIG_PKG_USING_CH32V307_SDK is not set +# end of WCH HAL & SDK Drivers + +# +# AT32 HAL & SDK Drivers +# +# CONFIG_PKG_USING_AT32A403A_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32A403A_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32A423_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32A423_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F45x_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F45x_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F402_405_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F402_405_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F403A_407_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F403A_407_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F413_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F413_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F415_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F415_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F421_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F421_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F423_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F423_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F425_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F425_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32F435_437_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32F435_437_CMSIS_DRIVER is not set +# CONFIG_PKG_USING_AT32M412_416_HAL_DRIVER is not set +# CONFIG_PKG_USING_AT32M412_416_CMSIS_DRIVER is not set +# end of AT32 HAL & SDK Drivers # end of HAL & SDK Drivers # @@ -970,12 +1262,14 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_BMI088 is not set # CONFIG_PKG_USING_HMC5883 is not set # CONFIG_PKG_USING_MAX6675 is not set +# CONFIG_PKG_USING_MAX31855 is not set # CONFIG_PKG_USING_TMP1075 is not set # CONFIG_PKG_USING_SR04 is not set # CONFIG_PKG_USING_CCS811 is not set # CONFIG_PKG_USING_PMSXX is not set # CONFIG_PKG_USING_RT3020 is not set # CONFIG_PKG_USING_MLX90632 is not set +# CONFIG_PKG_USING_MLX90382 is not set # CONFIG_PKG_USING_MLX90393 is not set # CONFIG_PKG_USING_MLX90392 is not set # CONFIG_PKG_USING_MLX90394 is not set @@ -1004,6 +1298,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_PAJ7620 is not set # CONFIG_PKG_USING_STHS34PF80 is not set +# CONFIG_PKG_USING_P3T1755 is not set # end of sensors drivers # @@ -1095,6 +1390,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_BT_MX02 is not set # CONFIG_PKG_USING_GC9A01 is not set # CONFIG_PKG_USING_IK485 is not set +# CONFIG_PKG_USING_SERVO is not set # CONFIG_PKG_USING_SPI_TOOLS is not set # end of peripheral libraries and drivers @@ -1111,6 +1407,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_QUEST is not set # CONFIG_PKG_USING_NAXOS is not set # CONFIG_PKG_USING_R_TINYMAIX is not set +# CONFIG_PKG_USING_LLMCHAT is not set # end of AI packages # @@ -1181,6 +1478,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_KI is not set # CONFIG_PKG_USING_ARMv7M_DWT is not set # CONFIG_PKG_USING_CRCLIB is not set +# CONFIG_PKG_USING_LIBCRC is not set # CONFIG_PKG_USING_LWGPS is not set # CONFIG_PKG_USING_STATE_MACHINE is not set # CONFIG_PKG_USING_DESIGN_PATTERN is not set @@ -1191,6 +1489,7 @@ CONFIG_RT_USING_ADT_REF=y # CONFIG_PKG_USING_SOEM is not set # CONFIG_PKG_USING_QPARAM is not set # CONFIG_PKG_USING_CorevMCU_CLI is not set +# CONFIG_PKG_USING_DRMP is not set # end of miscellaneous packages # @@ -1430,19 +1729,4 @@ CONFIG_RT_USING_ADT_REF=y # end of Arduino libraries # end of RT-Thread online packages -# -# RISC-V QEMU virt64 configs -# -CONFIG_BSP_USING_VIRTIO=y -CONFIG_BSP_USING_VIRTIO_BLK=y -CONFIG_BSP_USING_VIRTIO_NET=y -CONFIG_BSP_USING_VIRTIO_CONSOLE=y -CONFIG_BSP_USING_VIRTIO_GPU=y -CONFIG_BSP_USING_VIRTIO_INPUT=y -# end of RISC-V QEMU virt64 configs - -CONFIG_BOARD_QEMU_VIRT_RV64=y -CONFIG_ENABLE_FPU=y -# CONFIG_ENABLE_VECTOR is not set -# CONFIG_RT_USING_USERSPACE_32BIT_LIMIT is not set -CONFIG___STACKSIZE__=16384 +CONFIG_SOC_VIRT64_RISCV64=y diff --git a/bsp/qemu-virt64-riscv/.gitignore b/bsp/qemu-virt64-riscv/.gitignore index 341f703a73f..a8bcb3a0091 100644 --- a/bsp/qemu-virt64-riscv/.gitignore +++ b/bsp/qemu-virt64-riscv/.gitignore @@ -1,3 +1,4 @@ mnt.c romfs_data.c opensbi +*.qcow2 diff --git a/bsp/qemu-virt64-riscv/Kconfig b/bsp/qemu-virt64-riscv/Kconfig index 544753502b2..e84d45327f3 100644 --- a/bsp/qemu-virt64-riscv/Kconfig +++ b/bsp/qemu-virt64-riscv/Kconfig @@ -6,52 +6,21 @@ RTT_DIR := ../../ PKGS_DIR := packages +SOC_DM_PIC_DIR := $(RTT_DIR)/libcpu/risc-v/common/pic +SOC_DM_SERIAL_DIR := $(RTT_DIR)/libcpu/risc-v/common/serial + source "$(RTT_DIR)/Kconfig" osource "$PKGS_DIR/Kconfig" -rsource "driver/Kconfig" -config BOARD_QEMU_VIRT_RV64 +config SOC_VIRT64_RISCV64 bool - select ARCH_RISCV64 + select ARCH_RISCV + select ARCH_CPU_64BIT select ARCH_USING_RISCV_COMMON64 select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select RT_USING_CACHE select ARCH_MM_MMU - select ARCH_REMAP_KERNEL - default y - -config ENABLE_FPU - bool "Enable FPU" - select ARCH_RISCV_FPU + select ARCH_REMAP_KERNEL if RT_USING_SMART + select RT_USING_STDC_ATOMIC default y - -config ENABLE_VECTOR - bool "Using RISC-V Vector Extension" - select ARCH_RISCV_VECTOR - default n - -if ENABLE_VECTOR - choice - prompt "Vector Registers Length in Bits" - default ARCH_VECTOR_VLEN_128 - - config ARCH_VECTOR_VLEN_128 - bool "128" - - config ARCH_VECTOR_VLEN_256 - bool "256" - endchoice -endif - -config RT_USING_USERSPACE_32BIT_LIMIT - bool "Enable userspace 32bit limit" - default n - -config RT_USING_VIRTIO_MMIO_ALIGN - bool "Open packed attribution, this may caused an error on virtio" - default n - -config __STACKSIZE__ - int "stack size for interrupt" - default 4096 diff --git a/bsp/qemu-virt64-riscv/SConstruct b/bsp/qemu-virt64-riscv/SConstruct index 3387d0e1490..cf25bd5ecc3 100644 --- a/bsp/qemu-virt64-riscv/SConstruct +++ b/bsp/qemu-virt64-riscv/SConstruct @@ -21,22 +21,9 @@ env['ASCOM'] = env['ASPPCOM'] Export('RTT_ROOT') Export('rtconfig') -rtconfig.CPU='virt64' -rtconfig.ARCH='risc-v' # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) -stack_size = 4096 - -if GetDepend('RT_USING_SMART'): - # use smart link.lds - env['LINKFLAGS'] = env['LINKFLAGS'].replace('link.lds', 'link_smart.lds') - -stack_lds = open('link_stacksize.lds', 'w') -if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__') -stack_lds.write('__STACKSIZE__ = %d;\n' % stack_size) -stack_lds.close() - # make a building DoBuilding(TARGET, objs) diff --git a/bsp/qemu-virt64-riscv/applications/mnt.c b/bsp/qemu-virt64-riscv/applications/mnt.c deleted file mode 100644 index ccf2b39809d..00000000000 --- a/bsp/qemu-virt64-riscv/applications/mnt.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021/08/19 bernard the first version - */ - -#include - -#ifdef RT_USING_DFS -#include -#include - -int mnt_init(void) -{ - if (rt_device_find("virtio-blk0")) - { - /* mount virtio-blk as root directory */ - if (dfs_mount("virtio-blk0", "/", "elm", 0, RT_NULL) == 0) - { - rt_kprintf("file system initialization done!\n"); - } - else - { - if (dfs_mount("virtio-blk0", "/", "ext", 0, RT_NULL) == 0) - { - rt_kprintf("file system initialization done!\n"); - } - else - { - rt_kprintf("file system initialization fail!\n"); - } - } - } - - return 0; -} -INIT_ENV_EXPORT(mnt_init); -#endif diff --git a/bsp/qemu-virt64-riscv/driver/Kconfig b/bsp/qemu-virt64-riscv/driver/Kconfig deleted file mode 100644 index ba9a2650e19..00000000000 --- a/bsp/qemu-virt64-riscv/driver/Kconfig +++ /dev/null @@ -1,43 +0,0 @@ -menu "RISC-V QEMU virt64 configs" - -config BSP_USING_VIRTIO - bool "Using VirtIO" - default y - depends on RT_USING_DEVICE_OPS - -config BSP_USING_VIRTIO_BLK - bool "Using VirtIO BLK" - select RT_USING_VIRTIO - select RT_USING_VIRTIO_BLK - default y - depends on BSP_USING_VIRTIO - -config BSP_USING_VIRTIO_NET - bool "Using VirtIO NET" - select RT_USING_VIRTIO - select RT_USING_VIRTIO_NET - default y - depends on BSP_USING_VIRTIO - -config BSP_USING_VIRTIO_CONSOLE - bool "Using VirtIO Console" - select RT_USING_VIRTIO - select RT_USING_VIRTIO_CONSOLE - default y - depends on BSP_USING_VIRTIO - -config BSP_USING_VIRTIO_GPU - bool "Using VirtIO GPU" - select RT_USING_VIRTIO - select RT_USING_VIRTIO_GPU - default y - depends on BSP_USING_VIRTIO - -config BSP_USING_VIRTIO_INPUT - bool "Using VirtIO Input" - select RT_USING_VIRTIO - select RT_USING_VIRTIO_INPUT - default y - depends on BSP_USING_VIRTIO - -endmenu diff --git a/bsp/qemu-virt64-riscv/driver/asm/sbiasm.h b/bsp/qemu-virt64-riscv/driver/asm/sbiasm.h deleted file mode 100644 index 4639fba68cf..00000000000 --- a/bsp/qemu-virt64-riscv/driver/asm/sbiasm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SBI_ASM_H -#define _SBI_ASM_H - -.macro SBI_CALL which - li a7, \which - ecall - nop -.endm - -#endif /* _SBI_ASM_H */ diff --git a/bsp/qemu-virt64-riscv/driver/asm/sbidef.h b/bsp/qemu-virt64-riscv/driver/asm/sbidef.h deleted file mode 100644 index 5bcf58ade7c..00000000000 --- a/bsp/qemu-virt64-riscv/driver/asm/sbidef.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019-2020, Xim - * - * SPDX-License-Identifier: Apache-2.0 - * - */ -#ifndef _ASM_SBI_DEF_H -#define _ASM_SBI_DEF_H - -#define SBI_SET_TIMER 0 -#define SBI_CONSOLE_PUTCHAR 1 -#define SBI_CONSOLE_GETCHAR 2 -#define SBI_CLEAR_IPI 3 -#define SBI_SEND_IPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 - -#define SBI_CONSOLE_PUTSTR 9 - -#define SBI_SD_WRITE 10 -#define SBI_SD_READ 11 -#define SBI_NET_WRITE 12 -#define SBI_NET_READ 13 - -#endif /* _ASM_SBI_DEF_H */ diff --git a/bsp/qemu-virt64-riscv/driver/board.c b/bsp/qemu-virt64-riscv/driver/board.c index c5116aad0c5..b59e744f469 100644 --- a/bsp/qemu-virt64-riscv/driver/board.c +++ b/bsp/qemu-virt64-riscv/driver/board.c @@ -6,104 +6,12 @@ * Change Logs: * Date Author Notes * 2021-01-30 lizhirui first version + * 2025-04-26 GuEe-GUI init common */ -#include -#include -#include - -#include "board.h" -#include "mm_aspace.h" -#include "tick.h" - -#include "drv_uart.h" -#include "encoding.h" -#include "stack.h" -#include "sbi.h" -#include "riscv.h" -#include "plic.h" -#include "stack.h" - -#ifdef RT_USING_SMART -#include "riscv_mmu.h" -#include "mmu.h" -#include "page.h" -#include "lwp_arch.h" - -rt_region_t init_page_region = {(rt_size_t)RT_HW_PAGE_START, (rt_size_t)RT_HW_PAGE_END}; - -extern size_t MMUTable[]; - -struct mem_desc platform_mem_desc[] = { - {KERNEL_VADDR_START, (rt_size_t)RT_HW_PAGE_END - 1, (rt_size_t)ARCH_MAP_FAILED, NORMAL_MEM}, -}; - -#define NUM_MEM_DESC (sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0])) - -#endif - -void primary_cpu_entry(void) -{ - /* disable global interrupt */ - rt_hw_interrupt_disable(); - - entry(); -} - -#define IOREMAP_SIZE (1ul << 30) - -#ifndef ARCH_REMAP_KERNEL -#define IOREMAP_VEND USER_VADDR_START -#else -#define IOREMAP_VEND 0ul -#endif /* ARCH_REMAP_KERNEL */ +#include void rt_hw_board_init(void) { -#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 - - plic_init(); - - rt_hw_interrupt_init(); - - rt_hw_uart_init(); - -#ifdef RT_USING_CONSOLE - /* set console device */ - rt_console_set_device(RT_CONSOLE_DEVICE_NAME); -#endif /* RT_USING_CONSOLE */ - - rt_hw_tick_init(); - -#ifdef RT_USING_COMPONENTS_INIT - rt_components_board_init(); -#endif - -#ifdef RT_USING_HEAP - rt_kprintf("heap: [0x%08x - 0x%08x]\n", (rt_ubase_t)RT_HW_HEAP_BEGIN, (rt_ubase_t)RT_HW_HEAP_END); -#endif /* RT_USING_HEAP */ + rt_hw_common_setup(); } - -void rt_hw_cpu_reset(void) -{ - sbi_shutdown(); - - while (1) - ; -} -MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine); - diff --git a/bsp/qemu-virt64-riscv/driver/board.h b/bsp/qemu-virt64-riscv/driver/board.h index 433b1d8f53b..2e6403edd59 100644 --- a/bsp/qemu-virt64-riscv/driver/board.h +++ b/bsp/qemu-virt64-riscv/driver/board.h @@ -13,22 +13,6 @@ #include -extern unsigned int __bss_start; -extern unsigned int __bss_end; - -#ifndef RT_USING_SMART -#define KERNEL_VADDR_START 0x0 -#endif - -#define VIRT64_SBI_MEMSZ (0x200000) - -#define RT_HW_HEAP_BEGIN ((void *)&__bss_end) -#define RT_HW_HEAP_END ((void *)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)) -#define RT_HW_PAGE_START RT_HW_HEAP_END -#define RT_HW_PAGE_END ((void *)(KERNEL_VADDR_START + (256 * 1024 * 1024 - VIRT64_SBI_MEMSZ))) - void rt_hw_board_init(void); -void rt_init_user_mem(struct rt_thread *thread, const char *name, - unsigned long *entry); -#endif +#endif /* BOARD_H__ */ diff --git a/bsp/qemu-virt64-riscv/driver/drv_romfb.c b/bsp/qemu-virt64-riscv/driver/drv_romfb.c new file mode 100644 index 00000000000..260bc9ed9a3 --- /dev/null +++ b/bsp/qemu-virt64-riscv/driver/drv_romfb.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI the first version + */ + +#include +#include + +void platform_get_ramfb_params(rt_uint32_t *width, rt_uint32_t *height) +{ + *width = 800; + *height = 600; +} + +#include "../../../examples/test/hmi_test.c" diff --git a/bsp/qemu-virt64-riscv/driver/drv_uart.c b/bsp/qemu-virt64-riscv/driver/drv_uart.c deleted file mode 100644 index 5e2a33e76ca..00000000000 --- a/bsp/qemu-virt64-riscv/driver/drv_uart.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#include -#include -#include - -#include "board.h" -#include "drv_uart.h" - -#include -#ifdef RT_USING_SMART -#include -#endif -#include "sbi.h" - -struct device_uart -{ - rt_ubase_t hw_base; - rt_uint32_t irqno; -}; - -void *uart0_base = (void*)0x10000000; -struct rt_serial_device serial0; -struct device_uart uart0; - -void uart_init(void) -{ - rt_uint32_t div = UART_REFERENCE_CLOCK / (UART_DEFAULT_BAUDRATE * 16); - - write8_uart0(UART_IER, 0x00); - write8_uart0(UART_LCR, UART_LCR_BAUD_LATCH); - - // LSB - write8_uart0(0, div & 0xff); - // MSB - write8_uart0(1, (div >> 8) & 0xff); - - // set word length to 8 bits, no parity - write8_uart0(UART_LCR, UART_LCR_EIGHT_BITS); - - write8_uart0(UART_FCR, UART_FCR_FIFO_ENABLE | UART_FCR_FIFO_CLEAR); - - return; -} - -static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) -{ - return (RT_EOK); -} - -static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg) -{ - struct device_uart *uart = (struct device_uart*)serial->parent.user_data; - - switch (cmd) - { - case RT_DEVICE_CTRL_CLR_INT: - if ((size_t)arg == RT_DEVICE_FLAG_INT_RX) - { - rt_uint8_t value = read8_uart0(UART_IER); - write8_uart0(UART_IER, value & ~UART_IER_RX_ENABLE); - } - break; - - case RT_DEVICE_CTRL_SET_INT: - if ((size_t)arg == RT_DEVICE_FLAG_INT_RX) - { - rt_uint8_t value = read8_uart0(UART_IER); - write8_uart0(UART_IER, value | UART_IER_RX_ENABLE); - } - break; - } - - return (RT_EOK); -} - -static int _uart_putc(struct rt_serial_device *serial, char c) -{ - struct device_uart *uart; - uart = (struct device_uart*)serial->parent.user_data; - - // wait for Transmit Holding Empty to be set in LSR. - while((read8_uart0(UART_LSR) & UART_LSR_TX_IDLE) == 0) - ; - write8_uart0(UART_THR, c); - - return (1); -} - -static int _uart_getc(struct rt_serial_device *serial) -{ - struct device_uart *uart; - volatile rt_uint32_t lsr; - int ch = -1; - - uart = (struct device_uart*)serial->parent.user_data; - lsr = read8_uart0(UART_LSR); - - if (lsr & UART_LSR_RX_READY) - { - ch = read8_uart0(UART_RHR); - } - return ch; -} - -const struct rt_uart_ops _uart_ops = { - _uart_configure, - _uart_control, - _uart_putc, - _uart_getc, - // TODO: add DMA support - RT_NULL}; - -static void rt_hw_uart_isr(int irqno, void *param) -{ - rt_ubase_t level = rt_hw_interrupt_disable(); - - struct rt_serial_device *serial = (struct rt_serial_device *)param; - - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); - - rt_hw_interrupt_enable(level); -} - -/* - * 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(uart0_base, 4096); -#endif - // register device - serial = &serial0; - uart = &uart0; - - serial->ops = &_uart_ops; - serial->config = config; - serial->config.baud_rate = UART_DEFAULT_BAUDRATE; - uart->hw_base = (rt_ubase_t)uart0_base; - uart->irqno = 0x0a; - - 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, rt_hw_uart_isr, serial, RT_CONSOLE_DEVICE_NAME); - rt_hw_interrupt_umask(uart->irqno); - return 0; -} - -/* WEAK for SDK 0.5.6 */ -rt_weak void uart_debug_init(int uart_channel) -{ -} diff --git a/bsp/qemu-virt64-riscv/driver/drv_uart.h b/bsp/qemu-virt64-riscv/driver/drv_uart.h deleted file mode 100644 index faba48c8a6e..00000000000 --- a/bsp/qemu-virt64-riscv/driver/drv_uart.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2006-2020, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ - -#ifndef __DRV_UART_H__ -#define __DRV_UART_H__ - -#include "riscv_io.h" - -/** - * uart ns16550a - * http://byterunner.com/16550.html - */ - -/* TRANSMIT AND RECEIVE HOLDING REGISTER */ -#define UART_RHR 0 -#define UART_THR 0 - -/* INTERRUPT ENABLE REGISTER */ -#define UART_IER 1 -#define UART_IER_RX_ENABLE (1 << 0) -#define UART_IER_TX_ENABLE (1 << 1) - -/* FIFO CONTROL REGISTER */ -#define UART_FCR 2 -#define UART_FCR_FIFO_ENABLE (1 << 0) -#define UART_FCR_FIFO_CLEAR (3 << 1) - -/* INTERRUPT STATUS REGISTER */ -#define UART_ISR 2 - -/* LINE CONTROL REGISTER */ -#define UART_LCR 3 -#define UART_LCR_EIGHT_BITS (3 << 0) -// special mode to set baud rate -#define UART_LCR_BAUD_LATCH (1 << 7) - -/* LINE STATUS REGISTER */ -#define UART_LSR 5 -// input is waiting to be read from RHR -#define UART_LSR_RX_READY (1 << 0) -// THR can accept another character to send -#define UART_LSR_TX_IDLE (1 << 5) - -#define UART_REFERENCE_CLOCK 1843200 -#define UART_DEFAULT_BAUDRATE 115200 - -extern void *uart0_base; - -#define write8_uart0(idx, value) __raw_writeb(((rt_uint8_t)value), (void*)((size_t)uart0_base + (idx))) -#define read8_uart0(idx) __raw_readb((void*)((size_t)uart0_base + (idx))) - -void rt_hw_uart_start_rx_thread(); -int rt_hw_uart_init(void); -void drv_uart_puts(char *str); // for syscall - -#endif /* __DRV_UART_H__ */ diff --git a/bsp/qemu-virt64-riscv/driver/drv_virtio.c b/bsp/qemu-virt64-riscv/driver/drv_virtio.c deleted file mode 100644 index e1289863b7e..00000000000 --- a/bsp/qemu-virt64-riscv/driver/drv_virtio.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-11-11 GuEe-GUI the first version - */ - -#include -#include - -#ifdef BSP_USING_VIRTIO - -#include -#ifdef BSP_USING_VIRTIO_BLK -#include -#endif -#ifdef BSP_USING_VIRTIO_NET -#include -#endif -#ifdef BSP_USING_VIRTIO_CONSOLE -#include -#endif -#ifdef BSP_USING_VIRTIO_GPU -#include -#endif -#ifdef BSP_USING_VIRTIO_INPUT -#include -#endif - -#include - -static virtio_device_init_handler virtio_device_init_handlers[] = -{ -#ifdef BSP_USING_VIRTIO_BLK - [VIRTIO_DEVICE_ID_BLOCK] = rt_virtio_blk_init, -#endif -#ifdef BSP_USING_VIRTIO_NET - [VIRTIO_DEVICE_ID_NET] = rt_virtio_net_init, -#endif -#ifdef BSP_USING_VIRTIO_CONSOLE - [VIRTIO_DEVICE_ID_CONSOLE] = rt_virtio_console_init, -#endif -#ifdef BSP_USING_VIRTIO_GPU - [VIRTIO_DEVICE_ID_GPU] = rt_virtio_gpu_init, -#endif -#ifdef BSP_USING_VIRTIO_INPUT - [VIRTIO_DEVICE_ID_INPUT] = rt_virtio_input_init, -#endif - [VIRTIO_DEVICE_TYPE_SIZE] = RT_NULL -}; - -int rt_virtio_devices_init(void) -{ - int i; - rt_uint32_t irq = VIRTIO_IRQ_BASE; - rt_ubase_t mmio_base = VIRTIO_MMIO_BASE; - struct virtio_mmio_config *mmio_config; - virtio_device_init_handler init_handler; - - if (sizeof(virtio_device_init_handlers) == 0) - { - /* The compiler will optimize the codes after here. */ - return 0; - } - -#ifdef RT_USING_SMART - mmio_base = (rt_ubase_t)rt_ioremap((void *)mmio_base, VIRTIO_MMIO_SIZE * VIRTIO_MAX_NR); - - if (mmio_base == RT_NULL) - { - return -RT_ERROR; - } -#endif - - for (i = 0; i < VIRTIO_MAX_NR; ++i, ++irq, mmio_base += VIRTIO_MMIO_SIZE) - { - mmio_config = (struct virtio_mmio_config *)mmio_base; - - if (mmio_config->magic != VIRTIO_MAGIC_VALUE || - mmio_config->version != RT_USING_VIRTIO_VERSION || - mmio_config->vendor_id != VIRTIO_VENDOR_ID) - { - continue; - } - - init_handler = virtio_device_init_handlers[mmio_config->device_id]; - - if (init_handler != RT_NULL) - { - init_handler((rt_ubase_t *)mmio_base, irq); - } - } - - return 0; -} -INIT_DEVICE_EXPORT(rt_virtio_devices_init); -#endif /* BSP_USING_VIRTIO */ diff --git a/bsp/qemu-virt64-riscv/driver/drv_virtio.h b/bsp/qemu-virt64-riscv/driver/drv_virtio.h deleted file mode 100644 index 954338a3864..00000000000 --- a/bsp/qemu-virt64-riscv/driver/drv_virtio.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-11-11 GuEe-GUI the first version - */ - -#ifndef __DRV_VIRTIO_H__ -#define __DRV_VIRTIO_H__ - -int rt_virtio_devices_init(void); - -#endif /* __DRV_VIRTIO_H__ */ diff --git a/bsp/qemu-virt64-riscv/driver/virt.h b/bsp/qemu-virt64-riscv/driver/virt.h deleted file mode 100644 index f059feb50e6..00000000000 --- a/bsp/qemu-virt64-riscv/driver/virt.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-02-17 GuEe-GUI the first version - */ - -#ifndef VIRT_H__ -#define VIRT_H__ - -#include - -#ifdef RT_USING_SMART -#include -#include - -#endif - -/* VirtIO */ -#define VIRTIO_MMIO_BASE 0x10001000 -#define VIRTIO_MMIO_SIZE 0x00001000 -#define VIRTIO_MAX_NR 8 -#define VIRTIO_IRQ_BASE 1 -#define VIRTIO_VENDOR_ID 0x554d4551 /* "QEMU" */ - -#define MAX_HANDLERS 128 -#endif diff --git a/bsp/qemu-virt64-riscv/link.lds b/bsp/qemu-virt64-riscv/link.lds deleted file mode 100644 index a76fed4fa30..00000000000 --- a/bsp/qemu-virt64-riscv/link.lds +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020/12/12 bernard The first version - */ - -INCLUDE "link_stacksize.lds" - -OUTPUT_ARCH( "riscv" ) - -/* - * Memory layout: - * 0x80000000 - 0x80200000: SBI - * 0x80200000 - 0x81200000: Kernel - */ - -MEMORY -{ - SRAM : ORIGIN = 0x80200000, LENGTH = 0x1000000 -} - -ENTRY(_start) -SECTIONS -{ - . = 0x80200000 ; - - /* __STACKSIZE__ = 4096; */ - __text_start = .; - .start : - { - *(.start); - } > SRAM - - . = ALIGN(8); - - .text : - { - *(.text) /* remaining code */ - *(.text.*) /* remaining code */ - *(.rodata) /* read-only data (constants) */ - *(.rodata*) - *(.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 = .; - } > SRAM - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - *(.eh_frame_entry) - } > SRAM - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > SRAM - - . = ALIGN(8); - __text_end = .; - __text_size = __text_end - __text_start; - - .data : - { - *(.data) - *(.data.*) - - *(.data1) - *(.data1.*) - - . = ALIGN(8); - PROVIDE( __global_pointer$ = . + 0x800 ); - - *(.sdata) - *(.sdata.*) - } > SRAM - - . = ALIGN(8); - .ctors : - { - PROVIDE(__ctors_start__ = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__ctors_end__ = .); - } > SRAM - - .dtors : - { - PROVIDE(__dtors_start__ = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE(__dtors_end__ = .); - } > SRAM - - /* stack for dual core */ - .stack : - { - . = ALIGN(64); - __stack_start__ = .; - - . += __STACKSIZE__; - __stack_cpu0 = .; - - . += __STACKSIZE__; - __stack_cpu1 = .; - } > SRAM - - .sbss : - { - __bss_start = .; - *(.sbss) - *(.sbss.*) - *(.dynsbss) - *(.scommon) - } > SRAM - - .bss : - { - *(.bss) - *(.bss.*) - *(.dynbss) - *(COMMON) - __bss_end = .; - } > SRAM - - _end = .; - - /* Stabs debugging sections. */ - .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. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .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) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} diff --git a/bsp/qemu-virt64-riscv/link_smart.lds b/bsp/qemu-virt64-riscv/link_smart.lds deleted file mode 100644 index ddf596630ed..00000000000 --- a/bsp/qemu-virt64-riscv/link_smart.lds +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2020/12/12 bernard The first version - */ - -INCLUDE "link_stacksize.lds" - -OUTPUT_ARCH( "riscv" ) - -/* - * Memory layout: - * 0x80000000 - 0x80200000: SBI - * 0x80200000 - 0x81200000: Kernel - */ - -MEMORY -{ - SRAM : ORIGIN = 0xFFFFFFC000200000, LENGTH = 0x1000000 - 0x200000 -} - -ENTRY(_start) -SECTIONS -{ - /* . = 0x80200000 ; */ - . = 0xFFFFFFC000200000; - - /* __STACKSIZE__ = 4096; */ - __text_start = .; - .start : - { - *(.start); - } > SRAM - - . = ALIGN(8); - - .text : - { - *(.text) /* remaining code */ - *(.text.*) /* remaining code */ - *(.rodata) /* read-only data (constants) */ - *(.rodata*) - *(.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 = .; - } > SRAM - - .eh_frame_hdr : - { - *(.eh_frame_hdr) - *(.eh_frame_entry) - } > SRAM - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > SRAM - - . = ALIGN(8); - __text_end = .; - __text_size = __text_end - __text_start; - - .data : - { - *(.data) - *(.data.*) - - *(.data1) - *(.data1.*) - - . = ALIGN(8); - PROVIDE( __global_pointer$ = . + 0x800 ); - - *(.sdata) - *(.sdata.*) - } > SRAM - - . = ALIGN(8); - .ctors : - { - PROVIDE(__ctors_start__ = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE(__ctors_end__ = .); - } > SRAM - - .dtors : - { - PROVIDE(__dtors_start__ = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE(__dtors_end__ = .); - } > SRAM - - /* stack for dual core */ - .stack : - { - . = ALIGN(64); - __stack_start__ = .; - - . += __STACKSIZE__; - __stack_cpu0 = .; - - . += __STACKSIZE__; - __stack_cpu1 = .; - } > SRAM - - .sbss : - { - __bss_start = .; - *(.sbss) - *(.sbss.*) - *(.dynsbss) - *(.scommon) - } > SRAM - - .bss : - { - *(.bss) - *(.bss.*) - *(.dynbss) - *(COMMON) - __bss_end = .; - } > SRAM - - _end = .; - - /* Stabs debugging sections. */ - .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. - * Symbols in the DWARF debugging sections are relative to the beginning - * of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .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) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } -} diff --git a/bsp/qemu-virt64-riscv/link_stacksize.lds b/bsp/qemu-virt64-riscv/link_stacksize.lds deleted file mode 100644 index 14c2aad91f8..00000000000 --- a/bsp/qemu-virt64-riscv/link_stacksize.lds +++ /dev/null @@ -1 +0,0 @@ -__STACKSIZE__ = 16384; diff --git a/bsp/qemu-virt64-riscv/qemu-dbg.sh b/bsp/qemu-virt64-riscv/qemu-dbg.sh deleted file mode 100755 index a7958ef8e88..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-dbg.sh +++ /dev/null @@ -1,4 +0,0 @@ -qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin -s -S \ --drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \ --netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \ --device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0 diff --git a/bsp/qemu-virt64-riscv/qemu-dumpdtb.sh b/bsp/qemu-virt64-riscv/qemu-dumpdtb.sh deleted file mode 100755 index 12068b571a9..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-dumpdtb.sh +++ /dev/null @@ -1 +0,0 @@ -qemu-system-riscv64 -nographic -machine virt,dumpdtb=virt.dtb -m 256M -kernel rtthread.bin diff --git a/bsp/qemu-virt64-riscv/qemu-nographic.bat b/bsp/qemu-virt64-riscv/qemu-nographic.bat deleted file mode 100644 index df55b35e84f..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-nographic.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off -if exist sd.bin goto run -qemu-img create -f raw sd.bin 64M - -:run -qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin ^ --drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 ^ --netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 ^ --device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0 diff --git a/bsp/qemu-virt64-riscv/qemu-rv64ilp32-nographic.sh b/bsp/qemu-virt64-riscv/qemu-rv64ilp32-nographic.sh deleted file mode 100755 index 798cb9d3d70..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-rv64ilp32-nographic.sh +++ /dev/null @@ -1 +0,0 @@ -qemu-system-riscv64ilp32 -cpu rv64 -M virt -m 256M -nographic -kernel rtthread.elf diff --git a/bsp/qemu-virt64-riscv/qemu-v-dbg.sh b/bsp/qemu-virt64-riscv/qemu-v-dbg.sh deleted file mode 100644 index d22af856cbf..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-v-dbg.sh +++ /dev/null @@ -1,4 +0,0 @@ -qemu-system-riscv64 -nographic -machine virt -cpu rv64,v=true,vlen=128,vext_spec=v1.0 -m 256M -kernel rtthread.bin \ --drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \ --netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 -s -S \ --device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0 diff --git a/bsp/qemu-virt64-riscv/qemu-v-nographic.sh b/bsp/qemu-virt64-riscv/qemu-v-nographic.sh deleted file mode 100644 index 068ff4fa6c3..00000000000 --- a/bsp/qemu-virt64-riscv/qemu-v-nographic.sh +++ /dev/null @@ -1,9 +0,0 @@ -if [ ! -f "sd.bin" ]; then -dd if=/dev/zero of=sd.bin bs=1024 count=65536 -mkfs.fat sd.bin -fi - -qemu-system-riscv64 -nographic -machine virt -cpu rv64,v=true,vlen=128,vext_spec=v1.0 -m 256M -kernel rtthread.bin \ --drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \ --netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \ --device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0 diff --git a/bsp/qemu-virt64-riscv/qemu.py b/bsp/qemu-virt64-riscv/qemu.py new file mode 100755 index 00000000000..d10530338b4 --- /dev/null +++ b/bsp/qemu-virt64-riscv/qemu.py @@ -0,0 +1,242 @@ +#!/bin/python +# -*- coding: utf-8 -*- +import os, sys, re, shutil + +with open('rtconfig.h', 'r') as file: + rtconfig_header = file.read() + +if os.getenv('RTT_QEMU_ROOT'): + RTT_QEMU_ROOT = os.getenv('RTT_QEMU_ROOT') +else: + RTT_QEMU_ROOT = "" + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = os.path.join(os.getcwd(), '..', '..') + +# WSL? +is_windows = sys.platform.startswith('win') or \ + os.popen('which qemu-system-riscv64 | xargs file').read().find('PE') >= 0 or \ + (os.system("readlink `which qemu-system-riscv64` > /dev/null") == 0 and \ + os.popen('readlink `which qemu-system-riscv64` | xargs file').read().find('PE') >= 0) + +class QEMU_VERSION: + def __init__(self): + cmd = os.popen(RTT_QEMU_ROOT + "qemu-system-riscv64 --version").readlines()[0] + version = cmd[cmd.find("version ") + 8: -1].split('.') + + self.major = version[0] + self.minor = version[1] + self.revision = version[2] + # == + def __eq__(self, version_in): + version = version_in.split('.') + return self.major == version[0] and self.minor == version[1] and self.revision == version[2] + # >= + def __ge__(self, version_in): + return self.__gt__(version_in) or self.__eq__(version_in) + # > + def __gt__(self, version_in): + version = version_in.split('.') + return self.major > version[0] or \ + (self.major == version[0] and self.minor > version[1]) or \ + (self.major == version[0] and self.minor == version[1] and self.revision > version[2]) + # <= + def __le__(self, version_in): + return self.__lt__(version_in) or self.__eq__(version_in) + # < + def __lt__(self, version_in): + return not self.__ge__(version_in) + # != + def __ne__(self, version_in): + return not self.__eq__(version_in) + +qemu_version = QEMU_VERSION() + +opt = sys.argv + +graphic_cfg = """ \ + -device ramfb \ + -device virtio-keyboard-device \ + -device virtio-tablet-device \ +""" + +cdrom_cfg = "" +virtfs_cfg = "" +ufs_cfg = "" + +q_msi = "aia=aplic-imsic" +q_v = "" +q_prefix = "riscv64" +q_dumpdtb = "" +q_smp = int(re.findall(r'#define\s+RT_CPUS_NR\s+(\d+)', rtconfig_header)[0]) +q_mem = 128 +q_graphic = "-nographic" +q_debug = "" +q_bootargs = "console=ttyS0 earlycon=sbi cma=8M coherent_pool=2M root=vda0 rootfstype=elm rootwait rw" +q_initrd = "" +q_block = "virtio" +q_net = "user" +q_ssh = 12055 +q_flash = "flash" +q_sound = "hda" +q_gl = None +q_9p = "" + +def is_opt(key, inkey): + if str("-" + key) == inkey: + return True + return False + +for i in range(len(opt)): + if i == 0: + continue + inkey = opt[i] + + if is_opt("no-msi", inkey): q_msi = "aia=none" + if is_opt("v", inkey): q_v = ",v=true,vlen=128,vext_spec=v1.0" + if is_opt("rv64ilp32", inkey): q_prefix = "rv64ilp32" + if is_opt("dumpdtb", inkey): q_dumpdtb = str(",dumpdtb=" + opt[i + 1]) + if is_opt("smp", inkey): q_smp = int(opt[i + 1]) + if is_opt("mem", inkey): q_mem = int(opt[i + 1]) + if is_opt("debug", inkey): q_debug = "-S -s" + if is_opt("bootargs", inkey): q_bootargs = opt[i + 1] + if is_opt("initrd", inkey): q_initrd = str("-initrd " + opt[i + 1]) + if is_opt("graphic", inkey): q_graphic = graphic_cfg + if is_opt("virtio-block", inkey): q_block = opt[i + 1] + if is_opt("tap", inkey): q_net = "tap,ifname=tap0" + if is_opt("ssh", inkey): q_ssh = int(opt[i + 1]) + if is_opt("flash", inkey): q_flash = opt[i + 1] + if is_opt("sound", inkey): q_sound = opt[i + 1] + if is_opt("gl", inkey): q_gl = "-device virtio-gpu-gl-pci -display {},gl=on ".format(opt[i + 1]) + if is_opt("9p", inkey): q_9p = opt[i + 1] + +# Display +# --enable-opengl --enable-virglrenderer +if q_graphic != "-nographic": + if q_gl: + q_graphic += q_gl + else: + q_graphic += "-device virtio-gpu-device" +elif q_gl != None: + print("Error: GL should in graphic mode") + exit(-1) + +# Sound +if q_sound == "hda": + q_sound = "-device intel-hda -device hda-duplex " +elif q_sound == "virtio": + if qemu_version < '8.2.0': + print("Error: VirtIO Sound is not in this version: {}".format(qemu_version)) + exit(-1) + q_sound = "-device virtio-sound-pci,audiodev=vsnd -audiodev alsa,id=vsnd " +else: + print("Error: Invalid -sound {}".format(q_sound)) + exit(-1) + +# Net +# --enable-slirp +# Enable TAP in example (not support in Windows, Maybe WSL2): +# ETH0=`/sbin/route -n | awk '$1 == "0.0.0.0" {print $NF}'` +# ip link add br0 type bridge +# ip link set br0 up +# echo 1 | tee /proc/sys/net/ipv4/ip_forward > /dev/null +# ip link set ${ETH0} up +# ip link set ${ETH0} master br0 +# dhclient br0 +# ip tuntap add dev tap0 mode tap +# ip link set dev tap0 up +# ip link set tap0 master br0 +# +# Disable TAP in example (not support in Windows, Maybe WSL2): +# ip link set tap0 down +# ip tuntap del dev tap0 mod tap +# echo 0 | tee /proc/sys/net/ipv4/ip_forward > /dev/null +# ip link set br0 down +# ip link del br0 type bridge +if q_net.find("user") >= 0: + q_net += ",hostfwd=tcp::{}-:22".format(q_ssh) +else: + if not is_windows: + q_net += ",script=no,downscript=no" + print("Warning: SSH not set in TAP") + +# Storage +# pflash have pflash0 and pflash1, pflash0 is used for BootROMs such as UEFI +# if we load file to pflash0, QEMU will boot from it, so we only use pflash1. +# Well, we can R/W in pflash0 by CFI driver, but the data will lost after QEMU exits. +# +# partitions (not support in Windows, Maybe WSL2): +# modprobe nbd max_part=12 +# qemu-nbd --connect=/dev/nbdX ABC.qcow2 +# fdisk /dev/nbdX +# ... +# qemu-nbd --disconnect /dev/nbdX +disk_list = [q_block, q_flash] + +for disk in disk_list: + size = 64 + if disk == q_flash: + size = 32 + disk += ".qcow2" + if not os.path.exists(disk): + os.system("qemu-img create -f qcow2 {} {}M".format(disk, size)) + +# Share File System +# --enable-virtfs +if len(q_9p) > 0: + p9_tag = "hostshare" + virtfs_cfg = """ \ + -fsdev local,security_model=passthrough,id=fsdev0,path={} \ + -device virtio-9p-device,fsdev=fsdev0,mount_tag={} \ + """.format(q_9p, p9_tag) + q_bootargs += " 9p.tag={} 9p.mount=host".format(p9_tag) + +# Note +# Hot-plug / Hot-unplug in QEMU monitor: +# (qemu) chardev-add socket,host=127.0.0.1,port=4323,server=on,wait=off,telnet=on,id=console2 +# (qemu) device_add virtserialport,chardev=console2,name=org.rt-thread.port,id=port2 +# (qemu) device_del port2 +# (qemu) chardev-remove console2 +# +# VirtIO version disable legacy to set version >= 1.0: +# -global virtio-mmio.force-legacy=false +# +# VirtIO used virtqueue packed (version >= 1.0) +# -device virtio-XYZ-device,packed=on +# +# VirtIO used PCI/PCIe bus (version >= 1.0) +# -device virtio-XYZ-pci,disable-legacy=on + +os.system(""" +{}qemu-system-{} \ + -M virt,acpi=on,aclint=on,{}{}{} \ + -cpu max \ + -smp {} \ + -m {} \ + -kernel rtthread.bin \ + -append "{}" \ + {} \ + -serial mon:stdio \ + {} \ + {} \ + -drive if=none,file={}.qcow2,format=qcow2,id=blk0 \ + -device virtio-blk-device,drive=blk0 \ + -netdev {},id=net0 \ + -device virtio-net-device,netdev=net0,speed=800000 \ + -device virtio-rng-device \ + {} \ + -device virtio-crypto-device,cryptodev=vcrypto0 \ + -object cryptodev-backend-builtin,id=vcrypto0 \ + -device virtio-serial-device \ + -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 \ + -device virtserialport,chardev=console0,name=org.rt-thread.console \ + {} \ + -drive if=pflash,file={}.qcow2,format=qcow2,index=1 \ + -device pci-serial,chardev=console1 \ + -chardev socket,host=127.0.0.1,port=4322,server=on,wait=off,telnet=on,id=console1 \ + -device i6300esb -watchdog-action reset \ + -device edu,dma_mask=0xffffffff +""".format(RTT_QEMU_ROOT, q_prefix, q_msi, q_v, q_dumpdtb, q_smp, q_mem, q_bootargs, q_initrd, + q_graphic, q_debug, q_block, q_net, virtfs_cfg, q_sound, q_flash)) diff --git a/bsp/qemu-virt64-riscv/rtconfig.h b/bsp/qemu-virt64-riscv/rtconfig.h index 221ee5eb9bc..764583b43a6 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.h +++ b/bsp/qemu-virt64-riscv/rtconfig.h @@ -8,16 +8,6 @@ /* rt_vsnprintf options */ #define RT_KLIBC_USING_VSNPRINTF_LONGLONG -#define RT_KLIBC_USING_VSNPRINTF_STANDARD -#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS -#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS -#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER -#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER -#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32 -#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32 -#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6 -#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9 -#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4 /* end of rt_vsnprintf options */ /* rt_vsscanf options */ @@ -73,7 +63,9 @@ /* end of rt_strnlen options */ /* end of klibc options */ #define RT_NAME_MAX 24 -#define RT_CPUS_NR 1 +#define RT_USING_SMART +#define RT_USING_SMP +#define RT_CPUS_NR 4 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 @@ -84,6 +76,7 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 16384 +#define SYSTEM_THREAD_STACK_SIZE 16384 #define RT_USING_TIMER_SOFT #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 16384 @@ -96,6 +89,7 @@ #define RT_DEBUGING_ASSERT #define RT_DEBUGING_COLOR #define RT_DEBUGING_CONTEXT +#define RT_DEBUGING_CRITICAL /* Inter-Thread communication */ @@ -109,7 +103,6 @@ /* Memory Management */ -#define RT_PAGE_MAX_ORDER 11 #define RT_USING_MEMPOOL #define RT_USING_SLAB #define RT_USING_SLAB_AS_HEAP @@ -118,21 +111,33 @@ /* end of Memory Management */ #define RT_USING_DEVICE #define RT_USING_DEVICE_OPS +#define RT_USING_INTERRUPT_INFO #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" -#define RT_VER_NUM 0x50200 +#define RT_VER_NUM 0x50201 #define RT_USING_STDC_ATOMIC #define RT_BACKTRACE_LEVEL_MAX_NR 32 /* end of RT-Thread Kernel */ +#define ARCH_TEXT_OFFSET 0x80200000 +#define ARCH_RAM_OFFSET 0 +#define ARCH_SECONDARY_CPU_STACK_SIZE 4096 +#define ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS +#define ARCH_HEAP_SIZE 0x4000000 +#define ARCH_INIT_PAGE_SIZE 0x200000 + +/* RISC-V Architecture Configuration */ + +#define ARCH_RISCV_FPU +#define ARCH_USING_NEW_CTX_SWITCH +#define ARCH_USING_RISCV_COMMON64 +/* end of RISC-V Architecture Configuration */ #define ARCH_CPU_64BIT #define RT_USING_CACHE +#define RT_USING_CPU_FFS #define ARCH_MM_MMU +#define KERNEL_VADDR_START 0xfff0000000000000 #define ARCH_RISCV -#define ARCH_RISCV_FPU -#define ARCH_RISCV64 -#define ARCH_USING_NEW_CTX_SWITCH -#define ARCH_USING_RISCV_COMMON64 #define ARCH_REMAP_KERNEL /* RT-Thread Components */ @@ -174,17 +179,30 @@ #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_DRIVES 8 #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_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_DM #define RT_USING_DEVICE_IPC #define RT_UNAMED_PIPE_NUMBER 64 #define RT_USING_SYSTEM_WORKQUEUE @@ -194,24 +212,147 @@ #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_SERIAL_BYPASS +#define RT_SERIAL_8250 +#define RT_SERIAL_EARLY_SBI #define RT_USING_CPUTIME #define RT_USING_CPUTIME_RISCV #define CPUTIME_TIMER_FREQ 10000000 #define RT_USING_NULL #define RT_USING_ZERO #define RT_USING_RANDOM +#define RT_USING_MTD_NOR +#define RT_USING_MTD_NOR_CFI +#define RT_USING_PM +#define PM_TICKLESS_THRESHOLD_TIME 2 #define RT_USING_RTC -#define RT_USING_SOFT_RTC +#define RT_USING_ALARM +#define RT_ALARM_STACK_SIZE 16384 +#define RT_ALARM_TIMESLICE 5 +#define RT_ALARM_PRIORITY 10 +#define RT_RTC_GOLDFISH +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 16384 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 16384 +#define RT_MMCSD_THREAD_PRIORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +#define RT_USING_SDHCI +#define RT_SDIO_SDHCI_PCI +#define RT_USING_WDT +#define RT_WDT_I6300ESB +#define RT_USING_AUDIO +#define RT_AUDIO_REPLAY_MP_BLOCK_SIZE 4096 +#define RT_AUDIO_REPLAY_MP_BLOCK_COUNT 2 +#define RT_AUDIO_RECORD_PIPE_SIZE 2048 +#define RT_AUDIO_INTEL_HDA +#define RT_USING_TOUCH +#define RT_USING_LCD +#define RT_USING_GRAPHIC +#define RT_GRAPHIC_FB +#define RT_GRAPHIC_LOGO +#define RT_GRAPHIC_LOGO_RT_THREAD_CLUT224 +#define RT_USING_HWCRYPTO +#define RT_HWCRYPTO_DEFAULT_NAME "hwcryto" +#define RT_HWCRYPTO_IV_MAX_SIZE 16 +#define RT_HWCRYPTO_KEYBIT_MAX_SIZE 256 +#define RT_HWCRYPTO_USING_AES +#define RT_HWCRYPTO_USING_AES_ECB +#define RT_HWCRYPTO_USING_AES_CBC +#define RT_HWCRYPTO_USING_AES_CTR +#define RT_HWCRYPTO_USING_DES +#define RT_HWCRYPTO_USING_DES_ECB +#define RT_HWCRYPTO_USING_DES_CBC +#define RT_HWCRYPTO_USING_3DES +#define RT_HWCRYPTO_USING_3DES_ECB +#define RT_HWCRYPTO_USING_3DES_CBC +#define RT_HWCRYPTO_USING_RC4 +#define RT_HWCRYPTO_USING_RNG +#define RT_USING_ETHERNET +#define RT_USING_INPUT +#define RT_INPUT_POWER +#define RT_INPUT_TOUCHSCREEN +#define RT_USING_MBOX +#define RT_MBOX_PIC +#define RT_USING_RPMSG +#define RT_RPMSG_CHAR_MSG_MAX 64 +#define RT_RPMSG_CHAR_MSG_SIZE_MAX 256 +#define RT_USING_ATA +#define RT_ATA_AHCI +#define RT_USING_NVME +#define RT_USING_NVME_IO_QUEUE 4 +#define RT_NVME_PCI +#define RT_USING_BLK + +/* Partition Types */ + +#define RT_BLK_PARTITION_DFS +#define RT_BLK_PARTITION_EFI +/* end of Partition Types */ +#define RT_USING_SCSI +#define RT_SCSI_SD +#define RT_SCSI_CDROM +#define RT_USING_FIRMWARE +#define RT_FIRMWARE_QEMU_FW_CFG +#define RT_USING_REGULATOR +#define RT_USING_RESET + +/* Power Management (PM) Domains device drivers */ + +/* end of Power Management (PM) Domains device drivers */ +#define RT_USING_POWER_RESET +#define RT_POWER_RESET_SYSCON_POWEROFF +#define RT_POWER_RESET_SYSCON_REBOOT +#define RT_USING_THERMAL + +/* Thermal Sensors Drivers */ + +/* Thermal Cool Drivers */ + #define RT_USING_VIRTIO -#define RT_USING_VIRTIO10 -#define RT_USING_VIRTIO_BLK -#define RT_USING_VIRTIO_NET -#define RT_USING_VIRTIO_CONSOLE -#define RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR 4 -#define RT_USING_VIRTIO_GPU -#define RT_USING_VIRTIO_INPUT -#define RT_USING_PIN +#define RT_VIRTIO_TRANSPORT_MMIO +#define RT_VIRTIO_TRANSPORT_PCI +#define RT_VIRTIO_NET +#define RT_VIRTIO_BLK +#define RT_VIRTIO_CONSOLE +#define RT_VIRTIO_RNG +#define RT_VIRTIO_RPMSG +#define RT_VIRTIO_SCSI +#define RT_VIRTIO_RPROC_SERIAL +#define RT_VIRTIO_GPU +#define RT_VIRTIO_INPUT +#define RT_VIRTIO_CRYPTO +#define RT_VIRTIO_SOUND +#define RT_USING_DMA +#define RT_USING_MFD +#define RT_MFD_EDU +#define RT_MFD_SYSCON +#define RT_USING_IVSHMEM +#define RT_IVSHMEM_QEMU +#define RT_USING_OFW +#define RT_FDT_EARLYCON_MSG_SIZE 128 +#define RT_USING_OFW_BUS_RANGES_NUMBER 8 +#define RT_USING_PCI +#define RT_PCI_MSI +#define RT_PCI_SYS_64BIT +#define RT_PCI_CACHE_LINE_SIZE 8 + +/* PCI Device Drivers */ + +#define RT_PCI_ECAM +#define RT_PCI_HOST_COMMON +#define RT_PCI_HOST_GENERIC +#define RT_USING_PIC +#define MAX_HANDLERS 512 +#define RT_PIC_RISCV_AIA +#define RT_PIC_RISCV_INTC +#define RT_PIC_SIFIVE_PLIC #define RT_USING_KTIME +#define RT_USING_CLK +#define RT_USING_HWTIMER + +/* SoC (System on Chip) Drivers */ + /* end of Device Drivers */ /* C/C++ and POSIX layer */ @@ -234,6 +375,9 @@ #define RT_USING_POSIX_STDIO #define RT_USING_POSIX_POLL #define RT_USING_POSIX_SELECT +#define RT_USING_POSIX_EPOLL +#define RT_USING_POSIX_SIGNALFD +#define RT_SIGNALFD_MAX_NUM 10 #define RT_USING_POSIX_TERMIOS #define RT_USING_POSIX_AIO #define RT_USING_POSIX_DELAY @@ -320,9 +464,6 @@ /* Utilities */ -#define RT_USING_UTEST -#define UTEST_THR_STACK_SIZE 4096 -#define UTEST_THR_PRIORITY 20 #define RT_USING_RESOURCE_ID #define RT_USING_ADT #define RT_USING_ADT_AVL @@ -331,6 +472,29 @@ #define RT_USING_ADT_REF /* end of Utilities */ +/* Memory management */ + +#define RT_PAGE_MPR_SIZE_DYNAMIC +#define RT_PAGE_AFFINITY_BLOCK_SIZE 0x1000 +#define RT_PAGE_MAX_ORDER 11 +#define RT_USING_MEMBLOCK +#define RT_INIT_MEMORY_REGIONS 128 + +/* 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 64 + /* Using USB legacy version */ /* end of Using USB legacy version */ @@ -437,6 +601,14 @@ /* Kendryte SDK */ /* end of Kendryte SDK */ + +/* WCH HAL & SDK Drivers */ + +/* end of WCH HAL & SDK Drivers */ + +/* AT32 HAL & SDK Drivers */ + +/* end of AT32 HAL & SDK Drivers */ /* end of HAL & SDK Drivers */ /* sensors drivers */ @@ -516,18 +688,6 @@ /* end of Arduino libraries */ /* end of RT-Thread online packages */ - -/* RISC-V QEMU virt64 configs */ - -#define BSP_USING_VIRTIO -#define BSP_USING_VIRTIO_BLK -#define BSP_USING_VIRTIO_NET -#define BSP_USING_VIRTIO_CONSOLE -#define BSP_USING_VIRTIO_GPU -#define BSP_USING_VIRTIO_INPUT -/* end of RISC-V QEMU virt64 configs */ -#define BOARD_QEMU_VIRT_RV64 -#define ENABLE_FPU -#define __STACKSIZE__ 16384 +#define SOC_VIRT64_RISCV64 #endif diff --git a/bsp/qemu-virt64-riscv/rtconfig.py b/bsp/qemu-virt64-riscv/rtconfig.py index 09d530af4a1..e5ce51045ae 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.py +++ b/bsp/qemu-virt64-riscv/rtconfig.py @@ -2,7 +2,7 @@ # toolchains options ARCH ='risc-v' -CPU ='virt64' +CPU ='' CROSS_TOOL ='gcc' RTT_ROOT = os.getenv('RTT_ROOT') or os.path.join(os.getcwd(), '..', '..') @@ -24,6 +24,7 @@ PREFIX = os.getenv('RTT_CC_PREFIX') or 'riscv64-unknown-elf-' CC = PREFIX + 'gcc' CXX = PREFIX + 'g++' + CPP = PREFIX + 'cpp' AS = PREFIX + 'gcc' AR = PREFIX + 'ar' LINK = PREFIX + 'gcc' @@ -33,6 +34,7 @@ OBJCPY = PREFIX + 'objcopy' DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64 ' + CPPFLAGS= ' -nostdinc -undef -E -P -x assembler-with-cpp' CFLAGS = DEVICE + '-ffreestanding -flax-vector-conversions -Wno-cpp -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -fdiagnostics-color=always' AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ ' LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,_start -T link.lds' + ' -lsupc++ -lgcc -static' diff --git a/bsp/qemu-virt64-riscv/run.sh b/bsp/qemu-virt64-riscv/run.sh deleted file mode 100755 index dd53c95f612..00000000000 --- a/bsp/qemu-virt64-riscv/run.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -usage () -{ - echo "Usage:" - echo "./run.sh []" - echo "Note: if is not provided, will create a 'sd.bin'" - echo "in the current directory and load it by default." -} - -path_image=${1} - -if [ -z $path_image ]; then - path_image="./sd.bin" - if [ ! -f $path_image ]; then - dd if=/dev/zero of=$path_image bs=1024 count=65536 - mkfs.fat $path_image - fi -fi - -if [ ! -f $path_image ]; then - echo "ERROR: $path_image does not exist!" - usage - exit -fi - -qemu-system-riscv64 -nographic -machine virt -m 256M -kernel rtthread.bin \ --drive if=none,file=$path_image,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \ --netdev user,id=tap0 -device virtio-net-device,netdev=tap0,bus=virtio-mmio-bus.1 \ --device virtio-serial-device -chardev socket,host=127.0.0.1,port=4321,server=on,wait=off,telnet=on,id=console0 -device virtserialport,chardev=console0 diff --git a/components/drivers/cputime/Kconfig b/components/drivers/cputime/Kconfig index 97c2c462593..d86ef547f77 100644 --- a/components/drivers/cputime/Kconfig +++ b/components/drivers/cputime/Kconfig @@ -1,4 +1,4 @@ -config RT_USING_CPUTIME +menuconfig RT_USING_CPUTIME bool "Enable CPU time for high resolution clock counter" default n help @@ -25,9 +25,9 @@ if RT_USING_CPUTIME config RT_USING_CPUTIME_RISCV bool "Use rdtime instructions for CPU time" default y - depends on ARCH_RISCV64 + depends on ARCH_RISCV help - Some RISCV64 MCU Use rdtime instructions read CPU time. + Some RISC-V MCU Use rdtime instructions read CPU time. config CPUTIME_TIMER_FREQ int "CPUTIME timer freq" default 0 diff --git a/components/drivers/cputime/cputime_riscv.c b/components/drivers/cputime/cputime_riscv.c index 597157c226e..ef2354c032f 100644 --- a/components/drivers/cputime/cputime_riscv.c +++ b/components/drivers/cputime/cputime_riscv.c @@ -3,6 +3,7 @@ #include #include +#include /* Use Cycle counter of Data Watchpoint and Trace Register for CPU time */ @@ -10,17 +11,13 @@ static uint64_t riscv_cputime_getres(void) { uint64_t ret = 1000UL * 1000 * 1000; - ret = (ret * (1000UL * 1000)) / CPUTIME_TIMER_FREQ; + ret = (ret * (1000UL * 1000)) / riscv_timer_get_frequency(); return ret; } static uint64_t riscv_cputime_gettime(void) { - uint64_t time_elapsed; - __asm__ __volatile__( - "rdtime %0" - : "=r"(time_elapsed)); - return time_elapsed; + return riscv_timer_rdtime(); } const static struct rt_clock_cputime_ops _riscv_ops = diff --git a/components/drivers/ktime/src/risc-v/virt64/cputimer.c b/components/drivers/ktime/src/risc-v/cputimer.c similarity index 59% rename from components/drivers/ktime/src/risc-v/virt64/cputimer.c rename to components/drivers/ktime/src/risc-v/cputimer.c index 85c9c00f492..0ec1f7d4b9b 100644 --- a/components/drivers/ktime/src/risc-v/virt64/cputimer.c +++ b/components/drivers/ktime/src/risc-v/cputimer.c @@ -1,32 +1,32 @@ /* - * Copyright (c) 2006-2023, RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-07-10 xqyjlj The first version. + * 2025-04-20 GuEe-GUI Port to the DM */ #include "ktime.h" +#include "riscv_timer.h" static volatile unsigned long _init_cnt = 0; rt_uint64_t rt_ktime_cputimer_getres(void) { - return ((1000ULL * 1000 * 1000) * RT_KTIME_RESMUL) / CPUTIME_TIMER_FREQ; + return ((1000ULL * 1000 * 1000) * RT_KTIME_RESMUL) / riscv_timer_get_frequency(); } unsigned long rt_ktime_cputimer_getfrq(void) { - return CPUTIME_TIMER_FREQ; + return riscv_timer_get_frequency(); } unsigned long rt_ktime_cputimer_getcnt(void) { - unsigned long time_elapsed; - __asm__ __volatile__("rdtime %0" : "=r"(time_elapsed)); - return time_elapsed - _init_cnt; + return riscv_timer_rdtime() - _init_cnt; } unsigned long rt_ktime_cputimer_getstep(void) @@ -36,5 +36,5 @@ unsigned long rt_ktime_cputimer_getstep(void) void rt_ktime_cputimer_init(void) { - __asm__ __volatile__("rdtime %0" : "=r"(_init_cnt)); + _init_cnt = riscv_timer_rdtime(); } diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.c b/components/lwp/arch/risc-v/rv64/lwp_arch.c index 62383f91fa9..9fc4af6730c 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_arch.c +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.c @@ -34,9 +34,9 @@ #include #include -#include #include #include +#include extern rt_ubase_t MMUTable[]; @@ -113,7 +113,11 @@ int arch_user_space_init(struct rt_lwp *lwp) void *arch_kernel_mmu_table_get(void) { +#if defined(RT_USING_SMP) && RT_CPUS_NR > 1 + return (void *)((char *)MMUTable + rt_hw_cpu_id() * ARCH_PAGE_SIZE); +#else return (void *)((char *)MMUTable); +#endif } void arch_user_space_free(struct rt_lwp *lwp) @@ -166,13 +170,14 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack, RT_ASSERT(thread_sp != RT_NULL); struct rt_hw_stack_frame *syscall_frame; struct rt_hw_stack_frame *thread_frame; + struct rt_hw_switch_frame *frame; rt_uint8_t *stk; rt_uint8_t *syscall_stk; stk = (rt_uint8_t *)new_thread_stack; /* reserve syscall context, all the registers are copyed from parent */ - stk -= CTX_REG_NR * REGBYTES; + stk -= CTX_ALL_REG_NR * sizeof(void *); syscall_stk = stk; syscall_frame = (struct rt_hw_stack_frame *)stk; @@ -192,12 +197,17 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack, syscall_frame->tp = (rt_ubase_t)thread->thread_idr; #ifdef ARCH_USING_NEW_CTX_SWITCH - extern void *_rt_hw_stack_init(rt_ubase_t *sp, rt_ubase_t ra, rt_ubase_t sstatus); - rt_ubase_t sstatus = read_csr(sstatus) | SSTATUS_SPP; - sstatus &= ~SSTATUS_SIE; + RT_UNUSED(syscall_stk); + RT_UNUSED(thread_frame); + + frame = (struct rt_hw_switch_frame *)((rt_ubase_t)stk - sizeof(*frame)); + rt_memset(frame, 0, sizeof(*frame)); + + frame->regs[RT_HW_SWITCH_CONTEXT_RA] = (rt_ubase_t)exit; + frame->regs[RT_HW_SWITCH_CONTEXT_XSTATUS] = (csr_read(CSR_STATUS) | SR_PP) & ~SR_IE; /* compatible to RESTORE_CONTEXT */ - stk = (void *)_rt_hw_stack_init((rt_ubase_t *)stk, (rt_ubase_t)exit, sstatus); + stk = (void *)frame; #else /* build temp thread context */ stk -= sizeof(struct rt_hw_stack_frame); @@ -214,8 +224,8 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack, thread_frame->epc = (rt_ubase_t)exit; /* set old exception mode as supervisor, because in kernel */ - thread_frame->sstatus = read_csr(sstatus) | SSTATUS_SPP; - thread_frame->sstatus &= ~SSTATUS_SIE; /* must disable interrupt */ + thread_frame->xstatus = read_csr(CSR_STATUS) | SR_PP; + thread_frame->xstatus &= ~SR_IE; /* must disable interrupt */ /* set stack as syscall stack */ thread_frame->user_sp_exc_stack = (rt_ubase_t)syscall_stk; diff --git a/components/lwp/arch/risc-v/rv64/lwp_arch.h b/components/lwp/arch/risc-v/rv64/lwp_arch.h index f1d1176f5cb..53f6d47a1c0 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_arch.h +++ b/components/lwp/arch/risc-v/rv64/lwp_arch.h @@ -16,6 +16,8 @@ #ifdef ARCH_MM_MMU +#include + #ifdef ARCH_MM_MMU_32BIT_LIMIT #define USER_HEAP_VADDR 0xF0000000UL #define USER_HEAP_VEND 0xFE000000UL @@ -77,6 +79,6 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo, } #endif -#endif +#endif /* ARCH_MM_MMU */ #endif /*LWP_ARCH_H__*/ diff --git a/components/lwp/arch/risc-v/rv64/lwp_gcc.S b/components/lwp/arch/risc-v/rv64/lwp_gcc.S index c207285c6fa..efa92ecb06a 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_gcc.S +++ b/components/lwp/arch/risc-v/rv64/lwp_gcc.S @@ -19,10 +19,8 @@ #define __ASSEMBLY__ #endif /* __ASSEMBLY__ */ -#include "cpuport.h" -#include "encoding.h" -#include "stackframe.h" -#include "asm-generic.h" +#include "asm.h" +#include "csr.h" .section .text.lwp @@ -33,13 +31,13 @@ .type arch_start_umode, % function arch_start_umode: // load kstack for user process - csrw sscratch, a3 - li t0, SSTATUS_SPP | SSTATUS_SIE // set as user mode, close interrupt - csrc sstatus, t0 - li t0, SSTATUS_SPIE // enable interrupt when return to user mode - csrs sstatus, t0 + csrw CSR_SCRATCH, a3 + li t0, SR_PP | SR_IE // set as user mode, close interrupt + csrc CSR_STATUS, t0 + li t0, SR_PIE // enable interrupt when return to user mode + csrs CSR_STATUS, t0 - csrw sepc, a1 + csrw CSR_EPC, a1 mv sp, a2 sret//enter user mode @@ -49,12 +47,12 @@ arch_start_umode: .global arch_crt_start_umode .type arch_crt_start_umode, % function arch_crt_start_umode: - li t0, SSTATUS_SPP | SSTATUS_SIE // set as user mode, close interrupt - csrc sstatus, t0 - li t0, SSTATUS_SPIE // enable interrupt when return to user mode - csrs sstatus, t0 + li t0, SR_PP | SR_IE // set as user mode, close interrupt + csrc CSR_STATUS, t0 + li t0, SR_PIE // enable interrupt when return to user mode + csrs CSR_STATUS, t0 - csrw sepc, a1 + csrw CSR_EPC, a1 mv s0, a0 mv s1, a1 mv s2, a2 @@ -67,7 +65,7 @@ arch_crt_start_umode: mv ra, a0//return address mv a0, s0//args - csrw sscratch, s3 + csrw CSR_SCRATCH, s3 sret//enter user mode /** @@ -95,7 +93,7 @@ arch_ret_to_user: ret_to_user_exit: RESTORE_ALL - // `RESTORE_ALL` also reset sp to user sp, and setup sscratch + // `RESTORE_ALL` also reset sp to user sp, and setup xscratch sret /** @@ -103,18 +101,18 @@ ret_to_user_exit: * And handle pending signals; */ arch_signal_quit: - LOAD a0, FRAME_OFF_SP(sp) + REG_L a0, FRAME_OFF_SP(sp) call arch_signal_ucontext_restore /* reset kernel sp to the stack */ - addi sp, sp, CTX_REG_NR * REGBYTES - STORE sp, FRAME_OFF_SP(a0) + addi sp, sp, CTX_ALL_REG_NR * SZREG + REG_S sp, FRAME_OFF_SP(a0) /* return value is user sp */ mv sp, a0 /* restore user sp before enter trap */ - addi a0, sp, CTX_REG_NR * REGBYTES - csrw sscratch, a0 + addi a0, sp, CTX_ALL_REG_NR * SZREG + csrw CSR_SCRATCH, a0 RESTORE_ALL @@ -137,19 +135,19 @@ arch_thread_signal_enter: mv s2, a0 mv s1, a3 - LOAD t0, FRAME_OFF_SP(a2) + REG_L t0, FRAME_OFF_SP(a2) mv a3, t0 call arch_signal_ucontext_save /** restore kernel sp */ - addi sp, s3, CTX_REG_NR * REGBYTES + addi sp, s3, CTX_ALL_REG_NR * SZREG /** * set regiter RA to user signal handler - * set sp to user sp & save kernel sp in sscratch + * set sp to user sp & save kernel sp in xscratch */ mv ra, a0 - csrw sscratch, sp + csrw CSR_SCRATCH, sp mv sp, a0 /** @@ -161,13 +159,13 @@ arch_thread_signal_enter: 1: /* enter user mode and enable interrupt when return to user mode */ - li t0, SSTATUS_SPP - csrc sstatus, t0 - li t0, SSTATUS_SPIE - csrs sstatus, t0 + li t0, SR_PP + csrc CSR_STATUS, t0 + li t0, SR_PIE + csrs CSR_STATUS, t0 - /* sepc <- signal_handler */ - csrw sepc, s1 + /* xepc <- signal_handler */ + csrw CSR_EPC, s1 /* a0 <- signal id */ mv a0, s2 /* a1 <- siginfo */ @@ -176,7 +174,7 @@ arch_thread_signal_enter: mv a2, a1 /* restore user GP */ - LOAD gp, FRAME_OFF_GP(s3) + REG_L gp, FRAME_OFF_GP(s3) /** * handler(signo, psi, ucontext); @@ -229,12 +227,12 @@ arch_clone_exit: START_POINT(syscall_entry) #ifndef ARCH_USING_NEW_CTX_SWITCH //swap to thread kernel stack - csrr t0, sstatus + csrr t0, CSR_STATUS andi t0, t0, 0x100 beqz t0, __restore_sp_from_tcb -__restore_sp_from_sscratch: // from kernel - csrr t0, sscratch +__restore_sp_from_CSR_SCRATCH: // from kernel + csrr t0, CSR_SCRATCH j __move_stack_context __restore_sp_from_tcb: // from user @@ -245,14 +243,14 @@ __restore_sp_from_tcb: // from user __move_stack_context: mv t1, sp//src mv sp, t0//switch stack - addi sp, sp, -CTX_REG_NR * REGBYTES + addi sp, sp, -CTX_ALL_REG_NR * SZREG //copy context - li s0, CTX_REG_NR//cnt + li s0, CTX_ALL_REG_NR//cnt mv t2, sp//dst copy_context_loop: - LOAD t0, 0(t1) - STORE t0, 0(t2) + REG_L t0, 0(t1) + REG_S t0, 0(t2) addi s0, s0, -1 addi t1, t1, 8 addi t2, t2, 8 @@ -260,7 +258,7 @@ copy_context_loop: #endif /* ARCH_USING_NEW_CTX_SWITCH */ /* fetch SYSCALL ID */ - LOAD a7, 17 * REGBYTES(sp) + REG_L a7, 17 * SZREG(sp) addi a7, a7, -0xfe beqz a7, arch_signal_quit @@ -281,7 +279,7 @@ arch_syscall_exit: CLOSE_INTERRUPT #if defined(ARCH_MM_MMU) - LOAD s0, FRAME_OFF_SSTATUS(sp) + REG_L s0, FRAME_OFF_XSTATUS(sp) andi s0, s0, 0x100 bnez s0, dont_ret_to_user j arch_ret_to_user @@ -294,10 +292,10 @@ dont_ret_to_user: call lwp_user_setting_restore /* after restore the reg `tp`, need modify context */ - STORE tp, 4 * REGBYTES(sp) + REG_S tp, 4 * SZREG(sp) #endif //restore context RESTORE_ALL - csrw sscratch, zero + csrw CSR_SCRATCH, zero sret diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index f5435bcea51..6a18c7a6b9e 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -479,7 +479,7 @@ pid_t lwp_execve(char *filename, int debug, int argc, char **argv, char **envp) if (debug && rt_dbg_ops) { lwp->debug = debug; - rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)0); + rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)rt_hw_master_cpu_id()); } rt_thread_startup(thread); diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 6efc3a0e163..b14902378c0 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -3313,7 +3313,7 @@ rt_thread_t sys_thread_create(void *arg[]) if (lwp->debug) { - rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)0); + rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)rt_hw_master_cpu_id()); } LWP_LOCK(lwp); @@ -3426,7 +3426,7 @@ long _sys_clone(void *arg[]) if (lwp->debug) { - rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)0); + rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)rt_hw_master_cpu_id()); } LWP_LOCK(lwp); diff --git a/include/rthw.h b/include/rthw.h index 672e820918b..f0ffe5a1d3f 100644 --- a/include/rthw.h +++ b/include/rthw.h @@ -196,6 +196,10 @@ void rt_hw_us_delay(rt_uint32_t us); int rt_hw_cpu_id(void); +#ifndef rt_hw_master_cpu_id +#define rt_hw_master_cpu_id() 0 +#endif + #if defined(RT_USING_SMP) || defined(RT_USING_AMP) /** * ipi function diff --git a/libcpu/Kconfig b/libcpu/Kconfig index 1edace109a7..133f026cb89 100644 --- a/libcpu/Kconfig +++ b/libcpu/Kconfig @@ -2,6 +2,10 @@ if ARCH_ARMV8 && ARCH_CPU_64BIT orsource "./aarch64/Kconfig" endif +if ARCH_RISCV + orsource "./risc-v/Kconfig" +endif + config ARCH_CPU_64BIT bool @@ -195,7 +199,7 @@ config ARCH_ARMV8 select ARCH_ARM select ARCH_ARM_MMU select RT_USING_CPU_FFS - select ARCH_USING_ASID + select ARCH_USING_ASID if RT_USING_SMART select ARCH_USING_IRQ_CTX_LIST config ARCH_MIPS @@ -220,55 +224,8 @@ config ARCH_POWERPC config ARCH_RISCV bool - -config ARCH_RISCV_FPU - bool - -config ARCH_RISCV_VECTOR - bool - - if ARCH_RISCV_VECTOR - choice - prompt "RISCV Vector Vlen" - default ARCH_VECTOR_VLEN_128 - - config ARCH_VECTOR_VLEN_128 - bool "128" - config ARCH_VECTOR_VLEN_256 - bool "256" - endchoice - endif - -config ARCH_RISCV_FPU_S - select ARCH_RISCV_FPU - bool - -config ARCH_RISCV_FPU_D - select ARCH_RISCV_FPU - bool - -config ARCH_RISCV32 - select ARCH_RISCV - bool - -config ARCH_RISCV64 - select ARCH_RISCV - select ARCH_CPU_64BIT - bool - -if ARCH_RISCV64 - config ARCH_USING_NEW_CTX_SWITCH - bool - default y - - config ARCH_USING_RISCV_COMMON64 - bool - depends on ARCH_RISCV64 - select RT_USING_CPUTIME - select ARCH_USING_NEW_CTX_SWITCH - help - Using the common64 implementation under ./libcpu/risc-v -endif + select RT_USING_CPU_FFS + select RT_PAGE_MPR_SIZE_DYNAMIC if ARCH_MM_MMU config ARCH_REMAP_KERNEL bool diff --git a/libcpu/risc-v/.gitignore b/libcpu/risc-v/.gitignore new file mode 100755 index 00000000000..feb550d1903 --- /dev/null +++ b/libcpu/risc-v/.gitignore @@ -0,0 +1 @@ +link.lds diff --git a/libcpu/risc-v/Kconfig b/libcpu/risc-v/Kconfig new file mode 100644 index 00000000000..7a543be1437 --- /dev/null +++ b/libcpu/risc-v/Kconfig @@ -0,0 +1,91 @@ +menu "RISC-V Architecture Configuration" + config ARCH_TEXT_OFFSET + hex "Text offset" + default 0x200000 + help + We use the area as the DM ioremap address space in 32 bits RT-Thread: + [ARCH_TEXT_OFFSET - IOREMAP_SIZE, ARCH_TEXT_OFFSET) + So you SHOULD config the value bigger than this area. + The `IOREMAP_SIZE` is defined a default value in common/setup.c. + + config ARCH_RAM_OFFSET + hex "RAM offset" + default 0 + + config ARCH_SECONDARY_CPU_STACK_SIZE + int "Secondary CPU stack size" + default 4096 + + config ARCH_HAVE_EFFICIENT_UNALIGNED_ACCESS + bool + default y + + config ARCH_HEAP_SIZE + hex "Size of system heap" + default 0x4000000 + + config ARCH_INIT_PAGE_SIZE + hex "Size of init page region" + default 0x200000 + + config ARCH_RISCV_DISABLE_FENCE_I + bool + default n + + config ARCH_RISCV_DISABLE_SFENCE_VMA_ASID + bool + default n + + config ARCH_RISCV_M_MODE + bool + depends on !ARCH_MM_MMU + default n + + config ARCH_RISCV_32E + bool + depends on !ARCH_CPU_64BIT + depends on !ARCH_MM_MMU + depends on !RT_USING_DM + + config ARCH_RISCV_FPU + bool "Enable FPU" + default y + + config ARCH_RISCV_VECTOR + bool "Using RISC-V Vector Extension" + depends on !ARCH_RISCV_32E + + choice + prompt "Vector Registers Length in Bits" + depends on ARCH_RISCV_VECTOR + default ARCH_VECTOR_VLEN_128 + + config ARCH_VECTOR_VLEN_128 + bool "128" + config ARCH_VECTOR_VLEN_256 + bool "256" + endchoice + + config ARCH_RISCV_FPU_S + select ARCH_RISCV_FPU + bool + + config ARCH_RISCV_FPU_D + select ARCH_RISCV_FPU + bool + + config ARCH_USING_NEW_CTX_SWITCH + bool + depends on ARCH_CPU_64BIT + default y + + config ARCH_USING_RISCV_COMMON64 + bool + depends on ARCH_CPU_64BIT + select RT_USING_CPUTIME + select ARCH_USING_NEW_CTX_SWITCH + + config RT_USING_USERSPACE_32BIT_LIMIT + bool "Enable userspace 32bit limit" + default n +endmenu diff --git a/libcpu/risc-v/SConscript b/libcpu/risc-v/SConscript index ca5934b4f3f..ee856e92d6e 100644 --- a/libcpu/risc-v/SConscript +++ b/libcpu/risc-v/SConscript @@ -5,23 +5,38 @@ from building import * Import('rtconfig') -common64_arch = ['virt64', 'c906', 'c908'] cwd = GetCurrentDir() group = [] list = os.listdir(cwd) +bsp_path = Dir('#').abspath +vender_path = cwd -# add common code files -if rtconfig.CPU in common64_arch : - group += SConscript(os.path.join('common64', 'SConscript')) -else : - group += SConscript(os.path.join('common', 'SConscript')) +if not os.path.exists(bsp_path + "/link.lds"): + Env['LINKFLAGS'] = Env['LINKFLAGS'].replace('link.lds', cwd + "/link.lds") + Preprocessing("link.lds.S", ".lds", CPPPATH=[bsp_path, cwd + '/common/include']) + +# fix the linker with crtx.o +Env['LINKFLAGS'] += ' -nostartfiles' -group += SConscript(os.path.join('vector', 'SConscript')) +# add common code files +group += SConscript(os.path.join('common', 'SConscript')) # cpu porting code files -if 'VENDOR' in vars(rtconfig) and rtconfig.VENDOR != '': - group = group + SConscript(os.path.join(rtconfig.VENDOR, rtconfig.CPU, 'SConscript')) -elif rtconfig.CPU in list: +if 'VENDER' in vars(rtconfig) and rtconfig.VENDER != '': + group = group + SConscript(os.path.join(rtconfig.VENDER, rtconfig.CPU, 'SConscript')) + vender_path += rtconfig.VENDER + "/" + rtconfig.CPU +elif rtconfig.CPU != '': group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript')) + vender_path += rtconfig.CPU + +if os.path.exists(vender_path + "/mmu_vendor.h"): + Env['ASFLAGS'] += '-D__HAS_MMU_VENDOR__' + Env['CFLAGS'] += '-D__HAS_MMU_VENDOR__' + Env['CXXFLAGS'] += '-D__HAS_MMU_VENDOR__' + +if os.path.exists(vender_path + "/opcode_vendor.h"): + Env['ASFLAGS'] += '-D__HAS_OPCODE_VENDOR__' + Env['CFLAGS'] += '-D__HAS_OPCODE_VENDOR__' + Env['CXXFLAGS'] += '-D__HAS_OPCODE_VENDOR__' Return('group') diff --git a/libcpu/risc-v/common/README.md b/libcpu/risc-v/common/README.md new file mode 100644 index 00000000000..228394b3644 --- /dev/null +++ b/libcpu/risc-v/common/README.md @@ -0,0 +1,314 @@ +# Port to NOT DM + +## Cache + +Fill the cache CBOM block size in your BSP if supported ISA 'ZICBOM': + +```c +#include + +void rt_hw_cache_init(void) +{ + riscv_cache_set_cbom_block_size(<...>); +} +``` + +## CPU + +Fill the hartid map in your BSP if the hardid is not equal to the CPU id: + +```c +#include + +rt_ubase_t cpu_id_to_hartid_map[RT_CPUS_NR] = +{ + [...] +}; +``` + +## SMP + +Select your CPU ops in your BSP: + +```c +#include + +extern struct cpu_ops_t cpu_sbi_ops; +extern struct cpu_ops_t cpu_spinwait_ops; +[...] + +void rt_hw_secondary_cpu_up(void) +{ + int cpu_id; + rt_ubase_t entry; + struct cpu_ops_t *cpu_ops; + + if (!(entry = (rt_ubase_t)rt_kmem_v2p(_secondary_cpu_entry))) + { + LOG_E("Failed to translate '_secondary_cpu_entry' to physical address"); + RT_ASSERT(0); + } + + cpu_ops = <...>; + cpu_id = rt_hw_cpu_id(); + + /* Maybe we are no in the first cpu */ + for (int i = 0; i < RT_CPUS_NR; ++i) + { + int err; + + if (i == cpu_id) + { + continue; + } + + if (cpu_ops->cpu_init) + { + cpu_ops->cpu_init(i, RT_NULL); + } + + if ((err = cpu_ops->cpu_boot(i, entry))) + { + LOG_W("Call cpu %d on %s", i, "failed"); + } + } +} +``` + +## Interrupt + +Implement the PLIC information if enable M-mode in your BSP by `board.h`: + +```c +rt_inline void rt_ubase_t platform_get_clint_base(void) +{ + return clint_physical_address_base; +} + +rt_inline void rt_size_t platform_get_clint_size(void) +{ + return clint_physical_address_size; +} +``` + +### PLIC + RISC-V INTC + +Implement the PLIC information and `MAX_HANDLERS`, INTC type in your BSP by `board.h`: + +```c +#define MAX_HANDLERS <...> + +/* + * Type: + * - INTC_TYPE_RISCV (Default, could not define) + * - INTC_TYPE_ANDESTECH + */ +#define INTC_TYPE <...> + +/* + * Bits (Not quicks could not define): + * - PLIC_QUIRK_EDGE_INTERRUPT + */ +#define PLIC_QUICKS <...> + +rt_inline void rt_ubase_t platform_get_plic_base(void) +{ + return plic_physical_address_base; +} + +rt_inline void rt_size_t platform_get_plic_size(void) +{ + return plic_physical_address_size; +} +``` + +Use the `IRQ_XYZ(vector)` or `IPI_INTC(vector)` to instread of `vector`: + +```c +#include + +#define DEVICE_HWIRQ 1 + +static void device_isr(int hwirq, void *param) +{ + RT_ASSERT(DEVICE_HWIRQ == hwirq); +} + +void rt_hw_device_init(void) +{ + rt_hw_interrupt_install(IRQ_PLIC(DEVICE_HWIRQ), device_isr, RT_NULL, "device isr"); + rt_hw_interrupt_umask(IRQ_PLIC(DEVICE_HWIRQ)); +} + +#include + +static void pmu_isr(int hwirq, void *param) +{ + RT_ASSERT(IRQ_PMU_OVF == hwirq); +} + +void rt_hw_pmu_init(void) +{ + rt_hw_interrupt_install(IRQ_INTC(IRQ_PMU_OVF), pmu_isr, RT_NULL, "pmu isr"); + rt_hw_interrupt_umask(IRQ_INTC(IRQ_PMU_OVF)); +} + +#ifdef RT_USING_SMP +void rt_hw_ipi_init(void) +{ + rt_hw_ipi_handler_install(IPI_INTC(RT_SCHEDULE_IPI), rt_scheduler_ipi_handler); + rt_hw_interrupt_umask(IPI_INTC(RT_SCHEDULE_IPI)); +} +#endif /* RT_USING_SMP */ +``` + +### CLIC +Implement the CLIC information and `MAX_HANDLERS`, INTC type in your BSP by `board.h`: + +```c +#define MAX_HANDLERS <...> + +#define INTC_TYPE INTC_TYPE_CLIC + +/* + * Bits (Not quicks could not define): + * - CLIC_QUIRK_MODE_FIXED + * - CLIC_QUIRK_MINTTHRESH + */ +#define CLIC_QUICKS <...> + +rt_inline void rt_ubase_t platform_get_clic_base(void) +{ + return clic_physical_address_base; +} + +rt_inline void rt_size_t platform_get_clic_size(void) +{ + return clic_physical_address_size; +} +``` + +Use the `IRQ_CLIC(vector)` or `IPI_CLIC(vector)` to instread of `vector`: + +```c +#include + +#define DEVICE_HWIRQ 1 + +static void device_isr(int hwirq, void *param) +{ + RT_ASSERT(DEVICE_HWIRQ == hwirq); +} + +void rt_hw_device_init(void) +{ + rt_hw_interrupt_install(IRQ_CLIC(DEVICE_HWIRQ), device_isr, RT_NULL, "device isr"); + rt_hw_interrupt_umask(IRQ_CLIC(DEVICE_HWIRQ)); +} + +#ifdef RT_USING_SMP +void rt_hw_ipi_init(void) +{ + rt_hw_ipi_handler_install(IPI_CLIC(RT_SCHEDULE_IPI), rt_scheduler_ipi_handler); + rt_hw_interrupt_umask(IPI_CLIC(RT_SCHEDULE_IPI)); +} +#endif /* RT_USING_SMP */ +``` + +## ISA + +Select the ISA in your BSP: + +```c +#include + +void rt_hw_isa_init(void) +{ + riscv_isa_ext_set(I); + riscv_isa_ext_set(M); + riscv_isa_ext_set(A); + riscv_isa_ext_set(F); + riscv_isa_ext_set(D); + riscv_isa_ext_set(Q); + riscv_isa_ext_set(C); + riscv_isa_ext_set(V); + riscv_isa_ext_set(ZICBOM); + [...] +} +``` + +## Timer + +Initialize the RISC-V timer in your BSP: + +```c +#include +#include +#include + +void rt_hw_timer_init(int cpu_id) +{ + if (riscv_cpu_id_to_hartid(cpu_id) == boot_cpu_hartid) + { + riscv_timer_set_frequency(<...>); + } + + riscv_timer_init(); +} +``` + +## MMU + +Define the virtual address size in your BSP: + +```c +rt_uint8_t rt_hw_arch_vaddr_width = <...>; /* 0/32/39/48/57/64 */ +``` + +if the `rt_hw_arch_vaddr_width` is zero (RTOS only), the MMU will be disabled, we recommended to disable the SoC's Kconfig option `ARCH_MM_MMU` before build. + +## Board + +There is a recommended initialization: + +```c +[...] + +void rt_hw_board_init(void) +{ + int cpu_id = rt_hw_cpu_id(); + + /* Memory, Pages, MMU... */ + [...] + + rt_hw_isa_init(); + + rt_hw_cache_init(); + + rt_hw_interrupt_init(); + + rt_hw_timer_init(cpu_id); + + /* Components, Console, Idle hook, SMP install... */ + [...] +} + +#ifdef RT_USING_SMP +void rt_hw_secondary_cpu_bsp_start(void) +{ + int cpu_id = rt_hw_cpu_id(); + + rt_hw_spin_lock(&_cpus_lock); + + /* MMU... */ + [...] + + rt_hw_interrupt_init(); + + rt_hw_timer_init(cpu_id); + + /* SMP install, Scheduler... */ + [...] +} +#endif /* RT_USING_SMP */ +``` diff --git a/libcpu/risc-v/common/SConscript b/libcpu/risc-v/common/SConscript index deaa2907c56..36acbece044 100644 --- a/libcpu/risc-v/common/SConscript +++ b/libcpu/risc-v/common/SConscript @@ -2,14 +2,50 @@ from building import * +Import('rtconfig') + cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') -CPPPATH = [cwd] -ASFLAGS = ' -I ' + cwd +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, cwd + '/include'] + +if rtconfig.PLATFORM in ['gcc']: + src += Glob('*_gcc.S') + +if not GetDepend('RT_USING_LWP'): + SrcRemove(src, ['syscall.c']) + +if GetDepend('ARCH_MM_MMU'): + SrcRemove(src, ['mmu_dummy.c']) +else: + SrcRemove(src, ['mmu.c']) + +if GetDepend('ARCH_RISCV_M_MODE'): + SrcRemove(src, ['console.c', 'cpu_sbi.c', 'sbi.c']) + +if GetDepend('RT_USING_DM'): + SrcRemove(src, ['interrupt.c', 'console.c']) +else: + SrcRemove(src, ['setup.c']) + + if GetDepend('RT_USING_SMP'): + cpus_nr = GetConfigValue('RT_CPUS_NR') + hartid_map = open(cwd + '/hartid.map', 'w') + + for cpu in range(int(cpus_nr)): + hartid_map.write("[{}] = {},\n".format(cpu, cpu)) + + hartid_map.close() + +group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) -if not GetDepend('RT_USING_HW_ATOMIC'): - SrcRemove(src, 'atomic_riscv.c') +# build for sub-directory +list = os.listdir(cwd) +objs = [] -group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS) +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) +group = group + objs Return('group') diff --git a/libcpu/risc-v/common/atomic_riscv.c b/libcpu/risc-v/common/atomic_riscv.c index bc1561f2ee3..3286c94d9ab 100644 --- a/libcpu/risc-v/common/atomic_riscv.c +++ b/libcpu/risc-v/common/atomic_riscv.c @@ -10,150 +10,113 @@ #include +#include + rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoswap." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoadd." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; + val = -val; -#if __riscv_xlen == 32 - asm volatile ("amoadd.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoadd.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + __asm__ volatile ("amoadd." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoxor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoxor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoxor." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoand.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoand.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoand." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoor." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); + return result; } rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoxor.w %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoxor.d %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoxor." REG_WIDTH " %0, x0, (%1)" : "=r"(result) : "r"(ptr) : "memory"); + return result; } void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoswap.w %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoswap.d %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoswap." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(val), "r"(ptr) : "memory"); } rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr) { - rt_atomic_t result = 0; - rt_atomic_t temp = 1; -#if __riscv_xlen == 32 - asm volatile ("amoor.w %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoor.d %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory"); -#endif + rt_atomic_t result = 0, temp = 1; + + __asm__ volatile ("amoor." REG_WIDTH " %0, %1, (%2)" : "=r"(result) : "r"(temp), "r"(ptr) : "memory"); + return result; } void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr) { rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile ("amoand.w %0, x0, (%1)" : "=r"(result) :"r"(ptr) : "memory"); -#elif __riscv_xlen == 64 - asm volatile ("amoand.d %0, x0, (%1)" : "=r"(result) :"r"(ptr) : "memory"); -#endif + + __asm__ volatile ("amoand." REG_WIDTH " %0, x0, (%1)" : "=r"(result) :"r"(ptr) : "memory"); } rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *old, rt_atomic_t desired) { - rt_atomic_t tmp = *old; - rt_atomic_t result = 0; -#if __riscv_xlen == 32 - asm volatile( - " fence iorw, ow\n" - "1: lr.w.aq %[result], (%[ptr])\n" - " bne %[result], %[tmp], 2f\n" - " sc.w.rl %[tmp], %[desired], (%[ptr])\n" - " bnez %[tmp], 1b\n" - " li %[result], 1\n" - " j 3f\n" - " 2:sw %[result], (%[old])\n" - " li %[result], 0\n" - " 3:\n" - : [result]"+r" (result), [tmp]"+r" (tmp), [ptr]"+r" (ptr) - : [desired]"r" (desired), [old]"r"(old) - : "memory"); -#elif __riscv_xlen == 64 - asm volatile( + rt_atomic_t tmp = *old, result = 0; + + __asm__ volatile ( " fence iorw, ow\n" - "1: lr.d.aq %[result], (%[ptr])\n" + "1: lr." REG_WIDTH ".aq %[result], (%[ptr])\n" " bne %[result], %[tmp], 2f\n" - " sc.d.rl %[tmp], %[desired], (%[ptr])\n" + " sc." REG_WIDTH ".rl %[tmp], %[desired], (%[ptr])\n" " bnez %[tmp], 1b\n" " li %[result], 1\n" " j 3f\n" - " 2:sd %[result], (%[old])\n" + " 2:" REG_S " %[result], (%[old])\n" " li %[result], 0\n" " 3:\n" : [result]"+r" (result), [tmp]"+r" (tmp), [ptr]"+r" (ptr) : [desired]"r" (desired), [old]"r"(old) : "memory"); -#endif + return result; } diff --git a/libcpu/risc-v/common64/backtrace.c b/libcpu/risc-v/common/backtrace.c similarity index 93% rename from libcpu/risc-v/common64/backtrace.c rename to libcpu/risc-v/common/backtrace.c index 8cfe7126cbc..bf630a90857 100644 --- a/libcpu/risc-v/common64/backtrace.c +++ b/libcpu/risc-v/common/backtrace.c @@ -12,10 +12,10 @@ #define DBG_LVL DBG_INFO #include +#include +#include #include #include -#include "riscv_mmu.h" -#include "stack.h" #define WORD sizeof(rt_base_t) #define ARCH_CONTEXT_FETCH(pctx, id) (*(((unsigned long *)pctx) + (id))) @@ -72,8 +72,8 @@ rt_err_t rt_hw_backtrace_frame_unwind(rt_thread_t thread, struct rt_hw_backtrace if (fp && !((long)fp & 0x7)) { -#ifdef RT_USING_SMART - if (thread->lwp) + #ifdef RT_USING_SMART + if (thread && thread->lwp) { void *lwp = thread->lwp; void *this_lwp = lwp_self(); @@ -91,7 +91,7 @@ rt_err_t rt_hw_backtrace_frame_unwind(rt_thread_t thread, struct rt_hw_backtrace } } else -#endif + #endif /* RT_USING_SMART */ if ((rt_kmem_v2p(fp) != ARCH_MAP_FAILED)) { rc = _bt_kaddr(fp, frame); @@ -120,7 +120,7 @@ rt_err_t rt_hw_backtrace_frame_get(rt_thread_t thread, struct rt_hw_backtrace_fr { rt_hw_switch_frame_t sframe = thread->sp; frame->pc = sframe->regs[RT_HW_SWITCH_CONTEXT_RA]; - frame->fp = sframe->regs[RT_HW_SWITCH_CONTEXT_S0];; + frame->fp = sframe->regs[RT_HW_SWITCH_CONTEXT_S0]; rc = RT_EOK; } return rc; diff --git a/libcpu/risc-v/common/builtin_fdt_gcc.S b/libcpu/risc-v/common/builtin_fdt_gcc.S new file mode 100755 index 00000000000..834f50f3f2d --- /dev/null +++ b/libcpu/risc-v/common/builtin_fdt_gcc.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include + + .section ".data" + + .align RISCV_SZPTR + .globl rt_hw_builtin_fdt +rt_hw_builtin_fdt: +#ifdef RT_BUILTIN_FDT_PATH + .incbin RT_BUILTIN_FDT_PATH +#endif diff --git a/libcpu/risc-v/common/cache.c b/libcpu/risc-v/common/cache.c new file mode 100644 index 00000000000..0c7e248dc14 --- /dev/null +++ b/libcpu/risc-v/common/cache.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-29 lizhirui first version + * 2025-04-20 GuEe-GUI Port to the DM + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef RT_USING_SMP +#include +#endif +#ifdef RT_USING_HWCACHE +#include +#endif + +static rt_uint32_t riscv_cbom_block_size; + +void riscv_cache_set_cbom_block_size(rt_uint32_t size) +{ + if (!riscv_isa_ext_test(ZICBOM)) + { + RT_ASSERT(0); + return; + } + + HWREG32(&riscv_cbom_block_size) = size; + rt_hw_wmb(); +} + +rt_uint32_t riscv_cache_get_cbom_block_size(void) +{ + rt_hw_rmb(); + return HWREG32(&riscv_cbom_block_size); +} + +rt_always_inline void local_flush_icache_all(void) +{ + __asm__ volatile (OPC_FENCE_I:::"memory"); +} + +rt_inline void ipi_remote_fence_i(void *data) +{ + RT_UNUSED(data); + + local_flush_icache_all(); +} + +rt_weak void rt_hw_cpu_icache_enable(void) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_icache_enable(); +#endif +} + +rt_weak void rt_hw_cpu_icache_disable(void) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_icache_disable(); +#endif +} + +rt_weak rt_base_t rt_hw_cpu_icache_status(void) +{ +#ifdef RT_USING_HWCACHE + return rt_hwcache_icache_status(); +#elif !defined(ARCH_RISCV_DISABLE_FENCE_I) + return 0; +#else /* !ARCH_RISCV_DISABLE_FENCE_I */ + return !0; +#endif /* RT_USING_HWCACHE */ +} + +rt_weak void rt_hw_cpu_icache_ops(int ops, void *addr, int size) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_icache_ops(ops, addr, size); +#elif !defined(ARCH_RISCV_DISABLE_FENCE_I) + /* + * RISC-V doesn't have an instruction to flush parts of the icache, + * so instead we just flush the whole thing. + */ + if (ops == RT_HW_CACHE_INVALIDATE) + { + local_flush_icache_all(); + + #if (defined(RT_USING_SMP) && RT_CPUS_NR > 1) || defined(RT_USING_AMP) + #ifndef ARCH_RISCV_M_MODE + if (has_ipi_extension) + { + sbi_remote_fence_i(RT_NULL); + } + else + #endif /* !ARCH_RISCV_M_MODE */ + { + rt_smp_call_each_cpu(ipi_remote_fence_i, RT_NULL, SMP_CALL_WAIT_ALL); + } + #endif /* RT_USING_SMP */ + } + RT_UNUSED(addr); + RT_UNUSED(size); +#else /* !ARCH_RISCV_DISABLE_FENCE_I */ + RT_UNUSED(ops); + RT_UNUSED(addr); + RT_UNUSED(size); +#endif /* RT_USING_HWCACHE */ +} + +rt_weak void rt_hw_cpu_dcache_enable(void) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_dcache_enable(); +#endif +} + +rt_weak void rt_hw_cpu_dcache_disable(void) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_dcache_disable(); +#endif +} + +rt_weak rt_base_t rt_hw_cpu_dcache_status(void) +{ +#ifdef RT_USING_HWCACHE + return rt_hwcache_dcache_status(); +#else + return riscv_cache_get_cbom_block_size() == 0; +#endif +} + +rt_weak void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) +{ +#ifdef RT_USING_HWCACHE + rt_hwcache_dcache_ops(ops, addr, size); +#else + rt_uint32_t cbom_block_size; + + cbom_block_size = riscv_cache_get_cbom_block_size(); + + if (cbom_block_size) + { + if (ops == RT_HW_CACHE_FLUSH) + { + __asm__ volatile ( + " mv a0, %1\n\t" + " j 2f\n\t" + "3:\n\t" + OPC_CBO_CLEAN(a0) + " add a0, a0, %0\n\t" + "2:\n\t" + " bltu a0, %2, 3b\n\t" + ::"r"(cbom_block_size), + "r"((rt_ubase_t)addr & ~(cbom_block_size - 1UL)), + "r"((rt_ubase_t)addr + size) + : "a0"); + } + else if (ops == RT_HW_CACHE_INVALIDATE) + { + __asm__ volatile ( + " mv a0, %1\n\t" + " j 2f\n\t" + "3:\n\t" + OPC_CBO_INVAL(a0) + " add a0, a0, %0\n\t" + "2:\n\t" + " bltu a0, %2, 3b\n\t" + ::"r"(cbom_block_size), + "r"((rt_ubase_t)addr & ~(cbom_block_size - 1UL)), + "r"((rt_ubase_t)addr + size) + : "a0"); + } + } + else + { + __asm__ volatile (".rept 6\n nop\n .endr\n"); + } +#endif /* RT_USING_HWCACHE */ +} + +rt_weak void rt_hw_cpu_icache_invalidate_all(void) +{ + rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, RT_NULL, ~0U); +} + +rt_weak void rt_hw_cpu_icache_invalidate(void *addr, rt_size_t size) +{ + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size); +} + +rt_weak void rt_hw_cpu_dcache_clean_and_invalidate(void *addr, rt_size_t size) +{ + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size); +} + +rt_weak void rt_hw_icache_invalidate_all(void) +{ + rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, RT_NULL, ~0U); +} + +rt_weak void rt_hw_sync_cache_local(void *addr, int size) +{ + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, addr, size); + rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, addr, size); +} diff --git a/libcpu/risc-v/common/console.c b/libcpu/risc-v/common/console.c new file mode 100644 index 00000000000..a2ce9f148b3 --- /dev/null +++ b/libcpu/risc-v/common/console.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-05-18 Bernard port from FreeBSD + */ + +#include + +void rt_hw_console_output(const char *str) +{ + while (*str) + { + sbi_console_putchar(*str++); + } +} diff --git a/libcpu/risc-v/common/context_gcc.S b/libcpu/risc-v/common/context_gcc.S index 792ac8bd677..ff12da17452 100644 --- a/libcpu/risc-v/common/context_gcc.S +++ b/libcpu/risc-v/common/context_gcc.S @@ -1,319 +1,280 @@ /* - * Copyright (c) 2006-2018, RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting implementation - * 2018/12/27 Jesven Add SMP support - * 2020/11/20 BalanceTWK Add FPU support - * 2022/12/28 WangShun Add macro to distinguish whether FPU is supported - * 2023/03/19 Flyingcys Add riscv_32e support + * 2018-10-28 Bernard The unify RISC-V porting implementation + * 2018-12-27 Jesven Add SMP support + * 2021-02-02 lizhirui Add userspace support + * 2022-10-22 Shell Support User mode RVV; + * Trimming process switch context + * 2025-04-20 GuEe-GUI Support SMP */ -#define __ASSEMBLY__ -#include "cpuport.h" +#include "asm.h" +#include "csr.h" -#ifdef RT_USING_SMP -#define rt_hw_interrupt_disable rt_hw_local_irq_disable -#define rt_hw_interrupt_enable rt_hw_local_irq_enable -#endif +#define REG_IDX(name) RT_HW_SWITCH_CONTEXT_##name -/* - * rt_base_t rt_hw_interrupt_disable(void); - */ - .globl rt_hw_interrupt_disable -rt_hw_interrupt_disable: - csrrci a0, mstatus, 8 - ret +.macro SAVE_REG reg, index + REG_S \reg, \index * SZREG(sp) +.endm -/* - * void rt_hw_interrupt_enable(rt_base_t level); - */ - .globl rt_hw_interrupt_enable -rt_hw_interrupt_enable: - csrw mstatus, a0 - ret +.macro LOAD_REG reg, index + REG_L \reg, \index * SZREG(sp) +.endm + +.macro SAVE_CONTEXT + addi sp, sp, -(RT_HW_SWITCH_CONTEXT_SIZE * SZREG) + SAVE_REG tp, REG_IDX(TP) + SAVE_REG ra, REG_IDX(RA) + SAVE_REG s0, REG_IDX(S0) + SAVE_REG s1, REG_IDX(S1) + csrr s1, CSR_STATUS + li s0, (SR_PP) + or s1, s1, s0 + SAVE_REG s1, REG_IDX(XSTATUS) +.endm +.macro RESTORE_CONTEXT + LOAD_REG s1, REG_IDX(XSTATUS) + csrw CSR_STATUS, s1 + LOAD_REG s1, REG_IDX(S1) + LOAD_REG s0, REG_IDX(S0) + LOAD_REG ra, REG_IDX(RA) + LOAD_REG tp, REG_IDX(TP) + addi sp, sp, RT_HW_SWITCH_CONTEXT_SIZE * SZREG + csrw CSR_EPC, ra +.endm + + .section ".text","ax" + +#ifdef RT_USING_SMP /* - * #ifdef RT_USING_SMP - * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread); - * #else - * void rt_hw_context_switch_to(rt_ubase_t to); - * #endif - * a0 --> to + * void rt_hw_context_switch_to(rt_ubase_t to, struct rt_thread *to_thread); + * a0 --> to (thread stack) * a1 --> to_thread */ - .globl rt_hw_context_switch_to +.globl rt_hw_context_switch_to rt_hw_context_switch_to: - la t0, __rt_rvstack -#ifdef SOC_RISCV_FAMILY_CH32 -/* - * if it is an assembly entry code, the SP offset value is determined by the assembly code, - * but the C code is determined by the compiler, so we subtract 512 here as a reservation. - * When entering the interrupt function of C code, the compiler automatically presses the stack - * into the task stack. We can only change the SP value used by the calling function after switching - * the interrupt stack.This problem can be solved by modifying the interrupt to the assembly entry, - * and there is no need to reserve 512 bytes. You only need to switch the interrupt stack at the - * beginning of the interrupt function -*/ - addi t0, t0, -512 // for ch32 -#endif /* SOC_RISCV_FAMILY_CH32 */ - csrw mscratch,t0 - - LOAD sp, (a0) + REG_L sp, (a0) -#ifdef RT_USING_SMP - mv a0, a1 - call rt_cpus_lock_status_restore + /* Reserved to_thread */ + mv s1, a1 + + mv a0, s1 + call rt_cpus_lock_status_restore +#ifdef RT_USING_SMART + mv a0, s1 + call lwp_user_setting_restore #endif - LOAD a0, 2 * REGBYTES(sp) - csrw mstatus, a0 - j rt_hw_context_switch_exit + + j _context_switch_exit /* - * #ifdef RT_USING_SMP * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); - * #else - * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); - * #endif - * - * a0 --> from - * a1 --> to + * a0 --> from (from_thread stack) + * a1 --> to (to_thread stack) * a2 --> to_thread */ - .globl rt_hw_context_switch +.globl rt_hw_context_switch rt_hw_context_switch: - /* saved from thread context - * x1/ra -> sp(0) - * x1/ra -> sp(1) - * mstatus.mie -> sp(2) - * x(i) -> sp(i-4) - */ -#ifdef ARCH_RISCV_FPU - addi sp, sp, -32 * FREGBYTES - - FSTORE f0, 0 * FREGBYTES(sp) - FSTORE f1, 1 * FREGBYTES(sp) - FSTORE f2, 2 * FREGBYTES(sp) - FSTORE f3, 3 * FREGBYTES(sp) - FSTORE f4, 4 * FREGBYTES(sp) - FSTORE f5, 5 * FREGBYTES(sp) - FSTORE f6, 6 * FREGBYTES(sp) - FSTORE f7, 7 * FREGBYTES(sp) - FSTORE f8, 8 * FREGBYTES(sp) - FSTORE f9, 9 * FREGBYTES(sp) - FSTORE f10, 10 * FREGBYTES(sp) - FSTORE f11, 11 * FREGBYTES(sp) - FSTORE f12, 12 * FREGBYTES(sp) - FSTORE f13, 13 * FREGBYTES(sp) - FSTORE f14, 14 * FREGBYTES(sp) - FSTORE f15, 15 * FREGBYTES(sp) - FSTORE f16, 16 * FREGBYTES(sp) - FSTORE f17, 17 * FREGBYTES(sp) - FSTORE f18, 18 * FREGBYTES(sp) - FSTORE f19, 19 * FREGBYTES(sp) - FSTORE f20, 20 * FREGBYTES(sp) - FSTORE f21, 21 * FREGBYTES(sp) - FSTORE f22, 22 * FREGBYTES(sp) - FSTORE f23, 23 * FREGBYTES(sp) - FSTORE f24, 24 * FREGBYTES(sp) - FSTORE f25, 25 * FREGBYTES(sp) - FSTORE f26, 26 * FREGBYTES(sp) - FSTORE f27, 27 * FREGBYTES(sp) - FSTORE f28, 28 * FREGBYTES(sp) - FSTORE f29, 29 * FREGBYTES(sp) - FSTORE f30, 30 * FREGBYTES(sp) - FSTORE f31, 31 * FREGBYTES(sp) + SAVE_CONTEXT + mv a3, sp + REG_S a3, (a0) /* Store sp in preempted tasks TCB */ + REG_L a0, (a1) /* Get new task stack pointer */ + mv sp, a0 + + /* Backup thread self */ + mv s1, a2 + mv a0, s1 + call rt_cpus_lock_status_restore +#ifdef RT_USING_SMART + mv a0, s1 + call lwp_user_setting_restore #endif -#ifndef __riscv_32e - addi sp, sp, -32 * REGBYTES + j _context_switch_exit + +#define EXP_FRAME t0 +#define FROM_SPP t1 +#define TO_SPP t2 +#define TO_TCB a4 +#define TMP a5 + +/* + * void rt_hw_context_switch_interrupt(rt_ubase_t context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread) + * a0 --> interrupt context + * a1 --> addr of from_thread's sp + * a2 --> addr of to_thread's sp + * a3 --> to_thread's tcb + */ +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: +#ifdef RT_USING_DEBUG + /* Debug frame for backtrace */ +#if __riscv_xlen == 64 + addi sp, sp, -(48) + sd ra, 40(sp) + sd s0, 32(sp) +#elif __riscv_xlen == 32 + addi sp, sp, -(32) + sw ra, 28(sp) + sw s0, 24(sp) #else - addi sp, sp, -16 * REGBYTES +#error "Unexpected __riscv_xlen" #endif +#endif /* RT_USING_DEBUG */ + + /* We can discard all the previous ABI here */ + mv EXP_FRAME, a0 + mv FROM_SPP, a1 + mv TO_SPP, a2 + mv TO_TCB, a3 + +#ifdef RT_USING_SMART + PUSH EXP_FRAME + PUSH FROM_SPP + PUSH TO_SPP + PUSH TO_TCB - STORE sp, (a0) - - STORE x1, 0 * REGBYTES(sp) - STORE x1, 1 * REGBYTES(sp) - - csrr a0, mstatus - andi a0, a0, 8 - beqz a0, save_mpie - li a0, 0x80 -save_mpie: - STORE a0, 2 * REGBYTES(sp) - - STORE x4, 4 * REGBYTES(sp) - STORE x5, 5 * REGBYTES(sp) - STORE x6, 6 * REGBYTES(sp) - STORE x7, 7 * REGBYTES(sp) - STORE x8, 8 * REGBYTES(sp) - STORE x9, 9 * REGBYTES(sp) - STORE x10, 10 * REGBYTES(sp) - STORE x11, 11 * REGBYTES(sp) - STORE x12, 12 * REGBYTES(sp) - STORE x13, 13 * REGBYTES(sp) - STORE x14, 14 * REGBYTES(sp) - STORE x15, 15 * REGBYTES(sp) -#ifndef __riscv_32e - STORE x16, 16 * REGBYTES(sp) - STORE x17, 17 * REGBYTES(sp) - STORE x18, 18 * REGBYTES(sp) - STORE x19, 19 * REGBYTES(sp) - STORE x20, 20 * REGBYTES(sp) - STORE x21, 21 * REGBYTES(sp) - STORE x22, 22 * REGBYTES(sp) - STORE x23, 23 * REGBYTES(sp) - STORE x24, 24 * REGBYTES(sp) - STORE x25, 25 * REGBYTES(sp) - STORE x26, 26 * REGBYTES(sp) - STORE x27, 27 * REGBYTES(sp) - STORE x28, 28 * REGBYTES(sp) - STORE x29, 29 * REGBYTES(sp) - STORE x30, 30 * REGBYTES(sp) - STORE x31, 31 * REGBYTES(sp) + call rt_thread_self + call lwp_user_setting_save + + POP TO_TCB + POP TO_SPP + POP FROM_SPP + POP EXP_FRAME +#endif /* RT_USING_SMART */ + + /* Reset SP of from-thread */ + mv sp, EXP_FRAME + + addi sp, sp, -(RT_HW_SWITCH_CONTEXT_SIZE * SZREG) + /* Push context for swtich */ + la ra, rt_hw_resume_kernel + /* Save the entire context */ + li TMP, (K_XSTATUS_DEFAULT & ~SR_PIE) + REG_S TMP, REG_IDX(XSTATUS) * SZREG(sp) + REG_S ra, REG_IDX(RA) * SZREG(sp) + + /* Save SP of from-thread */ + mv a0, sp + REG_S a0, (FROM_SPP) + + /* Setup SP to to-thread's */ + REG_L a0, (TO_SPP) + mv sp, a0 + +#ifdef RT_USING_SMART + PUSH TO_TCB #endif - /* restore to thread context - * sp(0) -> epc; - * sp(1) -> ra; - * sp(i) -> x(i+2) - */ - LOAD sp, (a1) + mv a0, TO_TCB + call rt_cpus_lock_status_restore +#ifdef RT_USING_SMART + POP a0 /* TO_TCB */ + call lwp_user_setting_restore +#endif + j _context_switch_exit -#ifdef RT_USING_SMP - mv a0, a2 - call rt_cpus_lock_status_restore -#endif /*RT_USING_SMP*/ +#else /* !RT_USING_SMP */ + .section ".data" - j rt_hw_context_switch_exit + .align RISCV_SZPTR +/** + * @brief from thread used interrupt context switch + */ +.globl rt_interrupt_from_thread +rt_interrupt_from_thread: + RISCV_PTR 0 + +/** + * @brief to thread used interrupt context switch + */ +.globl rt_interrupt_to_thread +rt_interrupt_to_thread: + RISCV_PTR 0 + +/** + * @brief flag to indicate context switch in interrupt or not + */ +.globl rt_thread_switch_interrupt_flag +rt_thread_switch_interrupt_flag: + RISCV_PTR 0 -#ifdef RT_USING_SMP /* - * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); + * void rt_hw_context_switch_to(rt_ubase_t to); * - * a0 --> context - * a1 --> from - * a2 --> to - * a3 --> to_thread + * a0 --> to SP pointer */ - .globl rt_hw_context_switch_interrupt -rt_hw_context_switch_interrupt: +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + REG_L sp, (a0) - STORE a0, 0(a1) + call rt_thread_self + mv s1, a0 - LOAD sp, 0(a2) - move a0, a3 - call rt_cpus_lock_status_restore +#ifdef RT_USING_SMART + call lwp_aspace_switch +#endif - j rt_hw_context_switch_exit + j _context_switch_exit -#endif +/* + * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); + * + * a0 --> from SP pointer + * a1 --> to SP pointer + * + * It should only be used on local interrupt disable + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + SAVE_CONTEXT + REG_S sp, (a0) -.global rt_hw_context_switch_exit -rt_hw_context_switch_exit: -#ifdef RT_USING_SMP -#ifdef RT_USING_SIGNALS - mv a0, sp - - csrr t0, mhartid - /* switch interrupt stack of current cpu */ - la sp, __stack_start__ - addi t1, t0, 1 - li t2, __STACKSIZE__ - mul t1, t1, t2 - add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */ - - call rt_signal_check - mv sp, a0 -#endif -#endif - /* resw ra to mepc */ - LOAD a0, 0 * REGBYTES(sp) - csrw mepc, a0 + /* Restore to thread SP */ + REG_L sp, (a1) - LOAD x1, 1 * REGBYTES(sp) -#ifdef ARCH_RISCV_FPU - li t0, 0x7800 -#else - li t0, 0x1800 -#endif - csrw mstatus, t0 - LOAD a0, 2 * REGBYTES(sp) - csrs mstatus, a0 - - LOAD x4, 4 * REGBYTES(sp) - LOAD x5, 5 * REGBYTES(sp) - LOAD x6, 6 * REGBYTES(sp) - LOAD x7, 7 * REGBYTES(sp) - LOAD x8, 8 * REGBYTES(sp) - LOAD x9, 9 * REGBYTES(sp) - LOAD x10, 10 * REGBYTES(sp) - LOAD x11, 11 * REGBYTES(sp) - LOAD x12, 12 * REGBYTES(sp) - LOAD x13, 13 * REGBYTES(sp) - LOAD x14, 14 * REGBYTES(sp) - LOAD x15, 15 * REGBYTES(sp) -#ifndef __riscv_32e - LOAD x16, 16 * REGBYTES(sp) - LOAD x17, 17 * REGBYTES(sp) - LOAD x18, 18 * REGBYTES(sp) - LOAD x19, 19 * REGBYTES(sp) - LOAD x20, 20 * REGBYTES(sp) - LOAD x21, 21 * REGBYTES(sp) - LOAD x22, 22 * REGBYTES(sp) - LOAD x23, 23 * REGBYTES(sp) - LOAD x24, 24 * REGBYTES(sp) - LOAD x25, 25 * REGBYTES(sp) - LOAD x26, 26 * REGBYTES(sp) - LOAD x27, 27 * REGBYTES(sp) - LOAD x28, 28 * REGBYTES(sp) - LOAD x29, 29 * REGBYTES(sp) - LOAD x30, 30 * REGBYTES(sp) - LOAD x31, 31 * REGBYTES(sp) - - addi sp, sp, 32 * REGBYTES -#else - addi sp, sp, 16 * REGBYTES -#endif + /* Restore Address Space */ + call rt_thread_self + mv s1, a0 -#ifdef ARCH_RISCV_FPU - FLOAD f0, 0 * FREGBYTES(sp) - FLOAD f1, 1 * FREGBYTES(sp) - FLOAD f2, 2 * FREGBYTES(sp) - FLOAD f3, 3 * FREGBYTES(sp) - FLOAD f4, 4 * FREGBYTES(sp) - FLOAD f5, 5 * FREGBYTES(sp) - FLOAD f6, 6 * FREGBYTES(sp) - FLOAD f7, 7 * FREGBYTES(sp) - FLOAD f8, 8 * FREGBYTES(sp) - FLOAD f9, 9 * FREGBYTES(sp) - FLOAD f10, 10 * FREGBYTES(sp) - FLOAD f11, 11 * FREGBYTES(sp) - FLOAD f12, 12 * FREGBYTES(sp) - FLOAD f13, 13 * FREGBYTES(sp) - FLOAD f14, 14 * FREGBYTES(sp) - FLOAD f15, 15 * FREGBYTES(sp) - FLOAD f16, 16 * FREGBYTES(sp) - FLOAD f17, 17 * FREGBYTES(sp) - FLOAD f18, 18 * FREGBYTES(sp) - FLOAD f19, 19 * FREGBYTES(sp) - FLOAD f20, 20 * FREGBYTES(sp) - FLOAD f21, 21 * FREGBYTES(sp) - FLOAD f22, 22 * FREGBYTES(sp) - FLOAD f23, 23 * FREGBYTES(sp) - FLOAD f24, 24 * FREGBYTES(sp) - FLOAD f25, 25 * FREGBYTES(sp) - FLOAD f26, 26 * FREGBYTES(sp) - FLOAD f27, 27 * FREGBYTES(sp) - FLOAD f28, 28 * FREGBYTES(sp) - FLOAD f29, 29 * FREGBYTES(sp) - FLOAD f30, 30 * FREGBYTES(sp) - FLOAD f31, 31 * FREGBYTES(sp) - - addi sp, sp, 32 * FREGBYTES +#ifdef RT_USING_SMART + call lwp_aspace_switch #endif - mret + j _context_switch_exit + +/* + * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread) + * a0 --> from_thread's sp + * a1 --> to_thread's sp + * a2 --> from_thread's tcb + * a3 --> to_thread's tcb + */ +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + la t0, rt_thread_switch_interrupt_flag + REG_L t1, (t0) + bne t1, zero, _init_to_thread + + la t1, rt_interrupt_from_thread + REG_S a0, (t1) + +_init_to_thread: + la t1, rt_interrupt_to_thread + REG_S a1, (t1) + + li t1, 1 + REG_S t1, (t0) + + ret +#endif /* RT_USING_SMP */ + +.local _context_switch_exit +_context_switch_exit: + RESTORE_CONTEXT + XRET diff --git a/libcpu/risc-v/common/cpu.c b/libcpu/risc-v/common/cpu.c new file mode 100755 index 00000000000..994084ceeb9 --- /dev/null +++ b/libcpu/risc-v/common/cpu.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef RT_USING_SMP +rt_weak int riscv_master_cpu_id rt_align(L1_CACHE_BYTES) = 0; +#endif + +rt_ubase_t boot_cpu_hartid; + +static rt_bool_t hartid_equ_cpuid = RT_TRUE; +rt_ubase_t cpu_id_to_hartid_map[RT_CPUS_NR] rt_align(L1_CACHE_BYTES) = +{ +#if defined(RT_USING_SMP) && !defined(RT_USING_DM) +#include "hartid.map" +#endif +}; + +#if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) +static rt_ubase_t *percpu_hartid rt_align(L1_CACHE_BYTES); + +void percpu_hartid_init(rt_ubase_t *percpu_ptr, rt_ubase_t hartid) +{ + rt_ubase_t *percpu_hartid_paddr; + int cpu_id = riscv_hartid_to_cpu_id(hartid); + rt_size_t percpu_size = (rt_size_t)(&__percpu_end - &__percpu_start); + + percpu_hartid_paddr = percpu_ptr; + percpu_hartid = (void *)((rt_ubase_t)percpu_ptr - rt_kmem_pvoff()); + + /* Save to the real area */ + *(rt_ubase_t *)((void *)percpu_hartid_paddr + cpu_id * percpu_size) = hartid; +} + +/* This is the current CPU stack, but it is not used in this call. */ +void percpu_write(rt_ubase_t offset, const void *data, rt_size_t size) +{ + rt_memcpy(percpu_hartid + 1 + offset, data, size); +} + +void percpu_read(rt_ubase_t offset, void *data, rt_size_t size) +{ + rt_memcpy(data, percpu_hartid + 1 + offset, size); +} +#endif /* RT_USING_SMP && ARCH_MM_MMU */ + +rt_ubase_t riscv_cpu_id_to_hartid(int cpu_id) +{ + RT_ASSERT(cpu_id < RT_CPUS_NR); + + return cpu_id_to_hartid_map[cpu_id]; +} + +int riscv_hartid_to_cpu_id(rt_ubase_t hartid) +{ + int cpu_id; + + if (hartid_equ_cpuid) + { + return hartid; + } + + for (cpu_id = 0; cpu_id < RT_CPUS_NR; ++cpu_id) + { + if (hartid == cpu_id_to_hartid_map[cpu_id]) + { + break; + } + } + + return cpu_id; +} + +void riscv_hartid_remap_cpu_id(rt_ubase_t hartid, int cpu_id) +{ + RT_ASSERT(cpu_id < RT_CPUS_NR); + + if (cpu_id != hartid) + { + hartid_equ_cpuid = RT_FALSE; + } + + cpu_id_to_hartid_map[cpu_id] = hartid; + rt_hw_wmb(); +} + +int rt_hw_cpu_id(void) +{ +#ifdef RT_USING_SMP +#if !defined(ARCH_RISCV_M_MODE) && defined(ARCH_MM_MMU) + if (ARCH_VADDR_WIDTH) + { + return riscv_hartid_to_cpu_id(*percpu_hartid); + } + else +#endif /* !ARCH_RISCV_M_MODE && ARCH_MM_MMU */ + { + int cpu_id; + + __asm__ volatile ("mv %0, tp":"=r"(cpu_id)); + + return cpu_id; + } +#else + return 0; +#endif +} + +const char *rt_hw_cpu_arch(void) +{ +#if __riscv_xlen == 128 + return "riscv128"; +#elif __riscv_xlen == 64 + return "riscv64"; +#elif __riscv_xlen == 32 + return "riscv32"; +#else +#error "Unexpected __riscv_xlen" +#endif +} diff --git a/libcpu/risc-v/common/cpu_gcc.S b/libcpu/risc-v/common/cpu_gcc.S new file mode 100644 index 00000000000..1659e0ed2ba --- /dev/null +++ b/libcpu/risc-v/common/cpu_gcc.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include + +#ifdef RT_USING_SMP +#define rt_hw_interrupt_disable rt_hw_local_irq_disable +#define rt_hw_interrupt_enable rt_hw_local_irq_enable +#endif + + .section ".text","ax" + +START_POINT(rt_hw_interrupt_is_disabled) + csrr a0, CSR_STATUS + andi a0, a0, SR_IE + seqz a0, a0 + ret +START_POINT_END(rt_hw_interrupt_is_disabled) + +START_POINT(rt_hw_interrupt_enable) + /* Restore to old csr */ + csrs CSR_STATUS, a0 + ret +START_POINT_END(rt_hw_interrupt_enable) + +START_POINT(rt_hw_interrupt_disable) + /* Clear IE */ + csrrci a0, CSR_STATUS, SR_IE + ret +START_POINT_END(rt_hw_interrupt_disable) diff --git a/libcpu/risc-v/common/cpu_sbi.c b/libcpu/risc-v/common/cpu_sbi.c new file mode 100755 index 00000000000..0a8a319f238 --- /dev/null +++ b/libcpu/risc-v/common/cpu_sbi.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include +#include +#include + +static int sbi_cpu_boot(rt_uint32_t cpuid, rt_uint64_t entry) +{ + rt_ubase_t hartid = riscv_cpu_id_to_hartid(cpuid); + + return sbi_hsm_hart_start(hartid, entry, entry); +} + +static void sbi_cpu_shutdown(void) +{ + sbi_hsm_hart_stop(); +} + +struct cpu_ops_t cpu_sbi_ops = +{ + .method = "sbi", + .cpu_boot = sbi_cpu_boot, + .cpu_shutdown = sbi_cpu_shutdown, +}; diff --git a/libcpu/risc-v/common/cpu_spinwait.c b/libcpu/risc-v/common/cpu_spinwait.c new file mode 100755 index 00000000000..628046ccde0 --- /dev/null +++ b/libcpu/risc-v/common/cpu_spinwait.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include + +#include + +rt_uint8_t riscv_spinwait_table = 0; + +static int spinwait_cpu_boot(rt_uint32_t cpuid, rt_uint64_t entry) +{ + rt_hw_barrier(); + + HWREG8(&riscv_spinwait_table) = RT_UINT8_MAX; + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, &riscv_spinwait_table, sizeof(riscv_spinwait_table)); + + return 0; +} + +struct cpu_ops_t cpu_spinwait_ops = +{ + .method = "spinwait", + .cpu_boot = spinwait_cpu_boot, +}; diff --git a/libcpu/risc-v/common/cpuport.c b/libcpu/risc-v/common/cpuport.c index 502a8fcbf3d..502ee9c175d 100644 --- a/libcpu/risc-v/common/cpuport.c +++ b/libcpu/risc-v/common/cpuport.c @@ -1,99 +1,111 @@ /* - * Copyright (c) 2006-2023, RT-Thread Development Team + * Copyright (c) 2006-2025, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting code. - * 2020/11/20 BalanceTWK Add FPU support - * 2023/01/04 WangShun Adapt to CH32 + * 2018-10-28 Bernard The unify RISC-V porting code. + * 2025-04-20 GuEe-GUI Port ffsN and clz, spinlock */ #include #include -#include "cpuport.h" -#include "rt_hw_stack_frame.h" +#include -#ifndef RT_USING_SMP -volatile rt_ubase_t rt_interrupt_from_thread = 0; -volatile rt_ubase_t rt_interrupt_to_thread = 0; -volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0; -#endif +#ifdef RT_USING_CPU_FFS -/** - * This function will initialize thread stack - * - * @param tentry the entry of thread - * @param parameter the parameter of entry - * @param stack_addr the beginning stack address - * @param texit the function will be called when thread exit - * - * @return stack address - */ -rt_uint8_t *rt_hw_stack_init(void *tentry, - void *parameter, - rt_uint8_t *stack_addr, - void *texit) +int __rt_ffs(int value) { - struct rt_hw_stack_frame *frame; - rt_uint8_t *stk; - int i; - - stk = stack_addr + sizeof(rt_ubase_t); - stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_ubase_t)stk, REGBYTES); - stk -= sizeof(struct rt_hw_stack_frame); - - frame = (struct rt_hw_stack_frame *)stk; - - for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++) - { - ((rt_ubase_t *)frame)[i] = 0xdeadbeef; - } - - frame->ra = (rt_ubase_t)texit; - frame->a0 = (rt_ubase_t)parameter; - frame->epc = (rt_ubase_t)tentry; - - /* force to machine mode(MPP=11) and set MPIE to 1 */ -#ifdef ARCH_RISCV_FPU - frame->mstatus = 0x7880; +#ifdef __GNUC__ + return __builtin_ffs(value); #else - frame->mstatus = 0x1880; +#error Unsupport ffs #endif - - return stk; } -rt_weak void rt_trigger_software_interrupt(void) +unsigned long __rt_ffsl(unsigned long value) { - while (0); +#ifdef __GNUC__ + return __builtin_ffsl(value); +#else +#error Unsupport ffsl +#endif } -rt_weak void rt_hw_do_after_save_above(void) +unsigned long __rt_clz(unsigned long value) { - while (1); +#ifdef __GNUC__ + return __builtin_clz(value); +#else +#error Unsupport clz +#endif } +#endif /* RT_USING_CPU_FFS */ -/* - * #ifdef RT_USING_SMP - * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); - * #else - * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); - * #endif - */ -#ifndef RT_USING_SMP -rt_weak void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread) +#ifdef RT_USING_SMART +extern void percpu_write(rt_ubase_t offset, const void *data, rt_size_t size); + +void rt_hw_set_process_id(int pid) { - if (rt_thread_switch_interrupt_flag == 0) - rt_interrupt_from_thread = from; + percpu_write(0, &pid, sizeof(pid)); +} +#endif /* RT_USING_SMART */ - rt_interrupt_to_thread = to; - rt_thread_switch_interrupt_flag = 1; +#ifdef RT_USING_SMP +void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) +{ + lock->slock = 0; +} - rt_trigger_software_interrupt(); +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp, new_val, mask; + unsigned short ticket; + + __asm__ volatile ( + "1:\n\t" + " lr." REG_WIDTH ".aq %0, (%3)\n\t" + " srli %1, %0, 16\n\t" + " addi %1, %1, 1\n\t" + " slli %1, %1, 16\n\t" + " li %2, 0xffff\n\t" + " and %2, %0, %2\n\t" + " or %1, %1, %2\n\t" + " sc." REG_WIDTH ".rl %1, %1, (%3)\n\t" + " bnez %1, 1b" + : "=&r" (tmp), "=&r" (new_val), "=&r" (mask) + : "r" (&lock->slock) + : "memory"); + + ticket = (tmp >> 16) & 0xffff; + + while (HWREG16(&lock->tickets.owner) != ticket) + { + __asm__ volatile (OPC_PAUSE_I); + } +} - return ; +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp, new_val, mask; + + __asm__ volatile ( + "1:\n\t" + " lr." REG_WIDTH ".aq %0, (%3)\n\t" + " addi %1, %0, 1\n\t" + " li %2, 0xffff\n\t" + " and %1, %1, %2\n\t" + " slli %2, %2, 16\n\t" + " and %0, %0, %2\n\t" + " or %1, %0, %1\n\t" + " sc." REG_WIDTH ".rl %1, %1, (%3)\n\t" + " bnez %1, 1b" + : "=&r" (tmp), "=&r" (new_val), "=&r" (mask) + : "r" (&lock->slock) + : "memory"); + + rt_hw_barrier(); } -#endif /* end of RT_USING_SMP */ +#endif /* RT_USING_SMP */ diff --git a/libcpu/risc-v/common/cpuport.h b/libcpu/risc-v/common/cpuport.h deleted file mode 100644 index e485e91a4f8..00000000000 --- a/libcpu/risc-v/common/cpuport.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-03 Bernard The first version - * 2020/11/20 BalanceTWK Add FPU support - * 2023/01/04 WangShun Adapt to CH32 - * 2023/08/11 HPMicro Define ARCH_RISCV_FPU if FPU is enabled - */ - -#ifndef CPUPORT_H__ -#define CPUPORT_H__ - -#include - -#ifndef __ASSEMBLY__ -#ifdef RT_USING_SMP -typedef union { - unsigned long slock; - struct __arch_tickets { - unsigned short owner; - unsigned short next; - } tickets; -} rt_hw_spinlock_t; -#endif -#endif - -/* Preprocessor Definition */ -#if __riscv_flen == 32 -#define ARCH_RISCV_FPU -#define ARCH_RISCV_FPU_S -#endif - -#if __riscv_flen == 64 -#define ARCH_RISCV_FPU -#define ARCH_RISCV_FPU_D -#endif - -/* bytes of register width */ -#ifdef ARCH_CPU_64BIT -#define STORE sd -#define LOAD ld -#define REGBYTES 8 -#else -#define STORE sw -#define LOAD lw -#define REGBYTES 4 -#endif - -/* Preprocessor Definition */ -#ifdef ARCH_RISCV_FPU -#ifdef ARCH_RISCV_FPU_D -#define FSTORE fsd -#define FLOAD fld -#define FREGBYTES 8 -#define rv_floatreg_t rt_int64_t -#endif -#ifdef ARCH_RISCV_FPU_S -#define FSTORE fsw -#define FLOAD flw -#define FREGBYTES 4 -#define rv_floatreg_t rt_int32_t -#endif -#endif - -#endif diff --git a/libcpu/risc-v/common/hwcache/Kconfig b/libcpu/risc-v/common/hwcache/Kconfig new file mode 100644 index 00000000000..918b6253434 --- /dev/null +++ b/libcpu/risc-v/common/hwcache/Kconfig @@ -0,0 +1,3 @@ +config RT_CACHE_SIFIVE_CCACHE + bool "Sifive Composable Cache controller" + depends on RT_USING_HWCACHE diff --git a/libcpu/risc-v/common/hwcache/SConscript b/libcpu/risc-v/common/hwcache/SConscript new file mode 100644 index 00000000000..d7b5123ca56 --- /dev/null +++ b/libcpu/risc-v/common/hwcache/SConscript @@ -0,0 +1,17 @@ +from building import * + +group = [] + +if not GetDepend(['RT_USING_HWCACHE']): + Return('group') + +src = [] +cwd = GetCurrentDir() +CPPPATH = [cwd] + +if GetDepend(['RT_CACHE_SIFIVE_CCACHE']): + src += ['hwcache-sifive_ccache.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/risc-v/common/hwcache/hwcache-sifive_ccache.c b/libcpu/risc-v/common/hwcache/hwcache-sifive_ccache.c new file mode 100644 index 00000000000..6019fed0e7f --- /dev/null +++ b/libcpu/risc-v/common/hwcache/hwcache-sifive_ccache.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-25 GuEe-GUI the first version + */ + +#include +#include +#include +#include + +#define DBG_TAG "cache.sifive_ccache" +#define DBG_LVL DBG_INFO +#include + +#include + +#define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100 +#define SIFIVE_CCACHE_DIRECCFIX_HIGH 0x104 +#define SIFIVE_CCACHE_DIRECCFIX_COUNT 0x108 + +#define SIFIVE_CCACHE_DIRECCFAIL_LOW 0x120 +#define SIFIVE_CCACHE_DIRECCFAIL_HIGH 0x124 +#define SIFIVE_CCACHE_DIRECCFAIL_COUNT 0x128 + +#define SIFIVE_CCACHE_DATECCFIX_LOW 0x140 +#define SIFIVE_CCACHE_DATECCFIX_HIGH 0x144 +#define SIFIVE_CCACHE_DATECCFIX_COUNT 0x148 + +#define SIFIVE_CCACHE_DATECCFAIL_LOW 0x160 +#define SIFIVE_CCACHE_DATECCFAIL_HIGH 0x164 +#define SIFIVE_CCACHE_DATECCFAIL_COUNT 0x168 + +#define SIFIVE_CCACHE_CONFIG 0x00 +#define SIFIVE_CCACHE_CONFIG_BANK_MASK RT_GENMASK_ULL(7, 0) +#define SIFIVE_CCACHE_CONFIG_WAYS_MASK RT_GENMASK_ULL(15, 8) +#define SIFIVE_CCACHE_CONFIG_SETS_MASK RT_GENMASK_ULL(23, 16) +#define SIFIVE_CCACHE_CONFIG_BLKS_MASK RT_GENMASK_ULL(31, 24) + +#define SIFIVE_CCACHE_FLUSH64 0x200 +#define SIFIVE_CCACHE_FLUSH32 0x240 + +#define SIFIVE_CCACHE_WAYENABLE 0x08 +#define SIFIVE_CCACHE_ECCINJECTERR 0x40 + +#define SIFIVE_CCACHE_MAX_ECCINTR 4 +#define SIFIVE_CCACHE_LINE_SIZE 64 + +#define SIFIVE_CCACHE_TRUNKCLOCKGATE 0x1000 +#define SIFIVE_CCACHE_TRUNKCLOCKGATE_DISABLE RT_BIT(0) +#define SIFIVE_CCACHE_REGIONCLOCKGATE_DISABLE RT_BIT(1) + +enum +{ + DIR_CORR = 0, + DATA_CORR, + DATA_UNCORR, + DIR_UNCORR, +}; + +enum +{ + QUIRK_BROKEN_DATA_UNCORR = RT_BIT(0), + QUIRK_HAS_CG = RT_BIT(1), +}; + +static void *ccache_base; +static rt_ubase_t ccache_quirk; +static rt_uint32_t ccache_level; +static int ccache_irq[SIFIVE_CCACHE_MAX_ECCINTR]; +static struct rt_ofw_node *ccache_np; + +static void ccache_enable(void) +{ + rt_uint32_t config, ways; + + /* Enable all ways of composable cache */ + config = HWREG32(ccache_base + SIFIVE_CCACHE_CONFIG); + ways = RT_FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS_MASK, config); + + HWREG32(ccache_base + SIFIVE_CCACHE_WAYENABLE) = ways - 1; + + if (ccache_quirk & QUIRK_HAS_CG) + { + /* Enable clock gating bits */ + config = HWREG32(ccache_base + SIFIVE_CCACHE_TRUNKCLOCKGATE); + config &= ~(SIFIVE_CCACHE_TRUNKCLOCKGATE_DISABLE | SIFIVE_CCACHE_REGIONCLOCKGATE_DISABLE); + HWREG32(ccache_base + SIFIVE_CCACHE_TRUNKCLOCKGATE) = config; + } +} + +static void ccache_disable(void) +{ + rt_uint32_t config; + + HWREG32(ccache_base + SIFIVE_CCACHE_WAYENABLE) = 0; + + if (ccache_quirk & QUIRK_HAS_CG) + { + /* Disable clock gating bits */ + config = HWREG32(ccache_base + SIFIVE_CCACHE_TRUNKCLOCKGATE); + config |= SIFIVE_CCACHE_TRUNKCLOCKGATE_DISABLE | SIFIVE_CCACHE_REGIONCLOCKGATE_DISABLE; + HWREG32(ccache_base + SIFIVE_CCACHE_TRUNKCLOCKGATE) = config; + } +} + +static void ccache_flush_range(void *vaddr, rt_size_t size) +{ + rt_ubase_t start = (rt_ubase_t)rt_kmem_v2p(vaddr); + rt_ubase_t end = start + size; + + if (!size) + { + return; + } + + rt_hw_barrier(); + + for (rt_ubase_t line = RT_ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); + line < end; + line += SIFIVE_CCACHE_LINE_SIZE) + { + #ifdef ARCH_CPU_64BIT + HWREG64(ccache_base + SIFIVE_CCACHE_FLUSH64) = line; + #else + HWREG32(ccache_base + SIFIVE_CCACHE_FLUSH32) = line >> 4; + #endif + rt_hw_barrier(); + } +} + +static struct rt_hwcache_ops ccache_mgmt = +{ + .name = "ccache", + .enable = ccache_enable, + .disable = ccache_disable, + .flush = ccache_flush_range, + .invalidate = ccache_flush_range, +}; + +static void sifive_ccache_isr(int irq, void *param) +{ + rt_uint32_t add_h, add_l; + + if (irq == ccache_irq[DIR_CORR]) + { + add_h = HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFIX_HIGH); + add_l = HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFIX_LOW); + LOG_E("Dir error: 0x%08x%08x", add_h, add_l); + + /* Reading this register clears the DirError interrupt sig */ + HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFIX_COUNT); + } + else if (irq == ccache_irq[DIR_UNCORR]) + { + add_h = HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_HIGH); + add_l = HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_LOW); + + /* Reading this register clears the DirFail interrupt sig */ + HWREG32(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_COUNT); + LOG_E("Dir fail: 0x%08x%08x", add_h, add_l); + RT_ASSERT(0); + } + else if (irq == ccache_irq[DATA_CORR]) + { + add_h = HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFIX_HIGH); + add_l = HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFIX_LOW); + LOG_E("Data error: 0x%08x.%08x", add_h, add_l); + + /* Reading this register clears the DataError interrupt sig */ + HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFIX_COUNT); + } + else if (irq == ccache_irq[DATA_UNCORR]) + { + add_h = HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFAIL_HIGH); + add_l = HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFAIL_LOW); + LOG_E("Data fail: 0x%08x%08x", add_h, add_l); + + /* Reading this register clears the DataFail interrupt sig */ + HWREG32(ccache_base + SIFIVE_CCACHE_DATECCFAIL_COUNT); + } +} + +static void ccache_irq_init(void) +{ + if (!ccache_np) + { + return; + } + + for (int i = 0; i < RT_ARRAY_SIZE(ccache_irq); ++i) + { + int irq; + + if (i == DATA_UNCORR && (ccache_quirk & QUIRK_BROKEN_DATA_UNCORR)) + { + continue; + } + + irq = rt_ofw_get_irq(ccache_np, i); + + if (irq >= 0) + { + rt_hw_interrupt_install(irq, sifive_ccache_isr, ccache_np, "ccache"); + rt_hw_interrupt_umask(irq); + + ccache_irq[i] = irq; + } + } +} +INIT_SUBSYS_EXPORT(ccache_irq_init); + +static rt_err_t sifive_ccache_ofw_init(struct rt_ofw_node *np, + const struct rt_ofw_node_id *id) +{ + ccache_quirk = *(rt_ubase_t *)id->data; + + ccache_base = rt_ofw_iomap(np, 0); + + if (!ccache_base) + { + return -RT_EIO; + } + + ccache_np = np; + + if (!rt_dm_cpu_dcache_ops) + { + rt_dm_cpu_dcache_ops = &ccache_mgmt; + } + + return RT_EOK; +} + +static rt_ubase_t ccache0_quirk = QUIRK_HAS_CG; +static rt_ubase_t jh7100_quirk = QUIRK_BROKEN_DATA_UNCORR; + +static const struct rt_ofw_node_id sifive_ccache_ofw_ids[] = +{ + { .compatible = "sifive,fu540-c000-ccache" }, + { .compatible = "sifive,fu740-c000-ccache" }, + { .compatible = "starfive,jh7100-ccache", .data = &jh7100_quirk }, + { .compatible = "sifive,ccache0", .data = &ccache0_quirk }, + { /* sentinel */ } +}; +RT_HWCACHE_OFW_DECLARE(sifive_ccache, sifive_ccache_ofw_ids, sifive_ccache_ofw_init); diff --git a/libcpu/risc-v/common/include/asm-generic.h b/libcpu/risc-v/common/include/asm-generic.h new file mode 100644 index 00000000000..25e225a642e --- /dev/null +++ b/libcpu/risc-v/common/include/asm-generic.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-03-12 WangXiaoyao the first version + * 2025-04-20 GuEe-GUI Merge 64 and 32 mode + */ + +#ifndef __ASM_GENERIC_H__ +#define __ASM_GENERIC_H__ + +#include + +#ifdef __ASSEMBLY__ +/* use to mark a start point where every task start from */ +#define START_POINT(funcname) \ + .global funcname; \ + .type funcname, %function; \ + funcname: \ + .cfi_sections .debug_frame, .eh_frame; \ + .cfi_startproc; \ + .cfi_undefined ra + +#define START_POINT_END(name) \ + .cfi_endproc; \ + .size name, .-name; + +#define _AC(X,Y) X +#define _AT(T,X) X +#define __ASM_STR(x) x +#else +#define _AC(X,Y) (X##Y) +#define _AT(T,X) ((T)(X)) +#define __ASM_STR(x) #x +#endif + +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#if __riscv_xlen == 64 +#define BITS_PER_LONG 8 +#define __REG_SEL(a, b) __ASM_STR(a) +#elif __riscv_xlen == 32 +#define BITS_PER_LONG 4 +#define __REG_SEL(a, b) __ASM_STR(b) +#else +#error "Unexpected __riscv_xlen" +#endif + +#ifndef BIT +#define BIT(x) (_UL(1) << (x)) +#endif + +#ifndef GENMASK +#define GENMASK(h, l) (((_UL(~0)) << (l)) & (_UL(~0) >> (BITS_PER_LONG - 1 - (h)))) +#endif + +#define REG_WIDTH __REG_SEL(d, w) +#define REG_L __REG_SEL(ld, lw) +#define REG_S __REG_SEL(sd, sw) +#define REG_SC __REG_SEL(sc.d, sc.w) +#define REG_AMOSWAP_AQ __REG_SEL(amoswap.d.aq, amoswap.w.aq) +#define REG_ASM __REG_SEL(.dword, .word) +#define SZREG __REG_SEL(8, 4) +#define LGREG __REG_SEL(3, 2) +#define FREG_L __REG_SEL(fld, flw) +#define FREG_S __REG_SEL(fsd, fsw) + +#if __riscv_xlen == 64 +#ifdef __ASSEMBLY__ +#define RISCV_PTR .dword +#define RISCV_SZPTR 8 +#define RISCV_LGPTR 3 +#else +#define RISCV_PTR ".dword" +#define RISCV_SZPTR "8" +#define RISCV_LGPTR "3" +#endif +#elif __riscv_xlen == 32 +#ifdef __ASSEMBLY__ +#define RISCV_PTR .word +#define RISCV_SZPTR 4 +#define RISCV_LGPTR 2 +#else +#define RISCV_PTR ".word" +#define RISCV_SZPTR "4" +#define RISCV_LGPTR "2" +#endif +#else +#error "Unexpected __riscv_xlen" +#endif + +#endif /* __ASM_GENERIC_H__ */ diff --git a/libcpu/risc-v/common/include/asm.h b/libcpu/risc-v/common/include/asm.h new file mode 100644 index 00000000000..25722c36ef6 --- /dev/null +++ b/libcpu/risc-v/common/include/asm.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-02 lizhirui first version + * 2021-02-11 lizhirui fixed gp save/store bug + * 2021-11-18 JasonHu add fpu registers save/restore + * 2022-10-22 Shell Support kernel mode RVV + * 2025-04-20 GuEe-GUI Merge 64I and 32I/E + */ + +#ifndef __ASM_H__ +#define __ASM_H__ + +#include + +#include +#include + +#ifdef __GNUC__ +.macro LOAD_GLOBAL_POINTER +.option push +.option norelax + la gp, __global_pointer$ +.option pop +.endm + +.macro XRET +#ifdef ARCH_RISCV_M_MODE + mret +#else + sret +#endif +.endm + +.macro PUSH reg + addi sp, sp, -SZREG + REG_S \reg, 0(sp) +.endm + +.macro POP reg + REG_L \reg, 0(sp) + addi sp, sp, SZREG +.endm + +.macro OPEN_INTERRUPT + csrsi CSR_STATUS, 2 +.endm + +.macro CLOSE_INTERRUPT + csrci CSR_STATUS, 2 +.endm + +.macro SAVE_ALL +#ifdef ARCH_RISCV_FPU + /* Reserve float registers */ + addi sp, sp, -CTX_FPU_REG_NR * SZREG +#endif +#ifdef ARCH_RISCV_VECTOR + /* Reserve float registers */ + addi sp, sp, -CTX_VECTOR_REG_NR * SZREG +#endif + + /* Save general registers */ + addi sp, sp, -CTX_GENERAL_REG_NR * SZREG + REG_S x1, 1 * SZREG(sp) + + csrr x1, CSR_STATUS + REG_S x1, FRAME_OFF_XSTATUS(sp) + + csrr x1, CSR_CAUSE + REG_S x1, FRAME_OFF_XCAUSE(sp) + + csrr x1, CSR_EPC + REG_S x1, 0 * SZREG(sp) + + REG_S x3, 4 * SZREG(sp) + REG_S x4, 5 * SZREG(sp) + REG_S x5, 6 * SZREG(sp) + REG_S x6, 7 * SZREG(sp) + REG_S x7, 8 * SZREG(sp) + REG_S x8, 9 * SZREG(sp) + REG_S x9, 10 * SZREG(sp) + REG_S x10, 11 * SZREG(sp) + REG_S x11, 12 * SZREG(sp) + REG_S x12, 13 * SZREG(sp) + REG_S x13, 14 * SZREG(sp) + REG_S x14, 15 * SZREG(sp) + REG_S x15, 16 * SZREG(sp) +#ifndef ARCH_RISCV_32E + REG_S x16, 17 * SZREG(sp) + REG_S x17, 18 * SZREG(sp) + REG_S x18, 19 * SZREG(sp) + REG_S x19, 20 * SZREG(sp) + REG_S x20, 21 * SZREG(sp) + REG_S x21, 22 * SZREG(sp) + REG_S x22, 23 * SZREG(sp) + REG_S x23, 24 * SZREG(sp) + REG_S x24, 25 * SZREG(sp) + REG_S x25, 26 * SZREG(sp) + REG_S x26, 27 * SZREG(sp) + REG_S x27, 28 * SZREG(sp) + REG_S x28, 29 * SZREG(sp) + REG_S x29, 30 * SZREG(sp) + REG_S x30, 31 * SZREG(sp) + REG_S x31, 32 * SZREG(sp) +#endif /* !ARCH_RISCV_32E */ + csrr t0, CSR_SCRATCH + REG_S t0, 33 * SZREG(sp) + +#ifdef ARCH_RISCV_FPU + /* Backup sp and adjust sp to save float registers */ + mv t1, sp + addi t1, t1, CTX_GENERAL_REG_NR * SZREG + + li t0, SR_FS + csrs CSR_STATUS, t0 + FREG_S f0, FPU_CTX_F0_OFF(t1) + FREG_S f1, FPU_CTX_F1_OFF(t1) + FREG_S f2, FPU_CTX_F2_OFF(t1) + FREG_S f3, FPU_CTX_F3_OFF(t1) + FREG_S f4, FPU_CTX_F4_OFF(t1) + FREG_S f5, FPU_CTX_F5_OFF(t1) + FREG_S f6, FPU_CTX_F6_OFF(t1) + FREG_S f7, FPU_CTX_F7_OFF(t1) + FREG_S f8, FPU_CTX_F8_OFF(t1) + FREG_S f9, FPU_CTX_F9_OFF(t1) + FREG_S f10, FPU_CTX_F10_OFF(t1) + FREG_S f11, FPU_CTX_F11_OFF(t1) + FREG_S f12, FPU_CTX_F12_OFF(t1) + FREG_S f13, FPU_CTX_F13_OFF(t1) + FREG_S f14, FPU_CTX_F14_OFF(t1) + FREG_S f15, FPU_CTX_F15_OFF(t1) + FREG_S f16, FPU_CTX_F16_OFF(t1) + FREG_S f17, FPU_CTX_F17_OFF(t1) + FREG_S f18, FPU_CTX_F18_OFF(t1) + FREG_S f19, FPU_CTX_F19_OFF(t1) + FREG_S f20, FPU_CTX_F20_OFF(t1) + FREG_S f21, FPU_CTX_F21_OFF(t1) + FREG_S f22, FPU_CTX_F22_OFF(t1) + FREG_S f23, FPU_CTX_F23_OFF(t1) + FREG_S f24, FPU_CTX_F24_OFF(t1) + FREG_S f25, FPU_CTX_F25_OFF(t1) + FREG_S f26, FPU_CTX_F26_OFF(t1) + FREG_S f27, FPU_CTX_F27_OFF(t1) + FREG_S f28, FPU_CTX_F28_OFF(t1) + FREG_S f29, FPU_CTX_F29_OFF(t1) + FREG_S f30, FPU_CTX_F30_OFF(t1) + FREG_S f31, FPU_CTX_F31_OFF(t1) + + /* Clean FS domain */ + csrc CSR_STATUS, t0 + + /* Clean status would clr sr_sd; */ + li t0, SR_FS_CLEAN + csrs CSR_STATUS, t0 + +#endif /* ARCH_RISCV_FPU */ + +#ifdef ARCH_RISCV_VECTOR + csrr t0, CSR_STATUS + andi t0, t0, SR_VS + beqz t0, 0f + + /* push vector frame */ + addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG + + SAVE_VECTOR t1 +0: +#endif /* ARCH_RISCV_VECTOR */ +.endm + +.macro RESTORE_ALL +#ifdef ARCH_RISCV_VECTOR + /* Skip on close */ + ld t0, 2 * SZREG(sp) + /* Cannot use vector on initial */ + andi t0, t0, SR_VS_CLEAN + beqz t0, 0f + + /* Push vector frame */ + addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * SZREG + + RESTORE_VECTOR t1 +0: +#endif /* ARCH_RISCV_VECTOR */ + +#ifdef ARCH_RISCV_FPU + /* Restore float register */ + addi t2, sp, CTX_GENERAL_REG_NR * SZREG + + li t0, SR_FS + csrs CSR_STATUS, t0 + FREG_L f0, FPU_CTX_F0_OFF(t2) + FREG_L f1, FPU_CTX_F1_OFF(t2) + FREG_L f2, FPU_CTX_F2_OFF(t2) + FREG_L f3, FPU_CTX_F3_OFF(t2) + FREG_L f4, FPU_CTX_F4_OFF(t2) + FREG_L f5, FPU_CTX_F5_OFF(t2) + FREG_L f6, FPU_CTX_F6_OFF(t2) + FREG_L f7, FPU_CTX_F7_OFF(t2) + FREG_L f8, FPU_CTX_F8_OFF(t2) + FREG_L f9, FPU_CTX_F9_OFF(t2) + FREG_L f10, FPU_CTX_F10_OFF(t2) + FREG_L f11, FPU_CTX_F11_OFF(t2) + FREG_L f12, FPU_CTX_F12_OFF(t2) + FREG_L f13, FPU_CTX_F13_OFF(t2) + FREG_L f14, FPU_CTX_F14_OFF(t2) + FREG_L f15, FPU_CTX_F15_OFF(t2) + FREG_L f16, FPU_CTX_F16_OFF(t2) + FREG_L f17, FPU_CTX_F17_OFF(t2) + FREG_L f18, FPU_CTX_F18_OFF(t2) + FREG_L f19, FPU_CTX_F19_OFF(t2) + FREG_L f20, FPU_CTX_F20_OFF(t2) + FREG_L f21, FPU_CTX_F21_OFF(t2) + FREG_L f22, FPU_CTX_F22_OFF(t2) + FREG_L f23, FPU_CTX_F23_OFF(t2) + FREG_L f24, FPU_CTX_F24_OFF(t2) + FREG_L f25, FPU_CTX_F25_OFF(t2) + FREG_L f26, FPU_CTX_F26_OFF(t2) + FREG_L f27, FPU_CTX_F27_OFF(t2) + FREG_L f28, FPU_CTX_F28_OFF(t2) + FREG_L f29, FPU_CTX_F29_OFF(t2) + FREG_L f30, FPU_CTX_F30_OFF(t2) + FREG_L f31, FPU_CTX_F31_OFF(t2) + + /* Clean FS domain */ + csrc CSR_STATUS, t0 + + /* Clean status would clr sr_sd; */ + li t0, SR_FS_CLEAN + csrs CSR_STATUS, t0 + +#endif /* ARCH_RISCV_FPU */ + + /* Restore general register */ + addi t0, sp, CTX_ALL_REG_NR * SZREG + csrw CSR_SCRATCH, t0 + + /* resw ra to CSR_EPC */ + REG_L x1, 0 * SZREG(sp) + csrw CSR_EPC, x1 + + REG_L x1, 2 * SZREG(sp) + csrw CSR_STATUS, x1 + + REG_L x1, 1 * SZREG(sp) + + REG_L x3, 4 * SZREG(sp) + REG_L x4, 5 * SZREG(sp) + REG_L x5, 6 * SZREG(sp) + REG_L x6, 7 * SZREG(sp) + REG_L x7, 8 * SZREG(sp) + REG_L x8, 9 * SZREG(sp) + REG_L x9, 10 * SZREG(sp) + REG_L x10, 11 * SZREG(sp) + REG_L x11, 12 * SZREG(sp) + REG_L x12, 13 * SZREG(sp) + REG_L x13, 14 * SZREG(sp) + REG_L x14, 15 * SZREG(sp) + REG_L x15, 16 * SZREG(sp) +#ifndef ARCH_RISCV_32E + REG_L x16, 17 * SZREG(sp) + REG_L x17, 18 * SZREG(sp) + REG_L x18, 19 * SZREG(sp) + REG_L x19, 20 * SZREG(sp) + REG_L x20, 21 * SZREG(sp) + REG_L x21, 22 * SZREG(sp) + REG_L x22, 23 * SZREG(sp) + REG_L x23, 24 * SZREG(sp) + REG_L x24, 25 * SZREG(sp) + REG_L x25, 26 * SZREG(sp) + REG_L x26, 27 * SZREG(sp) + REG_L x27, 28 * SZREG(sp) + REG_L x28, 29 * SZREG(sp) + REG_L x29, 30 * SZREG(sp) + REG_L x30, 31 * SZREG(sp) + REG_L x31, 32 * SZREG(sp) +#endif /* !ARCH_RISCV_32E */ + + /* Restore user sp */ + REG_L sp, 33 * SZREG(sp) +.endm +#endif /* __GNUC__ */ + +#endif /* __ASM_H__ */ diff --git a/libcpu/risc-v/common/include/cache.h b/libcpu/risc-v/common/include/cache.h new file mode 100644 index 00000000000..a8224a9e59d --- /dev/null +++ b/libcpu/risc-v/common/include/cache.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI the first version + */ + +#ifndef __CACHE_H__ +#define __CACHE_H__ + +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#ifndef __ASSEMBLY__ +#include + +void riscv_cache_set_cbom_block_size(rt_uint32_t size); +rt_uint32_t riscv_cache_get_cbom_block_size(void); + +void rt_hw_cpu_icache_invalidate_all(void); +void rt_hw_cpu_icache_invalidate(void *addr, rt_size_t size); +void rt_hw_cpu_dcache_clean_and_invalidate(void *addr, rt_size_t size); + +void rt_hw_icache_invalidate_all(void); + +void rt_hw_sync_cache_local(void *addr, int size); +#endif /* !__ASSEMBLY__ */ + +#endif /* __CACHE_H__ */ diff --git a/libcpu/risc-v/common/include/context_ext.h b/libcpu/risc-v/common/include/context_ext.h new file mode 100644 index 00000000000..6006af4e3b6 --- /dev/null +++ b/libcpu/risc-v/common/include/context_ext.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-10 RT-Thread the first version + */ + +#ifndef __CONTEXT_EXT_H__ +#define __CONTEXT_EXT_H__ + +#include + +#ifdef ARCH_RISCV_FPU +/* 32 fpu register */ +#define CTX_FPU_REG_NR 32 +#else +#define CTX_FPU_REG_NR 0 +#endif + +#ifdef __ASSEMBLY__ + +/** + * ================================== + * RISC-V D ISA (Floating) + * ================================== + */ + +#ifdef ARCH_RISCV_FPU +#define FPU_CTX_F0_OFF (SZREG * 0) /* offsetof(fpu_context_t, fpustatus.f[0]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F1_OFF (SZREG * 1) /* offsetof(fpu_context_t, fpustatus.f[1]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F2_OFF (SZREG * 2) /* offsetof(fpu_context_t, fpustatus.f[2]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F3_OFF (SZREG * 3) /* offsetof(fpu_context_t, fpustatus.f[3]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F4_OFF (SZREG * 4) /* offsetof(fpu_context_t, fpustatus.f[4]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F5_OFF (SZREG * 5) /* offsetof(fpu_context_t, fpustatus.f[5]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F6_OFF (SZREG * 6) /* offsetof(fpu_context_t, fpustatus.f[6]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F7_OFF (SZREG * 7) /* offsetof(fpu_context_t, fpustatus.f[7]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F8_OFF (SZREG * 8) /* offsetof(fpu_context_t, fpustatus.f[8]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F9_OFF (SZREG * 9) /* offsetof(fpu_context_t, fpustatus.f[9]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F10_OFF (SZREG * 10) /* offsetof(fpu_context_t, fpustatus.f[10]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F11_OFF (SZREG * 11) /* offsetof(fpu_context_t, fpustatus.f[11]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F12_OFF (SZREG * 12) /* offsetof(fpu_context_t, fpustatus.f[12]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F13_OFF (SZREG * 13) /* offsetof(fpu_context_t, fpustatus.f[13]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F14_OFF (SZREG * 14) /* offsetof(fpu_context_t, fpustatus.f[14]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F15_OFF (SZREG * 15) /* offsetof(fpu_context_t, fpustatus.f[15]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F16_OFF (SZREG * 16) /* offsetof(fpu_context_t, fpustatus.f[16]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F17_OFF (SZREG * 17) /* offsetof(fpu_context_t, fpustatus.f[17]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F18_OFF (SZREG * 18) /* offsetof(fpu_context_t, fpustatus.f[18]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F19_OFF (SZREG * 19) /* offsetof(fpu_context_t, fpustatus.f[19]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F20_OFF (SZREG * 20) /* offsetof(fpu_context_t, fpustatus.f[20]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F21_OFF (SZREG * 21) /* offsetof(fpu_context_t, fpustatus.f[21]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F22_OFF (SZREG * 22) /* offsetof(fpu_context_t, fpustatus.f[22]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F23_OFF (SZREG * 23) /* offsetof(fpu_context_t, fpustatus.f[23]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F24_OFF (SZREG * 24) /* offsetof(fpu_context_t, fpustatus.f[24]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F25_OFF (SZREG * 25) /* offsetof(fpu_context_t, fpustatus.f[25]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F26_OFF (SZREG * 26) /* offsetof(fpu_context_t, fpustatus.f[26]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F27_OFF (SZREG * 27) /* offsetof(fpu_context_t, fpustatus.f[27]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F28_OFF (SZREG * 28) /* offsetof(fpu_context_t, fpustatus.f[28]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F29_OFF (SZREG * 29) /* offsetof(fpu_context_t, fpustatus.f[29]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F30_OFF (SZREG * 30) /* offsetof(fpu_context_t, fpustatus.f[30]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F31_OFF (SZREG * 31) /* offsetof(fpu_context_t, fpustatus.f[31]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#endif /* ARCH_RISCV_FPU */ + +#endif /* __ASSEMBLY__ */ + +#ifdef ARCH_RISCV_VECTOR +#include "rvv_context.h" +#else /* !ARCH_RISCV_VECTOR */ +#define CTX_VECTOR_REG_NR 0 +#endif /* ARCH_RISCV_VECTOR */ + +#endif /* __CONTEXT_EXT_H__ */ diff --git a/libcpu/risc-v/common/include/cpu.h b/libcpu/risc-v/common/include/cpu.h new file mode 100755 index 00000000000..2c7e920d19f --- /dev/null +++ b/libcpu/risc-v/common/include/cpu.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __CPU_H__ +#define __CPU_H__ + +#include + +#ifndef RT_CPUS_NR +#define RT_CPUS_NR 1 +#endif + +struct cpu_ops_t +{ + const char *method; + int (*cpu_init)(rt_uint32_t id, void *param); + int (*cpu_boot)(rt_uint32_t id, rt_uint64_t entry); + void (*cpu_shutdown)(void); +}; + +extern rt_ubase_t boot_cpu_hartid; +extern void _secondary_cpu_entry(void); + +#if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) +extern char __percpu_real_end, __percpu_end, __percpu_start; +#endif /* RT_USING_SMP && ARCH_MM_MMU */ + +rt_ubase_t riscv_cpu_id_to_hartid(int cpu_id); +int riscv_hartid_to_cpu_id(rt_ubase_t hartid); +void riscv_hartid_remap_cpu_id(rt_ubase_t hartid, int cpu_id); + +#endif /* __CPU_H__ */ diff --git a/libcpu/risc-v/common/include/cpuport.h b/libcpu/risc-v/common/include/cpuport.h new file mode 100644 index 00000000000..10586374ef7 --- /dev/null +++ b/libcpu/risc-v/common/include/cpuport.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-03 Bernard The first version + */ + +#ifndef CPUPORT_H__ +#define CPUPORT_H__ + +#include + +#ifdef RT_USING_SMP +typedef union +{ + unsigned long slock; + struct __arch_tickets + { + unsigned short owner; + unsigned short next; + } tickets; +} rt_hw_spinlock_t; + +extern int riscv_master_cpu_id; +#define rt_hw_master_cpu_id() ((rt_ubase_t)riscv_master_cpu_id) +#endif /* RT_USING_SMP */ + +#define RISCV_FENCE(p, s) __asm__ volatile ("fence " #p "," #s:::"memory") + +#define rt_hw_barrier(...) RISCV_FENCE(iorw, iorw) +#define rt_hw_wmb() RISCV_FENCE(ir, ir) +#define rt_hw_rmb() RISCV_FENCE(ow, ow) + +rt_inline void rt_hw_dsb(void) +{ + __asm__ volatile ("fence":::"memory"); +} + +rt_inline void rt_hw_dmb(void) +{ + __asm__ volatile ("fence":::"memory"); +} + +rt_inline void rt_hw_isb(void) +{ +#ifndef ARCH_RISCV_DISABLE_FENCE_I + __asm__ volatile (OPC_FENCE_I:::"memory"); +#endif +} + +rt_inline void rt_hw_cpu_relax(void) +{ + __asm__ volatile (OPC_PAUSE_I); + rt_hw_barrier(); +} + +void _thread_start(void); + +#endif /* CPUPORT_H__ */ diff --git a/libcpu/risc-v/common/include/csr.h b/libcpu/risc-v/common/include/csr.h new file mode 100644 index 00000000000..df76731123f --- /dev/null +++ b/libcpu/risc-v/common/include/csr.h @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __CSR_H__ +#define __CSR_H__ + +#include + +/* Status register flags */ +#define SR_SIE _UL(0x00000002) /* Supervisor Interrupt Enable */ +#define SR_MIE _UL(0x00000008) /* Machine Interrupt Enable */ +#define SR_SPIE _UL(0x00000020) /* Previous Supervisor IE */ +#define SR_MPIE _UL(0x00000080) /* Previous Machine IE */ +#define SR_SPP _UL(0x00000100) /* Previously Supervisor */ +#define SR_MPP _UL(0x00001800) /* Previously Machine */ +#define SR_SUM _UL(0x00040000) /* Supervisor User Memory Access */ +#define SR_MXR _UL(0x00080000) /* Make eXecutable Readable */ + +#define SR_FS _UL(0x00006000) /* Floating-point Status */ +#define SR_FS_OFF _UL(0x00000000) +#define SR_FS_INITIAL _UL(0x00002000) +#define SR_FS_CLEAN _UL(0x00004000) +#define SR_FS_DIRTY _UL(0x00006000) + +#define SR_VS _UL(0x00000600) /* Vector Status */ +#define SR_VS_OFF _UL(0x00000000) +#define SR_VS_INITIAL _UL(0x00000200) +#define SR_VS_CLEAN _UL(0x00000400) +#define SR_VS_DIRTY _UL(0x00000600) + +#define SR_XS _UL(0x00018000) /* Extension Status */ +#define SR_XS_OFF _UL(0x00000000) +#define SR_XS_INITIAL _UL(0x00008000) +#define SR_XS_CLEAN _UL(0x00010000) +#define SR_XS_DIRTY _UL(0x00018000) + +#define SR_FS_VS (SR_FS | SR_VS) /* Vector and Floating-Point Unit */ + +#ifndef ARCH_CPU_64BIT +#define SR_SD _UL(0x80000000) /* FS/VS/XS dirty */ +#else +#define SR_SD _UL(0x8000000000000000) /* FS/VS/XS dirty */ +#endif + +#ifdef ARCH_CPU_64BIT +#define SR_UXL _UL(0x300000000) /* XLEN mask for U-mode */ +#define SR_UXL_32 _UL(0x100000000) /* XLEN = 32 for U-mode */ +#define SR_UXL_64 _UL(0x200000000) /* XLEN = 64 for U-mode */ +#endif + +/* SATP flags */ +#ifndef ARCH_CPU_64BIT +#define SATP_PPN _UL(0x003fffff) +#define SATP_MODE_BARE _UL(0x00000000) +#define SATP_MODE_32 _UL(0x80000000) +#define SATP_MODE_SHIFT 31 +#define SATP_MODE_MASK (_UL(0x1) << SATP_MODE_SHIFT) +#define SATP_ASID_BITS 9 +#define SATP_ASID_SHIFT 22 +#define SATP_ASID_MASK _UL(0x1ff) +#else +#define SATP_PPN _UL(0x00000fffffffffff) +#define SATP_MODE_BARE _UL(0x0000000000000000) +#define SATP_MODE_39 _UL(0x8000000000000000) +#define SATP_MODE_48 _UL(0x9000000000000000) +#define SATP_MODE_57 _UL(0xa000000000000000) +#define SATP_MODE_64 _UL(0xb000000000000000) +#define SATP_MODE_SHIFT 60 +#define SATP_MODE_MASK (_UL(0xf) << SATP_MODE_SHIFT) +#define SATP_ASID_BITS 16 +#define SATP_ASID_SHIFT 44 +#define SATP_ASID_MASK _UL(0xffff) +#endif + +/* Exception cause high bit - is an interrupt if set */ +#define CAUSE_IRQ_FLAG (_UL(1) << (__riscv_xlen - 1)) + +/* Interrupt causes (minus the high bit) */ +#define IRQ_S_SOFT 1 +#define IRQ_VS_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_S_TIMER 5 +#define IRQ_VS_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_S_EXT 9 +#define IRQ_VS_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_S_GEXT 12 +#define IRQ_PMU_OVF 13 +#define IRQ_LOCAL_MAX (IRQ_PMU_OVF + 1) +#define IRQ_LOCAL_MASK GENMASK((IRQ_LOCAL_MAX - 1), 0) + +/* Exception causes */ +#define EXC_INST_MISALIGNED 0 +#define EXC_INST_ACCESS 1 +#define EXC_INST_ILLEGAL 2 +#define EXC_BREAKPOINT 3 +#define EXC_LOAD_MISALIGNED 4 +#define EXC_LOAD_ACCESS 5 +#define EXC_STORE_MISALIGNED 6 +#define EXC_STORE_ACCESS 7 +#define EXC_SYSCALL 8 +#define EXC_HYPERVISOR_SYSCALL 9 +#define EXC_SUPERVISOR_SYSCALL 10 +#define EXC_INST_PAGE_FAULT 12 +#define EXC_LOAD_PAGE_FAULT 13 +#define EXC_STORE_PAGE_FAULT 15 +#define EXC_INST_GUEST_PAGE_FAULT 20 +#define EXC_LOAD_GUEST_PAGE_FAULT 21 +#define EXC_VIRTUAL_INST_FAULT 22 +#define EXC_STORE_GUEST_PAGE_FAULT 23 + +/* PMP configuration */ +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_A_TOR 0x08 +#define PMP_A_NA4 0x10 +#define PMP_A_NAPOT 0x18 +#define PMP_L 0x80 + +/* HSTATUS flags */ +#ifdef ARCH_CPU_64BIT +#define HSTATUS_VSXL _UL(0x300000000) +#define HSTATUS_VSXL_SHIFT 32 +#endif +#define HSTATUS_VTSR _UL(0x00400000) +#define HSTATUS_VTW _UL(0x00200000) +#define HSTATUS_VTVM _UL(0x00100000) +#define HSTATUS_VGEIN _UL(0x0003f000) +#define HSTATUS_VGEIN_SHIFT 12 +#define HSTATUS_HU _UL(0x00000200) +#define HSTATUS_SPVP _UL(0x00000100) +#define HSTATUS_SPV _UL(0x00000080) +#define HSTATUS_GVA _UL(0x00000040) +#define HSTATUS_VSBE _UL(0x00000020) + +/* HGATP flags */ +#define HGATP_MODE_OFF _UL(0) +#define HGATP_MODE_SV32X4 _UL(1) +#define HGATP_MODE_SV39X4 _UL(8) +#define HGATP_MODE_SV48X4 _UL(9) +#define HGATP_MODE_SV57X4 _UL(10) + +#define HGATP32_MODE_SHIFT 31 +#define HGATP32_VMID_SHIFT 22 +#define HGATP32_VMID GENMASK(28, 22) +#define HGATP32_PPN GENMASK(21, 0) + +#define HGATP64_MODE_SHIFT 60 +#define HGATP64_VMID_SHIFT 44 +#define HGATP64_VMID GENMASK(57, 44) +#define HGATP64_PPN GENMASK(43, 0) + +#define HGATP_PAGE_SHIFT 12 + +#ifdef ARCH_CPU_64BIT +#define HGATP_PPN HGATP64_PPN +#define HGATP_VMID_SHIFT HGATP64_VMID_SHIFT +#define HGATP_VMID HGATP64_VMID +#define HGATP_MODE_SHIFT HGATP64_MODE_SHIFT +#else +#define HGATP_PPN HGATP32_PPN +#define HGATP_VMID_SHIFT HGATP32_VMID_SHIFT +#define HGATP_VMID HGATP32_VMID +#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT +#endif + +/* VSIP & HVIP relation */ +#define VSIP_TO_HVIP_SHIFT (IRQ_VS_SOFT - IRQ_S_SOFT) +#define VSIP_VALID_MASK ((_UL(1) << IRQ_S_SOFT) | \ + (_UL(1) << IRQ_S_TIMER) | \ + (_UL(1) << IRQ_S_EXT) | \ + (_UL(1) << IRQ_PMU_OVF)) + +/* AIA CSR bits */ +#define TOPI_IID_SHIFT 16 +#define TOPI_IID_MASK GENMASK(11, 0) +#define TOPI_IPRIO_MASK GENMASK(7, 0) +#define TOPI_IPRIO_BITS 8 + +#define TOPEI_ID_SHIFT 16 +#define TOPEI_ID_MASK GENMASK(10, 0) +#define TOPEI_PRIO_MASK GENMASK(10, 0) + +#define ISELECT_IPRIO0 0x30 +#define ISELECT_IPRIO15 0x3f +#define ISELECT_MASK GENMASK(8, 0) + +#define HVICTL_VTI BIT(30) +#define HVICTL_IID GENMASK(27, 16) +#define HVICTL_IID_SHIFT 16 +#define HVICTL_DPR BIT(9) +#define HVICTL_IPRIOM BIT(8) +#define HVICTL_IPRIO GENMASK(7, 0) + +/* xENVCFG flags */ +#define ENVCFG_STCE (_ULL(1) << 63) +#define ENVCFG_PBMTE (_ULL(1) << 62) +#define ENVCFG_CBZE (_UL(1) << 7) +#define ENVCFG_CBCFE (_UL(1) << 6) +#define ENVCFG_CBIE_SHIFT 4 +#define ENVCFG_CBIE (_UL(0x3) << ENVCFG_CBIE_SHIFT) +#define ENVCFG_CBIE_ILL _UL(0x0) +#define ENVCFG_CBIE_FLUSH _UL(0x1) +#define ENVCFG_CBIE_INV _UL(0x3) +#define ENVCFG_FIOM _UL(0x1) + +/* Smstateen bits */ +#define SMSTATEEN0_AIA_IMSIC_SHIFT 58 +#define SMSTATEEN0_AIA_IMSIC (_ULL(1) << SMSTATEEN0_AIA_IMSIC_SHIFT) +#define SMSTATEEN0_AIA_SHIFT 59 +#define SMSTATEEN0_AIA (_ULL(1) << SMSTATEEN0_AIA_SHIFT) +#define SMSTATEEN0_AIA_ISEL_SHIFT 60 +#define SMSTATEEN0_AIA_ISEL (_ULL(1) << SMSTATEEN0_AIA_ISEL_SHIFT) +#define SMSTATEEN0_HSENVCFG_SHIFT 62 +#define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT) +#define SMSTATEEN0_SSTATEEN0_SHIFT 63 +#define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT) + +/* symbolic CSR names: */ +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f + +#define CSR_SCOUNTOVF 0xda0 + +#define CSR_SSTATUS 0x100 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 +#define CSR_SENVCFG 0x10a +#define CSR_SSTATEEN0 0x10c +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 +#define CSR_SATP 0x180 + +#define CSR_STIMECMP 0x14d +#define CSR_STIMECMPH 0x15d + +/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ +#define CSR_SISELECT 0x150 +#define CSR_SIREG 0x151 + +/* Supervisor-Level Interrupts (AIA) */ +#define CSR_STOPEI 0x15c +#define CSR_STOPI 0xdb0 + +/* Supervisor-Level High-Half CSRs (AIA) */ +#define CSR_SIEH 0x114 +#define CSR_SIPH 0x154 + +#define CSR_VSSTATUS 0x200 +#define CSR_VSIE 0x204 +#define CSR_VSTVEC 0x205 +#define CSR_VSSCRATCH 0x240 +#define CSR_VSEPC 0x241 +#define CSR_VSCAUSE 0x242 +#define CSR_VSTVAL 0x243 +#define CSR_VSIP 0x244 +#define CSR_VSATP 0x280 +#define CSR_VSTIMECMP 0x24d +#define CSR_VSTIMECMPH 0x25d + +#define CSR_HSTATUS 0x600 +#define CSR_HEDELEG 0x602 +#define CSR_HIDELEG 0x603 +#define CSR_HIE 0x604 +#define CSR_HTIMEDELTA 0x605 +#define CSR_HCOUNTEREN 0x606 +#define CSR_HGEIE 0x607 +#define CSR_HENVCFG 0x60a +#define CSR_HTIMEDELTAH 0x615 +#define CSR_HENVCFGH 0x61a +#define CSR_HTVAL 0x643 +#define CSR_HIP 0x644 +#define CSR_HVIP 0x645 +#define CSR_HTINST 0x64a +#define CSR_HGATP 0x680 +#define CSR_HGEIP 0xe12 + +/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ +#define CSR_HVIEN 0x608 +#define CSR_HVICTL 0x609 +#define CSR_HVIPRIO1 0x646 +#define CSR_HVIPRIO2 0x647 + +/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ +#define CSR_VSISELECT 0x250 +#define CSR_VSIREG 0x251 + +/* VS-Level Interrupts (H-extension with AIA) */ +#define CSR_VSTOPEI 0x25c +#define CSR_VSTOPI 0xeb0 + +/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ +#define CSR_HIDELEGH 0x613 +#define CSR_HVIENH 0x618 +#define CSR_HVIPH 0x655 +#define CSR_HVIPRIO1H 0x656 +#define CSR_HVIPRIO2H 0x657 +#define CSR_VSIEH 0x214 +#define CSR_VSIPH 0x254 + +/* Hypervisor stateen CSRs */ +#define CSR_HSTATEEN0 0x60c +#define CSR_HSTATEEN0H 0x61c + +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MENVCFG 0x30a +#define CSR_MENVCFGH 0x31a +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPADDR0 0x3b0 +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 + +/* Machine-Level Interrupts (CLIC) */ +#define CSR_MTVT 0x307 +#define CSR_MNXTI 0x345 + +/* Machine-Level Window to Indirectly Accessed Registers (AIA) */ +#define CSR_MISELECT 0x350 +#define CSR_MIREG 0x351 + +/* Machine-Level Interrupts (AIA) */ +#define CSR_MTOPEI 0x35c +#define CSR_MTOPI 0xfb0 + +/* Virtual Interrupts for Supervisor Level (AIA) */ +#define CSR_MVIEN 0x308 +#define CSR_MVIP 0x309 + +/* Machine-Level High-Half CSRs (AIA) */ +#define CSR_MIDELEGH 0x313 +#define CSR_MIEH 0x314 +#define CSR_MVIENH 0x318 +#define CSR_MVIPH 0x319 +#define CSR_MIPH 0x354 + +#define CSR_VSTART 0x8 +#define CSR_VCSR 0xf +#define CSR_VL 0xc20 +#define CSR_VTYPE 0xc21 +#define CSR_VLENB 0xc22 + +/* Scalar Crypto Extension - Entropy */ +#define CSR_SEED 0x015 +#define SEED_OPST_MASK _UL(0xc0000000) +#define SEED_OPST_BIST _UL(0x00000000) +#define SEED_OPST_WAIT _UL(0x40000000) +#define SEED_OPST_ES16 _UL(0x80000000) +#define SEED_OPST_DEAD _UL(0xc0000000) +#define SEED_ENTROPY_MASK _UL(0xffff) + +#ifdef ARCH_RISCV_M_MODE +#define CSR_STATUS CSR_MSTATUS +#define CSR_IE CSR_MIE +#define CSR_TVEC CSR_MTVEC +#define CSR_ENVCFG CSR_MENVCFG +#define CSR_SCRATCH CSR_MSCRATCH +#define CSR_EPC CSR_MEPC +#define CSR_CAUSE CSR_MCAUSE +#define CSR_TVAL CSR_MTVAL +#define CSR_IP CSR_MIP + +#define CSR_IEH CSR_MIEH +#define CSR_ISELECT CSR_MISELECT +#define CSR_IREG CSR_MIREG +#define CSR_IPH CSR_MIPH +#define CSR_TOPEI CSR_MTOPEI +#define CSR_TOPI CSR_MTOPI + +#define SR_IE SR_MIE +#define SR_PIE SR_MPIE +#define SR_PP SR_MPP + +#define RV_IRQ_SOFT IRQ_M_SOFT +#define RV_IRQ_TIMER IRQ_M_TIMER +#define RV_IRQ_EXT IRQ_M_EXT +#else /* ARCH_RISCV_M_MODE */ +#define CSR_STATUS CSR_SSTATUS +#define CSR_IE CSR_SIE +#define CSR_TVEC CSR_STVEC +#define CSR_ENVCFG CSR_SENVCFG +#define CSR_SCRATCH CSR_SSCRATCH +#define CSR_EPC CSR_SEPC +#define CSR_CAUSE CSR_SCAUSE +#define CSR_TVAL CSR_STVAL +#define CSR_IP CSR_SIP + +#define CSR_IEH CSR_SIEH +#define CSR_ISELECT CSR_SISELECT +#define CSR_IREG CSR_SIREG +#define CSR_IPH CSR_SIPH +#define CSR_TOPEI CSR_STOPEI +#define CSR_TOPI CSR_STOPI + +#define SR_IE SR_SIE +#define SR_PIE SR_SPIE +#define SR_PP SR_SPP + +#define RV_IRQ_SOFT IRQ_S_SOFT +#define RV_IRQ_TIMER IRQ_S_TIMER +#define RV_IRQ_EXT IRQ_S_EXT +#define RV_IRQ_PMU IRQ_PMU_OVF +#define SIP_LCOFIP (_AC(0x1, UL) << IRQ_PMU_OVF) +#endif /* !ARCH_RISCV_M_MODE */ + +/* IE/IP (Supervisor/Machine Interrupt Enable/Pending) flags */ +#define IE_SIE (_UL(0x1) << RV_IRQ_SOFT) +#define IE_TIE (_UL(0x1) << RV_IRQ_TIMER) +#define IE_EIE (_UL(0x1) << RV_IRQ_EXT) + +#ifndef __ASSEMBLY__ + +#ifdef __GNUC__ +#define csr_swap(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrw %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_read(csr) \ +({ \ + register rt_ubase_t __v; \ + __asm__ volatile ("csrr %0, " __ASM_STR(csr) \ + : "=r" (__v) : \ + : "memory"); \ + __v; \ +}) + +#define csr_write(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrw " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_set(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrs %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_read_or(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrsi %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "i" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_set(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrs " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) + +#define csr_read_clear(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrrc %0, " __ASM_STR(csr) ", %1" \ + : "=r" (__v) : "rK" (__v) \ + : "memory"); \ + __v; \ +}) + +#define csr_clear(csr, val) \ +({ \ + rt_ubase_t __v = (rt_ubase_t)(val); \ + __asm__ volatile ("csrc " __ASM_STR(csr) ", %0" \ + : : "rK" (__v) \ + : "memory"); \ +}) +#endif /* __GNUC__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* __CSR_H__ */ diff --git a/libcpu/risc-v/common/include/interrupt.h b/libcpu/risc-v/common/include/interrupt.h new file mode 100644 index 00000000000..49232437501 --- /dev/null +++ b/libcpu/risc-v/common/include/interrupt.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-01 Bernard The first version + * 2025-04-20 GuEe-GUI Port for not DM + */ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include + +#define IRQ_INTC(vector) (vector) +#ifdef RT_USING_SMP +#define IPI_INTC(vector) (ipi_intc_base + (vector)) +#endif + +#define IRQ_PLIC(vector) (irq_plic_base + (vector)) + +#define IRQ_CLIC(vector) (vector) +#ifdef RT_USING_SMP +#define IPI_CLIC(vector) (ipi_clic_base + (vector)) +#endif + +#ifdef RT_USING_SMP +extern rt_uint32_t ipi_intc_base; +extern rt_uint32_t ipi_clic_base; +#endif +extern rt_uint32_t irq_plic_base; + +void rt_hw_interrupt_handle(rt_ubase_t scause); + +#ifdef RT_USING_SMP +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler); +#endif + +#endif /* __INTERRUPT_H__ */ diff --git a/libcpu/risc-v/common/include/isa_ext.h b/libcpu/risc-v/common/include/isa_ext.h new file mode 100644 index 00000000000..f806421abac --- /dev/null +++ b/libcpu/risc-v/common/include/isa_ext.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __ISA_EXT_H__ +#define __ISA_EXT_H__ + +#include + +#define RISCV_ISA_EXT_I 0 +#define RISCV_ISA_EXT_M 1 +#define RISCV_ISA_EXT_A 2 +#define RISCV_ISA_EXT_F 3 +#define RISCV_ISA_EXT_D 4 +#define RISCV_ISA_EXT_Q 5 +#define RISCV_ISA_EXT_C 6 +#define RISCV_ISA_EXT_V 7 +#define RISCV_ISA_EXT_H 8 + +#define RISCV_ISA_EXT_BASE 26 + +#define RISCV_ISA_EXT_SSCOFPMF 26 +#define RISCV_ISA_EXT_SSTC 27 +#define RISCV_ISA_EXT_SVINVAL 28 +#define RISCV_ISA_EXT_SVPBMT 29 +#define RISCV_ISA_EXT_ZBB 30 +#define RISCV_ISA_EXT_ZICBOM 31 +#define RISCV_ISA_EXT_ZIHINTPAUSE 32 +#define RISCV_ISA_EXT_SVNAPOT 33 +#define RISCV_ISA_EXT_ZICBOZ 34 +#define RISCV_ISA_EXT_SMAIA 35 +#define RISCV_ISA_EXT_SSAIA 36 +#define RISCV_ISA_EXT_ZBA 37 +#define RISCV_ISA_EXT_ZBS 38 +#define RISCV_ISA_EXT_ZICNTR 39 +#define RISCV_ISA_EXT_ZICSR 40 +#define RISCV_ISA_EXT_ZIFENCEI 41 +#define RISCV_ISA_EXT_ZIHPM 42 +#define RISCV_ISA_EXT_SMSTATEEN 43 +#define RISCV_ISA_EXT_ZICOND 44 +#define RISCV_ISA_EXT_ZBC 45 +#define RISCV_ISA_EXT_ZBKB 46 +#define RISCV_ISA_EXT_ZBKC 47 +#define RISCV_ISA_EXT_ZBKX 48 +#define RISCV_ISA_EXT_ZKND 49 +#define RISCV_ISA_EXT_ZKNE 50 +#define RISCV_ISA_EXT_ZKNH 51 +#define RISCV_ISA_EXT_ZKR 52 +#define RISCV_ISA_EXT_ZKSED 53 +#define RISCV_ISA_EXT_ZKSH 54 +#define RISCV_ISA_EXT_ZKT 55 +#define RISCV_ISA_EXT_ZVBB 56 +#define RISCV_ISA_EXT_ZVBC 57 +#define RISCV_ISA_EXT_ZVKB 58 +#define RISCV_ISA_EXT_ZVKG 59 +#define RISCV_ISA_EXT_ZVKNED 60 +#define RISCV_ISA_EXT_ZVKNHA 61 +#define RISCV_ISA_EXT_ZVKNHB 62 +#define RISCV_ISA_EXT_ZVKSED 63 +#define RISCV_ISA_EXT_ZVKSH 64 +#define RISCV_ISA_EXT_ZVKT 65 +#define RISCV_ISA_EXT_ZFH 66 +#define RISCV_ISA_EXT_ZFHMIN 67 +#define RISCV_ISA_EXT_ZIHINTNTL 68 +#define RISCV_ISA_EXT_ZVFH 69 +#define RISCV_ISA_EXT_ZVFHMIN 70 +#define RISCV_ISA_EXT_ZFA 71 +#define RISCV_ISA_EXT_ZTSO 72 +#define RISCV_ISA_EXT_ZACAS 73 +#define RISCV_ISA_EXT_XANDESPMU 74 + +#define RISCV_ISA_EXT_MAX 75 +#define RISCV_ISA_EXT_INVALID RT_UINT32_MAX + +#ifdef ARCH_RISCV_M_MODE +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA +#else +#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA +#endif + +void riscv_isa_ext_set_raw(rt_uint32_t isa); +void riscv_isa_ext_clear_raw(rt_uint32_t isa); +rt_bool_t riscv_isa_ext_test_raw(rt_uint32_t isa); + +#define riscv_isa_ext_set(isa) riscv_isa_ext_set_raw(RISCV_ISA_EXT_##isa) +#define riscv_isa_ext_clear(isa) riscv_isa_ext_clear_raw(RISCV_ISA_EXT_##isa) +#define riscv_isa_ext_test(isa) riscv_isa_ext_test_raw(RISCV_ISA_EXT_##isa) + +#endif /* __ISA_EXT_H__ */ diff --git a/libcpu/risc-v/common/include/mmu.h b/libcpu/risc-v/common/include/mmu.h new file mode 100644 index 00000000000..8839c584677 --- /dev/null +++ b/libcpu/risc-v/common/include/mmu.h @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2023-10-12 Shell Add permission control API + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __MMU_H__ +#define __MMU_H__ + +#include +#include + +#ifndef __ASSEMBLY__ +#include + +/* Normal memory wra mapping type */ +#define NORMAL_MEM 0 +/* Normal nocache memory mapping type */ +#define NORMAL_NOCACHE_MEM 1 +/* Device mapping type */ +#define DEVICE_MEM 2 + +struct mem_desc +{ + unsigned long vaddr_start; + unsigned long vaddr_end; + unsigned long paddr_start; + unsigned long attr; + struct rt_varea varea; +}; + +#ifdef __HAS_MMU_VENDOR__ +#include +#endif + +#endif /* !__ASSEMBLY__ */ + +#define RT_HW_MMU_PROT_READ 1 +#define RT_HW_MMU_PROT_WRITE 2 +#define RT_HW_MMU_PROT_EXECUTE 4 +#define RT_HW_MMU_PROT_KERNEL 8 +#define RT_HW_MMU_PROT_USER 16 +#define RT_HW_MMU_PROT_CACHE 32 + +/* Page table entry (PTE) fields */ +#define PTE_V BIT(0) /* Valid */ +#define PTE_R BIT(1) /* Read */ +#define PTE_W BIT(2) /* Write */ +#define PTE_X BIT(3) /* Execute */ +#define PTE_U BIT(4) /* User */ +#define PTE_G BIT(5) /* Global */ +#define PTE_A BIT(6) /* Accessed */ +#define PTE_D BIT(7) /* Dirty */ +#define PTE_SOFT GENMASK(9, 8) /* Reserved for Software */ + +#define PTE_BITS 10 + +#define PTE_ATTR_NONE _UL(0) +#define PTE_ATTR_RW (PTE_R | PTE_W) +#define PTE_ATTR_RWX (PTE_ATTR_RW | PTE_X) +#define PTE_ATTR_KERNEL (PTE_V | PTE_ATTR_RWX | PTE_A | PTE_D) +#define PTE_ATTR_USER (PTE_ATTR_KERNEL | PTE_U) + +#if !defined(__HAS_MMU_VENDOR__) && __riscv_xlen != 32 +#define SVPBMT_SHIFT 61 /* ISA SVPBMT */ + +#define PTE_VENDOR_PMA (0x0ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_NOCACHE (0x1ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_IO (0x2ULL << SVPBMT_SHIFT) +#define PTE_VENDOR_MTMASK (0x3ULL << SVPBMT_SHIFT) +#endif /* !__HAS_MMU_VENDOR__ && __riscv_xlen != 32 */ + +#ifndef PTE_VENDOR_PMA +#define PTE_VENDOR_PMA PTE_ATTR_NONE +#endif + +#ifndef PTE_VENDOR_NOCACHE +#define PTE_VENDOR_NOCACHE PTE_ATTR_NONE +#endif + +#ifndef PTE_VENDOR_IO +#define PTE_VENDOR_IO PTE_ATTR_NONE +#endif + +#ifndef MMU_VENDOR_MAP_K_ROCB +#define MMU_VENDOR_MAP_K_ROCB ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_K_RO +#define MMU_VENDOR_MAP_K_RO ((PTE_ATTR_KERNEL & ~PTE_W) | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_K_RWCB +#define MMU_VENDOR_MAP_K_RWCB (PTE_ATTR_KERNEL | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_K_RW +#define MMU_VENDOR_MAP_K_RW (PTE_ATTR_KERNEL | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_K_DEVICE +#define MMU_VENDOR_MAP_K_DEVICE ((PTE_ATTR_KERNEL & ~PTE_X) | PTE_VENDOR_IO) +#endif +#ifndef MMU_VENDOR_MAP_U_ROCB +#define MMU_VENDOR_MAP_U_ROCB ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_U_RO +#define MMU_VENDOR_MAP_U_RO ((PTE_ATTR_USER & ~PTE_W) | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_U_RWCB +#define MMU_VENDOR_MAP_U_RWCB (PTE_ATTR_USER | PTE_VENDOR_PMA) +#endif +#ifndef MMU_VENDOR_MAP_U_RW +#define MMU_VENDOR_MAP_U_RW (PTE_ATTR_USER | PTE_VENDOR_NOCACHE) +#endif +#ifndef MMU_VENDOR_MAP_U_DEVICE +#define MMU_VENDOR_MAP_U_DEVICE ((PTE_ATTR_USER & ~PTE_X) | PTE_VENDOR_IO) +#endif +#ifndef MMU_VENDOR_MAP_EARLY +#define MMU_VENDOR_MAP_EARLY (PTE_RWX | PTE_G | PTE_V) +#endif + +#define MMU_MAP_K_ROCB MMU_VENDOR_MAP_K_ROCB +#define MMU_MAP_K_RO MMU_VENDOR_MAP_K_RO +#define MMU_MAP_K_RWCB MMU_VENDOR_MAP_K_RWCB +#define MMU_MAP_K_RW MMU_VENDOR_MAP_K_RW +#define MMU_MAP_K_DEVICE MMU_VENDOR_MAP_K_DEVICE +#define MMU_MAP_U_ROCB MMU_VENDOR_MAP_U_ROCB +#define MMU_MAP_U_RO MMU_VENDOR_MAP_U_RO +#define MMU_MAP_U_RWCB MMU_VENDOR_MAP_U_RWCB +#define MMU_MAP_U_RW MMU_VENDOR_MAP_U_RW +#define MMU_MAP_U_DEVICE MMU_VENDOR_MAP_U_DEVICE + +#define MMU_MAP_ERROR_VANOTALIGN -1 +#define MMU_MAP_ERROR_PANOTALIGN -2 +#define MMU_MAP_ERROR_NOPAGE -3 +#define MMU_MAP_ERROR_CONFLICT -4 + +#define ARCH_VADDR_WIDTH rt_hw_arch_vaddr_width +#define ARCH_ADDRESS_WIDTH_BITS __riscv_xlen + +#define ARCH_MAP_FAILED _AT(void *, _ULL(-1)) + +#define ARCH_EARLY_MAP_SIZE 0x80000000 + +#ifndef __ASSEMBLY__ + +struct rt_aspace; + +extern rt_uint8_t rt_hw_arch_vaddr_width; + +void *rt_hw_mmu_tbl_get(void); +void rt_hw_mmu_tbl_set(unsigned long tbl); +int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, + rt_ubase_t *vtable, rt_ubase_t pv_off); +void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr); +void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size, + size_t attr); +void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size); +void rt_hw_aspace_switch(rt_aspace_t aspace); +void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr); + +int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, + enum rt_mmu_cntl cmd); + +void *rt_hw_mmu_pgtbl_create(void); +void rt_hw_mmu_pgtbl_delete(void *pgtbl); + +#ifndef MMU_VENDOR_ATTR_RM_PERM_IMPL +/** + * @brief Remove permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be removed + * @return size_t returned attribution + */ +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; + /* remove write permission for kernel */ + case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: + attr &= ~PTE_W; + break; + default: + RT_ASSERT(0); + } + return attr; +} +#endif /* MMU_VENDOR_ATTR_RM_PERM_IMPL */ + +#ifndef MMU_VENDOR_ATTR_ADD_PERM_IMPL +/** + * @brief Add permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be added + * @return size_t returned attribution + */ +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); + } + return attr; +} +#endif /* MMU_VENDOR_ATTR_ADD_PERM_IMPL */ + +#ifndef MMU_VENDOR_ATTR_TEST_PERM_IMPL +/** + * @brief Test permission from attribution + * + * @param attr architecture specified mmu attribution + * @param prot protect that will be test + * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE + */ +rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) +{ + rt_bool_t rc = 0; + + 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); + } + + if (rc && (prot & RT_HW_MMU_PROT_USER)) + { + rc = !!(attr & PTE_U); + } + return rc; +} +#endif /* MMU_VENDOR_ATTR_TEST_PERM_IMPL */ + +#endif /* !__ASSEMBLY__ */ + +#endif /* __MMU_H__ */ diff --git a/libcpu/risc-v/common/include/opcode.h b/libcpu/risc-v/common/include/opcode.h new file mode 100644 index 00000000000..f98b529d48b --- /dev/null +++ b/libcpu/risc-v/common/include/opcode.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-09 Shell Add portable asm support + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __OPCODE_H__ +#define __OPCODE_H__ + +#include + +#include +#ifdef __HAS_OPCODE_VENDOR__ +#include +#endif + +/** + * @brief binary opcode pseudo operations + * Used to bypass toolchain restriction on extension ISA + * + */ + +/** + * @brief RISC-V instruction formats + */ + +#define OPCODE_MISC_MEM 15 +#define OPCODE_SYSTEM 115 + +#ifndef __OPC_INSN_FORMAT_R +/** + * R type: .insn r opcode6, func3, func7, rd, rs1, rs2 + * + * +-------+-----+-----+-------+----+---------+ + * | func7 | rs2 | rs1 | func3 | rd | opcode6 | + * +-------+-----+-----+-------+----+---------+ + * 31 25 20 15 12 7 0 + */ +#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \ + ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2)"\n\t" +#endif /* !__OPC_INSN_FORMAT_R */ + +#ifndef __OPC_INSN_FORMAT_I +/** + * I type: .insn i opcode6, func3, rd, rs1, simm12 + * + * +--------+-----+-------+----+---------+ + * | simm12 | rs1 | func3 | rd | opcode6 | + * +--------+-----+-------+----+---------+ + * 31 20 15 12 7 0 + */ +#define __OPC_INSN_FORMAT_I(opcode, func3, rd, rs1, simm12) \ + ".insn i "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(simm12)"\n\t" +#endif /* !__OPC_INSN_FORMAT_I */ + +#ifndef OPC_CBO_INVAL +#define OPC_CBO_INVAL(base) __OPC_INSN_FORMAT_I(OPCODE_MISC_MEM, 2, x0, base, 0) +#endif + +#ifndef OPC_CBO_CLEAN +#define OPC_CBO_CLEAN(base) __OPC_INSN_FORMAT_I(OPCODE_MISC_MEM, 2, x0, base, 1) +#endif + +#ifndef OPC_FENCE_I +#ifdef ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA +#define OPC_FENCE_I __ASM_STR(fence.i) +#else /* !ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA */ +#define OPC_FENCE_I __ASM_STR(.long 0x0000100f) +#endif /* ARCH_TOOLCHAIN_HAS_ZIFENCEI_ISA */ +#endif /* !OPC_FENCE_I */ + +#ifndef OPC_PAUSE_I +#ifdef ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE +#define OPC_PAUSE_I __ASM_STR(pause) +#else /* !ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE */ +#define OPC_PAUSE_I __ASM_STR(.4byte 0x0100000f) +#endif /* ARCH_TOOLCHAIN_HAS_ZIHINTPAUSE */ +#endif /* !OPC_PAUSE_I */ + +#endif /* __OPCODE_H__ */ \ No newline at end of file diff --git a/libcpu/risc-v/common/include/page_def.h b/libcpu/risc-v/common/include/page_def.h new file mode 100644 index 00000000000..ba68d85ee77 --- /dev/null +++ b/libcpu/risc-v/common/include/page_def.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#ifndef __PAGE_DEF_H__ +#define __PAGE_DEF_H__ + +#include + +#ifndef ARCH_PAGE_SHIFT +#define ARCH_PAGE_SHIFT 12 +#elif ARCH_PAGE_SHIFT != 12 +#warning Make sure you fully understand what you are doing +#endif +#define ARCH_PAGE_SIZE (_UL(1) << ARCH_PAGE_SHIFT) +#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1) + +#define SUPPER_PAGE_SIZE 0x200000 +#define SUPPER_PAGE_MASK (SUPPER_PAGE_SIZE - 1) + +#endif /* __PAGE_DEF_H__ */ diff --git a/libcpu/risc-v/common/include/riscv_timer.h b/libcpu/risc-v/common/include/riscv_timer.h new file mode 100755 index 00000000000..353ebc144d8 --- /dev/null +++ b/libcpu/risc-v/common/include/riscv_timer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-28 Bernard The unify RISC-V porting code. + */ + +#ifndef __RISCV_TIMER_H__ +#define __RISCV_TIMER_H__ + +#include + +void riscv_timer_set_frequency(rt_uint32_t freq); +rt_uint32_t riscv_timer_get_frequency(void); + +rt_uint64_t riscv_timer_rdtime(void); + +void riscv_timer_isr(void); + +void riscv_timer_init(void); +void riscv_timer_probe(void *clint_timer_cmp, void *clint_timer_val); + +void riscv_timer_us_delay(rt_uint32_t us); + +#endif /* __RISCV_TIMER_H__ */ diff --git a/libcpu/risc-v/common64/sbi.h b/libcpu/risc-v/common/include/sbi.h similarity index 98% rename from libcpu/risc-v/common64/sbi.h rename to libcpu/risc-v/common/include/sbi.h index 45853871a89..e571157a1b4 100644 --- a/libcpu/risc-v/common64/sbi.h +++ b/libcpu/risc-v/common/include/sbi.h @@ -49,6 +49,7 @@ #define _MACHINE_SBI_H_ #include +#include #include /* SBI Specification Version */ @@ -171,6 +172,10 @@ extern unsigned long sbi_spec_version; extern unsigned long sbi_impl_id; extern unsigned long sbi_impl_version; +extern bool has_time_extension; +extern bool has_ipi_extension; +extern bool has_rfnc_extension; + static __inline long sbi_probe_extension(long id) { diff --git a/libcpu/risc-v/common/include/setup.h b/libcpu/risc-v/common/include/setup.h new file mode 100644 index 00000000000..f04d839a11c --- /dev/null +++ b/libcpu/risc-v/common/include/setup.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-02-21 GuEe-GUI first version + */ + +#ifndef __SETUP_H__ +#define __SETUP_H__ + +void rt_hw_common_setup(void); + +#endif /* __SETUP_H__ */ diff --git a/libcpu/risc-v/common/include/stack.h b/libcpu/risc-v/common/include/stack.h new file mode 100644 index 00000000000..4efefaed797 --- /dev/null +++ b/libcpu/risc-v/common/include/stack.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2021-11-18 JasonHu add fpu member + * 2022-10-22 Shell Support kernel mode RVV + */ + +#ifndef __STACK_H__ +#define __STACK_H__ + +#include + +#include + +#ifdef ARCH_RISCV_FPU + #define K_XSTATUS_DEFAULT_BASE (SR_PP | SR_PIE | SR_SUM | SR_FS) +#else + #define K_XSTATUS_DEFAULT_BASE (SR_PP | SR_PIE | SR_SUM) +#endif + +#ifdef ARCH_RISCV_VECTOR + #define K_XSTATUS_DEFAULT (K_XSTATUS_DEFAULT_BASE | SR_VS) +#else + #define K_XSTATUS_DEFAULT K_XSTATUS_DEFAULT_BASE +#endif + +#define CTX_GENERAL_REG_NR 34 +#define CTX_ALL_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR + CTX_VECTOR_REG_NR) + +#define FRAME_OFF_XSTATUS (2 * SZREG) +#define FRAME_OFF_XCAUSE (3 * SZREG) +#define FRAME_OFF_SP (32 * SZREG) +#define FRAME_OFF_GP (4 * SZREG) + +/* Switch frame */ +#define RT_HW_SWITCH_CONTEXT_XSTATUS 0 +#define RT_HW_SWITCH_CONTEXT_S1 1 +#define RT_HW_SWITCH_CONTEXT_S0 2 +#define RT_HW_SWITCH_CONTEXT_RA 3 +#define RT_HW_SWITCH_CONTEXT_TP 4 +#define RT_HW_SWITCH_CONTEXT_SIZE 8 /* Padding for alignment */ + +#ifndef __ASSEMBLY__ +typedef struct rt_hw_switch_frame +{ + rt_uint64_t regs[RT_HW_SWITCH_CONTEXT_SIZE]; +} *rt_hw_switch_frame_t; + +struct rt_hw_stack_frame +{ + rt_ubase_t epc; /* epc - epc - program counter */ + rt_ubase_t ra; /* x1 - ra - return address for jumps */ + rt_ubase_t xstatus; /* - supervisor/machine status register */ + rt_ubase_t xcause; /* - supervisor/machine cause register */ + rt_ubase_t gp; /* x3 - gp - global pointer */ + rt_ubase_t tp; /* x4 - tp - thread pointer */ + rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ + rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ + rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ + rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ + rt_ubase_t s1; /* x9 - s1 - saved register 1 */ + rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ + rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ + rt_ubase_t a2; /* x12 - a2 - function argument 2 */ + rt_ubase_t a3; /* x13 - a3 - function argument 3 */ + rt_ubase_t a4; /* x14 - a4 - function argument 4 */ + rt_ubase_t a5; /* x15 - a5 - function argument 5 */ +#ifndef ARCH_RISCV_32E + rt_ubase_t a6; /* x16 - a6 - function argument 6 */ + rt_ubase_t a7; /* x17 - s7 - function argument 7 */ + rt_ubase_t s2; /* x18 - s2 - saved register 2 */ + rt_ubase_t s3; /* x19 - s3 - saved register 3 */ + rt_ubase_t s4; /* x20 - s4 - saved register 4 */ + rt_ubase_t s5; /* x21 - s5 - saved register 5 */ + rt_ubase_t s6; /* x22 - s6 - saved register 6 */ + rt_ubase_t s7; /* x23 - s7 - saved register 7 */ + rt_ubase_t s8; /* x24 - s8 - saved register 8 */ + rt_ubase_t s9; /* x25 - s9 - saved register 9 */ + rt_ubase_t s10; /* x26 - s10 - saved register 10 */ + rt_ubase_t s11; /* x27 - s11 - saved register 11 */ + rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ + rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ + rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ + rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ +#endif /* !ARCH_RISCV_32E */ + + rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */ + +#ifdef ARCH_RISCV_FPU + rt_ubase_t f[CTX_FPU_REG_NR]; /* f0~f31 */ +#endif +#ifdef ARCH_RISCV_VECTOR + rt_ubase_t v[CTX_VECTOR_REG_NR]; +#endif +}; +#endif /* __ASSEMBLY__ */ + +#endif /* __STACK_H__ */ diff --git a/libcpu/risc-v/common/include/tlb.h b/libcpu/risc-v/common/include/tlb.h new file mode 100644 index 00000000000..e57cfc7f817 --- /dev/null +++ b/libcpu/risc-v/common/include/tlb.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-11-28 WangXiaoyao the first version + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __TLB_H__ +#define __TLB_H__ + +#include + +#include +#include +#include +#include + +#define SFENCE_VMA_ASID(asid) \ + __asm__ volatile ("sfence.vma x0, %0"::"r"(asid) : "memory"); + +#define SFENCE_VMA_ADDR_INV(start) \ + __asm__ volatile ("sfence.vma %0, zero" ::"r"(start) : "memory"); + +rt_inline void rt_hw_tlb_invalidate_all(void) +{ + union + { + unsigned long mask; + unsigned long all; + } flush = { -1UL }; + + if (sbi_remote_sfence_vma(&flush.mask, flush.all, 0, flush.all) == SBI_SUCCESS) + { + return; + } + + LOG_W("TLB invalidate all failed"); +} + +rt_inline void rt_hw_tlb_invalidate_all_local(void) +{ + __asm__ volatile ("sfence.vma" ::: "memory"); +} + +rt_inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace) +{ +#if defined(ARCH_RISCV_DISABLE_SFENCE_VMA_ASID) || !defined(ARCH_USING_ASID) + rt_hw_tlb_invalidate_all_local(); +#else + rt_uint64_t asid_value = aspace->asid & SATP_ASID_MASK; + + SFENCE_VMA_ASID(asid_value); +#endif +} + +rt_inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start) +{ + RT_UNUSED(aspace); + SFENCE_VMA_ADDR_INV(start); +} + +rt_inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start, + size_t size, size_t stride) +{ + /* huge page is taking as normal page */ + if (size <= ARCH_PAGE_SIZE) + { + rt_hw_tlb_invalidate_page(aspace, start); + } + else + { + rt_hw_tlb_invalidate_aspace(aspace); + } +} + +#endif /* __TLB_H__ */ diff --git a/libcpu/risc-v/common/interrupt.c b/libcpu/risc-v/common/interrupt.c new file mode 100644 index 00000000000..2f7ad0398be --- /dev/null +++ b/libcpu/risc-v/common/interrupt.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-01 Bernard The first version + * 2025-04-20 GuEe-GUI Port for not DM + */ + +#include +#include + +#include +#include +#include +#include + +#define INTC_TYPE_RISCV 0 +#define INTC_TYPE_ANDESTECH 1 +#define INTC_TYPE_CLIC 2 + +#ifndef INTC_TYPE +#define INTC_TYPE INTC_TYPE_RISCV +#endif + +#define PIC_DISABLE_DM + +#if INTC_TYPE != INTC_TYPE_CLIC +/* --------------------------- PLIC and Local INTC -------------------------- */ + +#ifndef PLIC_QUICKS +#define PLIC_QUICKS 0 +#endif + +#include "pic/pic-sifive-plic.c" +#undef DBG_TAG +#undef DBG_LVL +#include "pic/pic-riscv-intc.c" +#undef DBG_TAG +#undef DBG_LVL + +#ifdef RT_USING_SMP +rt_uint32_t ipi_intc_base; +#endif +rt_uint32_t irq_plic_base; + +static struct plic *system_plic; + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ +/* ---------------------------------- CLIC ---------------------------------- */ + +#ifndef CLIC_QUICKS +#define CLIC_QUICKS 0 +#endif + +/* + * CLIC can be used alongside INTC and PLIC in a SoC. + * However, we typically assume that NOT DM systems are MCUs, + * and they only use CLIC for interrupt handling. + */ +#include "pic/pic-riscv-clic.c" +#undef DBG_TAG +#undef DBG_LVL + +#ifdef RT_USING_SMP +rt_uint32_t ipi_clic_base; +#endif +static struct riscv_clic *system_clic; + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ + +#define DBG_TAG "hw.irq" +#define DBG_LVL DBG_INFO + +static struct rt_irq_desc irq_desc[MAX_HANDLERS]; + +rt_weak void rt_hw_interrupt_init(void) +{ + union + { + struct { rt_ubase_t base, size }; + rt_ubase_t range[2]; + } mmio; + +#ifdef RT_USING_SMP + if (rt_hw_cpu_id() != riscv_hartid_to_cpu_id(boot_cpu_hartid)) + { + goto _percpu_init; + } +#endif /* RT_USING_SMP */ + +#if INTC_TYPE != INTC_TYPE_CLIC +/* --------------------------- PLIC and Local INTC -------------------------- */ + + riscv_intc_common_init(&system_rv_intc, INTC_TYPE == INTC_TYPE_ANDESTECH); + + irq_plic_base = rv_intc->irqs_def_count + rv_intc->irqs_count; +#ifdef RT_USING_SMP + ipi_intc_base = irq_plic_base - RT_MAX_IPI; +#endif + +#ifdef ARCH_RISCV_M_MODE + mmio.range[0] = platform_get_clint_base(); + mmio.range[1] = platform_get_clint_size(); + riscv_clint_common_init(mmio.range, 1); +#endif + + RT_ASSERT(irq_plic_base < MAX_HANDLERS); + + mmio.base = platform_get_plic_base(); + mmio.size = platform_get_plic_size(); + + system_plic = plic_common_init(mmio.base, mmio.size, MAX_HANDLERS - irq_plic_base, PLIC_QUICKS); + + RT_ASSERT(system_plic != RT_NULL); + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ +/* ---------------------------------- CLIC ---------------------------------- */ + + if (rt_hw_cpu_id() != riscv_hartid_to_cpu_id(boot_cpu_hartid)) + { + return; + } + +#ifdef ARCH_RISCV_M_MODE + mmio.range[0] = platform_get_clint_base(); + mmio.range[1] = platform_get_clint_size(); + riscv_clint_common_init(mmio.range, 1); +#endif + + mmio.base = platform_get_clic_base(); + mmio.size = platform_get_clic_size(); + + system_clic = clic_common_init(mmio.base, mmio.size, CLIC_QUICKS); + + RT_ASSERT(system_clic != RT_NULL); + +#ifdef RT_USING_SMP + ipi_intc_base = system_clic->ipi_base; +#endif + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ + +#ifdef RT_USING_SMP +_percpu_init: +#endif +#if INTC_TYPE != INTC_TYPE_CLIC + + plic_percpu_common_init(system_plic); + + rt_hw_interrupt_umask(IRQ_INTC(IRQ_S_EXT)); + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ + + riscv_clic_percpu_common_init(system_clic); + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ +} + +rt_weak void rt_hw_interrupt_mask(int vector) +{ +#if INTC_TYPE != INTC_TYPE_CLIC +/* --------------------------- PLIC and Local INTC -------------------------- */ + + if (vector >= irq_plic_base) + { + vector -= irq_plic_base; + + LOG_D("PLIC IRQ %d %s on CPU#%d", vector, "enabled", rt_hw_cpu_id()); + plic_irq_mask_raw(rt_hw_cpu_id(), vector); + } + else + { + #if INTC_TYPE == INTC_TYPE_RISCV + riscv_intc_irq_mask_raw(&system_rv_intc, vector); + #else + andes_intc_irq_mask_raw(&system_rv_intc, vector); + #endif + } + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ +/* ---------------------------------- CLIC ---------------------------------- */ + + riscv_clic_irq_mask_raw(system_clic, vector); + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ +} + +rt_weak void rt_hw_interrupt_umask(int vector) +{ +#if INTC_TYPE != INTC_TYPE_CLIC +/* --------------------------- PLIC and Local INTC -------------------------- */ + + if (vector >= irq_plic_base) + { + vector -= irq_plic_base; + + LOG_D("PLIC IRQ %d %s on CPU#%d", vector, "disabled", rt_hw_cpu_id()); + plic_irq_unmask_raw(rt_hw_cpu_id(), vector); + } + else + { + #if INTC_TYPE == INTC_TYPE_RISCV + riscv_intc_irq_unmask_raw(&system_rv_intc, vector); + #else + andes_intc_irq_unmask_raw(&system_rv_intc, vector); + #endif + } + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ +/* ---------------------------------- CLIC ---------------------------------- */ + + riscv_clic_irq_unmask_raw(system_clic, vector); + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ +} + +rt_weak rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS) + { + old_handler = irq_desc[vector].handler; + + if (handler != RT_NULL) + { + irq_desc[vector].handler = (rt_isr_handler_t)handler; + irq_desc[vector].param = param; + #ifdef RT_USING_INTERRUPT_INFO + rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); + irq_desc[vector].counter = 0; + #endif + } + } + + return old_handler; +} + +#ifdef RT_USING_SMP +rt_weak void rt_hw_ipi_handler_install(int ipi_hwirq, rt_isr_handler_t ipi_isr_handler) +{ + rt_hw_interrupt_install(ipi_hwirq, ipi_isr_handler, RT_NULL, "IPI_HANDLER"); +} + +rt_weak void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask) +{ + RT_BITMAP_DECLARE(cpu_masks, RT_CPUS_NR) = { cpu_mask }; + +#if INTC_TYPE != INTC_TYPE_CLIC + riscv_intc_irq_send_ipi_raw(&system_rv_intc, ipi_intc_base + ipi_vector, cpu_masks); +#else + riscv_clic_irq_send_ipi_raw(system_clic, ipi_clic_base + ipi_vector, cpu_masks); +#endif +} +#endif /* RT_USING_SMP */ + +static rt_bool_t handler_irq(int hwirq, void *data) +{ + struct rt_irq_desc *irq_desc = &irq_desc[hwirq + (rt_ubase_t)data]; + + if (irq_desc->handler) + { + irq_desc->handler(hwirq, irq_desc->param); + + return RT_TRUE; + } + + return RT_FALSE; +} + +static rt_bool_t handler_plic_irq(int hwirq, void *data) +{ + plic_irq_ack_or_eoi(rt_hw_cpu_id(), hwirq); + + return handler_irq(hwirq, data) +} + +rt_weak void rt_hw_interrupt_handle(rt_uint32_t vector, void *param) +{ + /* vector is equal to scause from trap */ + +#if INTC_TYPE != INTC_TYPE_CLIC +/* --------------------------- PLIC and Local INTC -------------------------- */ + + if (vector == IRQ_S_EXT) + { + plic_handler_isr_raw(system_plic, handler_plic_irq, irq_plic_base); + } + else + { + #if INTC_TYPE == INTC_TYPE_RISCV + riscv_intc_handler_raw(&system_rv_intc, vector, handler_irq, RT_NULL); + #else + riscv_intc_aia_handler_raw(&system_rv_intc, handler_irq, RT_NULL); + #endif + } + +#else /* INTC_TYPE == INTC_TYPE_CLIC */ +/* ---------------------------------- CLIC ---------------------------------- */ + + riscv_clic_handler_isr_raw(system_clic, vector, handler_irq, RT_NULL); + +#endif /* INTC_TYPE != INTC_TYPE_CLIC */ +} diff --git a/libcpu/risc-v/common/interrupt_gcc.S b/libcpu/risc-v/common/interrupt_gcc.S deleted file mode 100644 index fc916dd821a..00000000000 --- a/libcpu/risc-v/common/interrupt_gcc.S +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2023/01/17 WangShun The first version - * 2023/03/19 Flyingcys Add riscv_32e support - * 2023/08/09 HPMicro Fix the issue t0 was modified unexpectedly before being saved - */ -#define __ASSEMBLY__ -#include "cpuport.h" - - .section .text.entry, "ax" -#if defined(SOC_SERIES_GD32VF103V) - .align 6 -#else - .align 2 -#endif - .global SW_handler - -SW_handler: - csrci mstatus, 0x8 -#ifdef ARCH_RISCV_FPU - addi sp, sp, -32 * FREGBYTES - FSTORE f0, 0 * FREGBYTES(sp) - FSTORE f1, 1 * FREGBYTES(sp) - FSTORE f2, 2 * FREGBYTES(sp) - FSTORE f3, 3 * FREGBYTES(sp) - FSTORE f4, 4 * FREGBYTES(sp) - FSTORE f5, 5 * FREGBYTES(sp) - FSTORE f6, 6 * FREGBYTES(sp) - FSTORE f7, 7 * FREGBYTES(sp) - FSTORE f8, 8 * FREGBYTES(sp) - FSTORE f9, 9 * FREGBYTES(sp) - FSTORE f10, 10 * FREGBYTES(sp) - FSTORE f11, 11 * FREGBYTES(sp) - FSTORE f12, 12 * FREGBYTES(sp) - FSTORE f13, 13 * FREGBYTES(sp) - FSTORE f14, 14 * FREGBYTES(sp) - FSTORE f15, 15 * FREGBYTES(sp) - FSTORE f16, 16 * FREGBYTES(sp) - FSTORE f17, 17 * FREGBYTES(sp) - FSTORE f18, 18 * FREGBYTES(sp) - FSTORE f19, 19 * FREGBYTES(sp) - FSTORE f20, 20 * FREGBYTES(sp) - FSTORE f21, 21 * FREGBYTES(sp) - FSTORE f22, 22 * FREGBYTES(sp) - FSTORE f23, 23 * FREGBYTES(sp) - FSTORE f24, 24 * FREGBYTES(sp) - FSTORE f25, 25 * FREGBYTES(sp) - FSTORE f26, 26 * FREGBYTES(sp) - FSTORE f27, 27 * FREGBYTES(sp) - FSTORE f28, 28 * FREGBYTES(sp) - FSTORE f29, 29 * FREGBYTES(sp) - FSTORE f30, 30 * FREGBYTES(sp) - FSTORE f31, 31 * FREGBYTES(sp) -#endif - /* save all from thread context */ -#ifndef __riscv_32e - addi sp, sp, -32 * REGBYTES -#else - addi sp, sp, -16 * REGBYTES -#endif - STORE x5, 5 * REGBYTES(sp) - STORE x1, 1 * REGBYTES(sp) - /* Mandatory set the MPIE of mstatus */ - li t0, 0x80 - STORE t0, 2 * REGBYTES(sp) - STORE x4, 4 * REGBYTES(sp) - STORE x6, 6 * REGBYTES(sp) - STORE x7, 7 * REGBYTES(sp) - STORE x8, 8 * REGBYTES(sp) - STORE x9, 9 * REGBYTES(sp) - STORE x10, 10 * REGBYTES(sp) - STORE x11, 11 * REGBYTES(sp) - STORE x12, 12 * REGBYTES(sp) - STORE x13, 13 * REGBYTES(sp) - STORE x14, 14 * REGBYTES(sp) - STORE x15, 15 * REGBYTES(sp) -#ifndef __riscv_32e - STORE x16, 16 * REGBYTES(sp) - STORE x17, 17 * REGBYTES(sp) - STORE x18, 18 * REGBYTES(sp) - STORE x19, 19 * REGBYTES(sp) - STORE x20, 20 * REGBYTES(sp) - STORE x21, 21 * REGBYTES(sp) - STORE x22, 22 * REGBYTES(sp) - STORE x23, 23 * REGBYTES(sp) - STORE x24, 24 * REGBYTES(sp) - STORE x25, 25 * REGBYTES(sp) - STORE x26, 26 * REGBYTES(sp) - STORE x27, 27 * REGBYTES(sp) - STORE x28, 28 * REGBYTES(sp) - STORE x29, 29 * REGBYTES(sp) - STORE x30, 30 * REGBYTES(sp) - STORE x31, 31 * REGBYTES(sp) -#endif - /* switch to interrupt stack */ - csrrw sp,mscratch,sp - /* interrupt handle */ - call rt_interrupt_enter - /* Do the work after saving the above */ - jal rt_hw_do_after_save_above - - call rt_interrupt_leave - /* switch to from thread stack */ - csrrw sp,mscratch,sp - - /* Determine whether to trigger scheduling at the interrupt function */ - la t0, rt_thread_switch_interrupt_flag - lw t2, 0(t0) - beqz t2, 1f - /* clear the flag of rt_thread_switch_interrupt_flag */ - sw zero, 0(t0) - - csrr a0, mepc - STORE a0, 0 * REGBYTES(sp) - - la t0, rt_interrupt_from_thread - LOAD t1, 0(t0) - STORE sp, 0(t1) - - la t0, rt_interrupt_to_thread - LOAD t1, 0(t0) - LOAD sp, 0(t1) - - LOAD a0, 0 * REGBYTES(sp) - csrw mepc, a0 - -1: - LOAD x1, 1 * REGBYTES(sp) - - /* Set the mode after MRET */ - li t0, 0x1800 - csrs mstatus, t0 - LOAD t0, 2 * REGBYTES(sp) - csrs mstatus, t0 - - LOAD x4, 4 * REGBYTES(sp) - LOAD x5, 5 * REGBYTES(sp) - LOAD x6, 6 * REGBYTES(sp) - LOAD x7, 7 * REGBYTES(sp) - LOAD x8, 8 * REGBYTES(sp) - LOAD x9, 9 * REGBYTES(sp) - LOAD x10, 10 * REGBYTES(sp) - LOAD x11, 11 * REGBYTES(sp) - LOAD x12, 12 * REGBYTES(sp) - LOAD x13, 13 * REGBYTES(sp) - LOAD x14, 14 * REGBYTES(sp) - LOAD x15, 15 * REGBYTES(sp) -#ifndef __riscv_32e - LOAD x16, 16 * REGBYTES(sp) - LOAD x17, 17 * REGBYTES(sp) - LOAD x18, 18 * REGBYTES(sp) - LOAD x19, 19 * REGBYTES(sp) - LOAD x20, 20 * REGBYTES(sp) - LOAD x21, 21 * REGBYTES(sp) - LOAD x22, 22 * REGBYTES(sp) - LOAD x23, 23 * REGBYTES(sp) - LOAD x24, 24 * REGBYTES(sp) - LOAD x25, 25 * REGBYTES(sp) - LOAD x26, 26 * REGBYTES(sp) - LOAD x27, 27 * REGBYTES(sp) - LOAD x28, 28 * REGBYTES(sp) - LOAD x29, 29 * REGBYTES(sp) - LOAD x30, 30 * REGBYTES(sp) - LOAD x31, 31 * REGBYTES(sp) - - addi sp, sp, 32 * REGBYTES -#else - addi sp, sp, 16 * REGBYTES -#endif - -#ifdef ARCH_RISCV_FPU - FLOAD f0, 0 * FREGBYTES(sp) - FLOAD f1, 1 * FREGBYTES(sp) - FLOAD f2, 2 * FREGBYTES(sp) - FLOAD f3, 3 * FREGBYTES(sp) - FLOAD f4, 4 * FREGBYTES(sp) - FLOAD f5, 5 * FREGBYTES(sp) - FLOAD f6, 6 * FREGBYTES(sp) - FLOAD f7, 7 * FREGBYTES(sp) - FLOAD f8, 8 * FREGBYTES(sp) - FLOAD f9, 9 * FREGBYTES(sp) - FLOAD f10, 10 * FREGBYTES(sp) - FLOAD f11, 11 * FREGBYTES(sp) - FLOAD f12, 12 * FREGBYTES(sp) - FLOAD f13, 13 * FREGBYTES(sp) - FLOAD f14, 14 * FREGBYTES(sp) - FLOAD f15, 15 * FREGBYTES(sp) - FLOAD f16, 16 * FREGBYTES(sp) - FLOAD f17, 17 * FREGBYTES(sp) - FLOAD f18, 18 * FREGBYTES(sp) - FLOAD f19, 19 * FREGBYTES(sp) - FLOAD f20, 20 * FREGBYTES(sp) - FLOAD f21, 21 * FREGBYTES(sp) - FLOAD f22, 22 * FREGBYTES(sp) - FLOAD f23, 23 * FREGBYTES(sp) - FLOAD f24, 24 * FREGBYTES(sp) - FLOAD f25, 25 * FREGBYTES(sp) - FLOAD f26, 26 * FREGBYTES(sp) - FLOAD f27, 27 * FREGBYTES(sp) - FLOAD f28, 28 * FREGBYTES(sp) - FLOAD f29, 29 * FREGBYTES(sp) - FLOAD f30, 30 * FREGBYTES(sp) - FLOAD f31, 31 * FREGBYTES(sp) - - addi sp, sp, 32 * FREGBYTES -#endif - mret - - - .section .text.trap_entry - .align 2 - .weak trap_entry - .global trap_entry -trap_entry: -#ifdef ARCH_RISCV_FPU - addi sp, sp, -32 * FREGBYTES - - FSTORE f0, 0 * FREGBYTES(sp) - FSTORE f1, 1 * FREGBYTES(sp) - FSTORE f2, 2 * FREGBYTES(sp) - FSTORE f3, 3 * FREGBYTES(sp) - FSTORE f4, 4 * FREGBYTES(sp) - FSTORE f5, 5 * FREGBYTES(sp) - FSTORE f6, 6 * FREGBYTES(sp) - FSTORE f7, 7 * FREGBYTES(sp) - FSTORE f8, 8 * FREGBYTES(sp) - FSTORE f9, 9 * FREGBYTES(sp) - FSTORE f10, 10 * FREGBYTES(sp) - FSTORE f11, 11 * FREGBYTES(sp) - FSTORE f12, 12 * FREGBYTES(sp) - FSTORE f13, 13 * FREGBYTES(sp) - FSTORE f14, 14 * FREGBYTES(sp) - FSTORE f15, 15 * FREGBYTES(sp) - FSTORE f16, 16 * FREGBYTES(sp) - FSTORE f17, 17 * FREGBYTES(sp) - FSTORE f18, 18 * FREGBYTES(sp) - FSTORE f19, 19 * FREGBYTES(sp) - FSTORE f20, 20 * FREGBYTES(sp) - FSTORE f21, 21 * FREGBYTES(sp) - FSTORE f22, 22 * FREGBYTES(sp) - FSTORE f23, 23 * FREGBYTES(sp) - FSTORE f24, 24 * FREGBYTES(sp) - FSTORE f25, 25 * FREGBYTES(sp) - FSTORE f26, 26 * FREGBYTES(sp) - FSTORE f27, 27 * FREGBYTES(sp) - FSTORE f28, 28 * FREGBYTES(sp) - FSTORE f29, 29 * FREGBYTES(sp) - FSTORE f30, 30 * FREGBYTES(sp) - FSTORE f31, 31 * FREGBYTES(sp) - -#endif - - /* save thread context to thread stack */ -#ifndef __riscv_32e - addi sp, sp, -32 * REGBYTES -#else - addi sp, sp, -16 * REGBYTES -#endif - STORE x1, 1 * REGBYTES(sp) - - csrr x1, mstatus - STORE x1, 2 * REGBYTES(sp) - - csrr x1, mepc - STORE x1, 0 * REGBYTES(sp) - - STORE x4, 4 * REGBYTES(sp) - STORE x5, 5 * REGBYTES(sp) - STORE x6, 6 * REGBYTES(sp) - STORE x7, 7 * REGBYTES(sp) - STORE x8, 8 * REGBYTES(sp) - STORE x9, 9 * REGBYTES(sp) - STORE x10, 10 * REGBYTES(sp) - STORE x11, 11 * REGBYTES(sp) - STORE x12, 12 * REGBYTES(sp) - STORE x13, 13 * REGBYTES(sp) - STORE x14, 14 * REGBYTES(sp) - STORE x15, 15 * REGBYTES(sp) -#ifndef __riscv_32e - STORE x16, 16 * REGBYTES(sp) - STORE x17, 17 * REGBYTES(sp) - STORE x18, 18 * REGBYTES(sp) - STORE x19, 19 * REGBYTES(sp) - STORE x20, 20 * REGBYTES(sp) - STORE x21, 21 * REGBYTES(sp) - STORE x22, 22 * REGBYTES(sp) - STORE x23, 23 * REGBYTES(sp) - STORE x24, 24 * REGBYTES(sp) - STORE x25, 25 * REGBYTES(sp) - STORE x26, 26 * REGBYTES(sp) - STORE x27, 27 * REGBYTES(sp) - STORE x28, 28 * REGBYTES(sp) - STORE x29, 29 * REGBYTES(sp) - STORE x30, 30 * REGBYTES(sp) - STORE x31, 31 * REGBYTES(sp) -#endif - - /* switch to interrupt stack */ - move s0, sp - -#ifdef RT_USING_SMP - /* get cpu id */ - csrr t0, mhartid - - /* switch interrupt stack of current cpu */ - la sp, __stack_start__ - addi t1, t0, 1 - li t2, __STACKSIZE__ - mul t1, t1, t2 - add sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */ -#endif - - /* handle interrupt */ - call rt_interrupt_enter - csrr a0, mcause - csrr a1, mepc - mv a2, s0 - call handle_trap - call rt_interrupt_leave - -#ifdef RT_USING_SMP - /* s0 --> sp */ - mv sp, s0 - mv a0, s0 - call rt_scheduler_do_irq_switch - tail rt_hw_context_switch_exit - -#else - - /* switch to from_thread stack */ - move sp, s0 - - /* need to switch new thread */ - la s0, rt_thread_switch_interrupt_flag - lw s2, 0(s0) - beqz s2, spurious_interrupt - sw zero, 0(s0) - - la s0, rt_interrupt_from_thread - LOAD s1, 0(s0) - STORE sp, 0(s1) - - la s0, rt_interrupt_to_thread - LOAD s1, 0(s0) - LOAD sp, 0(s1) - -#endif - -spurious_interrupt: - tail rt_hw_context_switch_exit diff --git a/libcpu/risc-v/common/isa_ext.c b/libcpu/risc-v/common/isa_ext.c new file mode 100644 index 00000000000..ffbb676c034 --- /dev/null +++ b/libcpu/risc-v/common/isa_ext.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include +#include + +static RT_BITMAP_DECLARE(isa_map, RISCV_ISA_EXT_MAX); + +void riscv_isa_ext_set_raw(rt_uint32_t isa) +{ + rt_bitmap_set_bit(isa_map, isa); +} + +void riscv_isa_ext_clear_raw(rt_uint32_t isa) +{ + rt_bitmap_clear_bit(isa_map, isa); +} + +rt_bool_t riscv_isa_ext_test_raw(rt_uint32_t isa) +{ + return rt_bitmap_test_bit(isa_map, isa); +} diff --git a/libcpu/risc-v/common/mmu.c b/libcpu/risc-v/common/mmu.c new file mode 100644 index 00000000000..e6ac5c471eb --- /dev/null +++ b/libcpu/risc-v/common/mmu.c @@ -0,0 +1,1260 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2022-12-13 WangXiaoyao Port to new mm + * 2023-10-12 Shell Add permission control API + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#include +#include + +#define DBG_TAG "hw.mmu" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef RT_USING_SMART +#include +#endif + +#ifndef KERNEL_VADDR_START +#define KERNEL_VADDR_START ARCH_TEXT_OFFSET +#endif + +#if defined(RT_USING_SMP) && RT_CPUS_NR > 1 +#define MMU_PERCPU +#endif + +#if __riscv_xlen == 32 +#define VPN_BITS 10 +#define VPN_MASK 0x3ffUL +#define PPN_MASK 0xfff00000UL +#define LEVEL_MAX 1 +rt_weak rt_uint8_t rt_hw_arch_vaddr_width = 32; +#else +#define VPN_BITS 9 +#define VPN_MASK 0x1ffUL +#define PPN_MASK 0x3ffffffffffc00UL +#define LEVEL_MAX 5 +rt_weak rt_uint8_t rt_hw_arch_vaddr_width = 39; +#endif + +struct mmu_level_info +{ + unsigned long *pos; + void *page; +}; + +#ifdef MMU_PERCPU +#define PERCPU_OFFSET rt_hw_cpu_id() * ARCH_PAGE_SIZE +static struct mmu_level_info percpu_level[RT_CPUS_NR][LEVEL_MAX + 1]; +#else +#define PERCPU_OFFSET 0 +#endif + +volatile unsigned long MMUTable[512 * RT_CPUS_NR] rt_align(ARCH_PAGE_SIZE); + +static rt_uint8_t satp_level_4k, satp_level_2M; +static unsigned long satp_mode; + +struct page_table +{ + unsigned long page[ARCH_PAGE_SIZE / sizeof(unsigned long)]; +}; +static struct page_table *__init_page_array; + +void set_free_page(void *page_array) +{ + __init_page_array = page_array; +} + +unsigned long get_free_page(void) +{ + static unsigned long page_off = 0UL; + + if (page_off < ARCH_PAGE_SIZE / sizeof(unsigned long)) + { + return (unsigned long)(__init_page_array[page_off++].page); + } + + return 0; +} + +static int mmu_map_early(rt_ubase_t *tbl, rt_uint8_t max_level, + rt_ubase_t va, rt_ubase_t pa, rt_ubase_t attr, rt_bool_t flush) +{ + unsigned long page, *table; + rt_ubase_t off, level_shift; + + if (max_level == satp_level_2M) + { + if ((va & SUPPER_PAGE_MASK) || (pa & SUPPER_PAGE_MASK)) + { + return MMU_MAP_ERROR_VANOTALIGN; + } + } + else + { + if ((va & ARCH_PAGE_MASK) || (pa & ARCH_PAGE_MASK)) + { + return MMU_MAP_ERROR_VANOTALIGN; + } + } + + table = tbl; + level_shift = rt_hw_arch_vaddr_width - VPN_BITS; + + for (int level = 0; level < max_level; ++level) + { + off = (va >> level_shift) & VPN_MASK; + + if (!(table[off] & PTE_V)) + { + if (!(page = get_free_page())) + { + return MMU_MAP_ERROR_NOPAGE; + } + + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + table[off] = ((page >> ARCH_PAGE_SHIFT) << PTE_BITS) | PTE_V; + + if (flush) + { + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + } + } + + if ((table[off] & PTE_ATTR_RWX) != 0) + { + /* No a page! */ + return MMU_MAP_ERROR_CONFLICT; + } + + /* Step into the next level page table */ + page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)page; + + level_shift -= VPN_BITS; + } + + off = (va >> level_shift) & VPN_MASK; + table[off] = ((pa >> ARCH_PAGE_SHIFT) << PTE_BITS) | attr; + + if (flush) + { + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + } + + return 0; +} + +#ifdef MMU_PERCPU +static int mmu_map_percpu_early(rt_ubase_t *tbl, rt_ubase_t *tbl_shadow, + rt_ubase_t va, rt_ubase_t pa) +{ + unsigned long page; + rt_ubase_t off, level_shift; + + if (tbl == tbl_shadow) + { + return mmu_map_early(tbl, satp_level_4k, va, pa, MMU_MAP_K_RWCB, RT_FALSE); + } + + level_shift = rt_hw_arch_vaddr_width - VPN_BITS; + + for (int level = 0; level < satp_level_4k; ++level) + { + rt_memcpy(tbl_shadow, tbl, ARCH_PAGE_SIZE); + + if (!(page = get_free_page())) + { + return MMU_MAP_ERROR_NOPAGE; + } + + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + + off = (va >> level_shift) & VPN_MASK; + tbl_shadow[off] = ((page >> ARCH_PAGE_SHIFT) << PTE_BITS) | PTE_V; + + /* Step into the next level page table */ + tbl = (unsigned long *)((tbl[off] >> PTE_BITS) << ARCH_PAGE_SHIFT); + tbl_shadow = (unsigned long *)((tbl_shadow[off] >> PTE_BITS) << ARCH_PAGE_SHIFT); + + level_shift -= VPN_BITS; + } + + off = (va >> level_shift) & VPN_MASK; + tbl_shadow[off] = ((pa >> ARCH_PAGE_SHIFT) << PTE_BITS) | MMU_MAP_K_RWCB; + + return 0; +} +#endif /* MMU_PERCPU */ + +/** + * @brief Switch the current address space to the specified one. + * + * This function is responsible for switching the address space by updating the page table + * and related hardware state. The behavior depends on whether the architecture supports + * Address Space Identifiers (ASIDs), devided by macro definition of ARCH_USING_ASID. + * + * @param aspace Pointer to the address space structure containing the new page table. + * + * @note If ASID is supported (`ARCH_USING_ASID` is defined), the function will call + * `rt_hw_asid_switch_pgtbl` to switch the page table and update the ASID. + * Otherwise, it will directly write the `satp` CSR to switch the page table + * and invalidate the TLB. + */ +#ifdef ARCH_USING_ASID +static rt_uint64_t _asid_acquire(rt_aspace_t aspace) +{ + static rt_uint32_t next_asid = 1; + static rt_uint64_t global_asid_generation = BIT(SATP_ASID_BITS); + + if ((aspace->asid ^ global_asid_generation) >> SATP_ASID_BITS) + { + if (next_asid != MAX_ASID) + { + aspace->asid = global_asid_generation | next_asid++; + } + else + { + global_asid_generation += ASID_FIRST_GENERATION; + next_asid = 1; + rt_hw_tlb_invalidate_all_local(); + + aspace->asid = global_asid_generation | next_asid++; + } + } + + return aspace->asid & SATP_ASID_MASK; +} + +void rt_hw_aspace_switch(rt_aspace_t aspace) +{ + rt_uint64_t asid; + uintptr_t page_table; + +#ifdef MMU_PERCPU + if (aspace == &rt_kernel_space) +#endif + { + page_table = (uintptr_t)rt_kmem_v2p(aspace->page_table + PERCPU_OFFSET); + } +#ifdef MMU_PERCPU + else + { + /* Just sync the per-CPU page */ + int cpu_id = rt_hw_cpu_id(); + unsigned long off = (unsigned long)percpu_level[cpu_id][0].pos; + unsigned long *table = aspace->page_table, *table_shadow = percpu_level[cpu_id][0].page; + + table[off] = table_shadow[off]; + } +#endif /* MMU_PERCPU */ + + asid = _asid_acquire(aspace); + + csr_write(satp, satp_mode | (asid << SATP_ASID_SHIFT) | ((rt_ubase_t)pgtbl >> ARCH_PAGE_SHIFT)); + + SFENCE_VMA_ASID(asid); +} + +#else /* !ARCH_USING_ASID */ +void rt_hw_aspace_switch(rt_aspace_t aspace) +{ + uintptr_t page_table; + +#ifdef MMU_PERCPU + if (aspace == &rt_kernel_space) +#endif + { + page_table = (uintptr_t)rt_kmem_v2p(aspace->page_table + PERCPU_OFFSET); + } +#ifdef MMU_PERCPU + else + { + /* Just sync the per-CPU page */ + int cpu_id = rt_hw_cpu_id(); + unsigned long off = (unsigned long)percpu_level[cpu_id][0].pos; + unsigned long *table = aspace->page_table, *table_shadow = percpu_level[cpu_id][0].page; + + table[off] = table_shadow[off]; + } +#endif /* MMU_PERCPU */ + + csr_write(CSR_SATP, satp_mode | ((rt_ubase_t)page_table >> ARCH_PAGE_SHIFT)); + + rt_hw_tlb_invalidate_all_local(); +} +#endif /* ARCH_USING_ASID */ + +void rt_hw_mmu_tbl_set(unsigned long tbl) +{ + tbl += PERCPU_OFFSET; + tbl += rt_kmem_pvoff(); + + csr_write(CSR_SATP, satp_mode | (tbl >> ARCH_PAGE_SHIFT)); + + rt_hw_tlb_invalidate_all_local(); +} + +void *rt_hw_mmu_tbl_get(void) +{ + rt_ubase_t satp = csr_read(CSR_SATP); + + return (void *)((satp & SATP_PPN) << ARCH_PAGE_SHIFT) - rt_kmem_pvoff(); +} + +void *rt_ioremap_early(void *paddr, size_t size) +{ + rt_ubase_t base; + volatile size_t count; + static void *tbl = RT_NULL; + + if (!size) + { + return RT_NULL; + } + + if (!tbl) + { + tbl = rt_hw_mmu_tbl_get(); + } + + base = RT_ALIGN_DOWN((rt_size_t)paddr, SUPPER_PAGE_SIZE); + count = RT_ALIGN((rt_ubase_t)paddr + size - base, SUPPER_PAGE_SIZE) / SUPPER_PAGE_SIZE; + + while (count --> 0) + { + if (mmu_map_early(tbl, satp_level_2M, base, base, MMU_MAP_K_DEVICE, RT_TRUE)) + { + return RT_NULL; + } + + base += SUPPER_PAGE_SIZE; + } + + return paddr; +} + +#ifdef MMU_PERCPU +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 = rt_hw_arch_vaddr_width - VPN_BITS; + + for (int level = 0; level < satp_level_4k; ++level) + { + if (!(page = (unsigned long)rt_pages_alloc(0))) + { + return MMU_MAP_ERROR_NOPAGE; + } + + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + + off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; + table[off] = (((page + rt_kmem_pvoff()) >> ARCH_PAGE_SHIFT) << PTE_BITS) | PTE_V; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + + percpu_level[cpu_id][level].page = (void *)table; + percpu_level[cpu_id][level].pos = (unsigned long *)off; + + /* Step into the next level page table */ + table = (unsigned long *)(((table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT) - rt_kmem_pvoff()); + + level_shift -= VPN_BITS; + } + + off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; + table[off] = (((rt_ubase_t)pa >> ARCH_PAGE_SHIFT) << PTE_BITS) | MMU_MAP_K_RWCB; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + + percpu_level[cpu_id][satp_level_4k].page = (void *)table; + percpu_level[cpu_id][satp_level_4k].pos = (unsigned long *)off; + + return ARCH_PAGE_SIZE; +} + +static void percpu_map_sync(struct rt_aspace *aspace, int level, unsigned long *table, rt_ubase_t off) +{ + if (aspace == &rt_kernel_space && + percpu_level[0][level].page == table && + percpu_level[0][level].pos != (unsigned long *)off) + { + unsigned long *table_shadow; + + for (int i = 1; i < RT_CPUS_NR; ++i) + { + table_shadow = percpu_level[i][level].page; + table_shadow[off] = table[off]; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table_shadow + off, sizeof(void *)); + } + } +} + +static void percpu_mmu_init_check(void) +{ + size_t mapped, size; + void *page_table, *vaddr, *paddr; + static rt_bool_t inited = RT_FALSE; + + if (inited) + { + return; + } + inited = RT_TRUE; + + page_table = rt_kernel_space.page_table; + + for (int cpu_id = 0; cpu_id < RT_CPUS_NR; ++cpu_id) + { + vaddr = &__percpu_start; + paddr = vaddr + rt_kmem_pvoff(); + size = (size_t)(&__percpu_end - &__percpu_start); + /* Offset to per-CPU partition for current CPU */ + paddr += size * cpu_id; + + while (size > 0) + { + MM_PGTBL_LOCK(&rt_kernel_space); + mapped = _map_percpu_area(page_table, vaddr, paddr, cpu_id); + MM_PGTBL_UNLOCK(&rt_kernel_space); + + RT_ASSERT(mapped > 0); + + size -= mapped; + vaddr += mapped; + paddr += mapped; + } + + page_table += ARCH_PAGE_SIZE; + } +} +#endif /* MMU_PERCPU */ + +static size_t _map_area(struct rt_aspace *aspace, void *va, void *pa, + size_t attr, size_t max_size) +{ + rt_uint8_t max_level; + unsigned long page, *table; + rt_ubase_t off, level_shift; + + if (max_size >= SUPPER_PAGE_SIZE && + !((rt_ubase_t)va & SUPPER_PAGE_MASK) && + !((rt_ubase_t)pa & SUPPER_PAGE_MASK)) + { + max_level = satp_level_2M; + max_size = SUPPER_PAGE_SIZE; + } + else + { + max_level = satp_level_4k; + max_size = ARCH_PAGE_SIZE; + } + + table = aspace->page_table; + level_shift = rt_hw_arch_vaddr_width - VPN_BITS; + + for (int level = 0; level < max_level; ++level) + { + off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; + + if (!(table[off] & PTE_V)) + { + if (!(page = (unsigned long)rt_pages_alloc(0))) + { + return MMU_MAP_ERROR_NOPAGE; + } + + rt_memset((void *)page, 0, ARCH_PAGE_SIZE); + table[off] = (((page + rt_kmem_pvoff()) >> ARCH_PAGE_SHIFT) << PTE_BITS) | PTE_V; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + } + else + { + page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT; + page -= rt_kmem_pvoff(); + + rt_page_ref_inc((void *)page, 0); + } + + if ((table[off] & PTE_ATTR_RWX) != 0) + { + /* No a page! */ + return MMU_MAP_ERROR_CONFLICT; + } + + #ifdef MMU_PERCPU + percpu_map_sync(aspace, level, table, off); + #endif + + /* Step into the next level page table */ + page = (table[off] >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)(page - rt_kmem_pvoff()); + + level_shift -= VPN_BITS; + } + + off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; + table[off] = (((rt_ubase_t)pa >> ARCH_PAGE_SHIFT) << PTE_BITS) | attr; + + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, table + off, sizeof(void *)); + +#ifdef MMU_PERCPU + percpu_map_sync(aspace, max_level, table, off); +#endif + + return max_size; +} + +static size_t _unmap_area(struct rt_aspace *aspace, void *va, size_t max_size) +{ + int level, ref; + rt_ubase_t off, level_shift; + unsigned long page, *table, *pos; + struct mmu_level_info level_info[LEVEL_MAX]; + + rt_memset(level_info, 0, sizeof(level_info)); + + table = aspace->page_table; + level_shift = rt_hw_arch_vaddr_width - VPN_BITS; + + /* Max level is 4k */ + for (level = 0; level <= satp_level_4k; ++level) + { + off = ((rt_ubase_t)va >> level_shift) & VPN_MASK; + page = table[off]; + + if (!(page & PTE_V)) + { + break; + } + + if ((page & PTE_ATTR_RWX) != 0) + { + /* No a page! */ + break; + } + + level_info[level].pos = table + off; + + /* Step into the next level page table */ + page = (page >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)(page - rt_kmem_pvoff()); + + level_info[level].page = table; + + level_shift -= VPN_BITS; + } + + if (level == satp_level_4k) + { + max_size = ARCH_PAGE_SIZE; + } + else + { + max_size = SUPPER_PAGE_SIZE; + } + + level = satp_level_4k; + pos = level_info[level].pos; + if (pos) + { + *pos = (unsigned long)RT_NULL; + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, pos, sizeof(void *)); + } + --level; + + while (level >= 0) + { + pos = level_info[level].pos; + + if (pos) + { + void *cur_page = level_info[level].page; + + ref = rt_page_ref_get(cur_page, 0); + + if (ref == 1) + { + *pos = (unsigned long)RT_NULL; + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, pos, sizeof(void *)); + + #ifdef MMU_PERCPU + table = percpu_level[0][level].page; + + if (pos >= table && pos < table + (ARCH_PAGE_SIZE / sizeof(unsigned long))) + { + percpu_map_sync(aspace, level, table, pos - table); + } + #endif /* MMU_PERCPU */ + } + + rt_pages_free(cur_page, 0); + } + else + { + break; + } + + --level; + } + + return max_size; +} + +/** + * @brief Maps a virtual address space to a physical address space. + * + * This function maps a specified range of virtual addresses to a range of physical addresses + * and sets the attributes of the page table entries (PTEs). If an error occurs during the + * mapping process, the function will automatically roll back any partially completed mappings. + * + * @param aspace Pointer to the address space structure containing the page table information. + * @param v_addr The starting virtual address to be mapped. + * @param p_addr The starting physical address to be mapped. + * @param size The size of the memory to be mapped (in bytes). + * @param attr The attributes of the page table entries (e.g., read/write permissions, cache policies). + * + * @return On success, returns the starting virtual address `v_addr`; + * On failure, returns `NULL`. + * + * @note This function will not override existing page table entries. + * @warning The caller must ensure that `v_addr` and `p_addr` are page-aligned, + * and `size` is a multiple of the page size. + * + */ +void *rt_hw_mmu_map(struct rt_aspace *aspace, void *v_addr, void *p_addr, + size_t size, size_t attr) +{ + size_t mapped; + void *unmap_va = v_addr; + +#ifdef MMU_PERCPU + percpu_mmu_init_check(); +#endif + + while (size > 0) + { + #ifdef MMU_PERCPU + if (v_addr < (void *)&__percpu_start || + v_addr >= (void *)&__percpu_real_end) + #endif + { + MM_PGTBL_LOCK(aspace); + mapped = _map_area(aspace, v_addr, p_addr, attr, size); + MM_PGTBL_UNLOCK(aspace); + } + #ifdef MMU_PERCPU + else + { + /* Make the kernel skip the per-CPU as soon as possible */ + mapped = size > SUPPER_PAGE_SIZE ? SUPPER_PAGE_SIZE : size; + } + #endif /* MMU_PERCPU */ + + if (mapped && mapped <= size) + { + size -= mapped; + v_addr += mapped; + p_addr += mapped; + + continue; + } + + /* Error, undo map */ + while (unmap_va != v_addr) + { + MM_PGTBL_LOCK(aspace); + mapped = _unmap_area(aspace, unmap_va, size); + MM_PGTBL_UNLOCK(aspace); + + unmap_va += mapped; + } + + break; + } + + return unmap_va; +} + +/** + * @brief Unmaps a range of virtual memory addresses from the specified address space. + * + * This function is responsible for unmapping a contiguous region of virtual memory + * from the given address space. It handles multiple pages and ensures thread safety + * by locking the page table during the unmapping operation. + * + * @param aspace Pointer to the address space structure from which the memory will be unmapped. + * @param v_addr Starting virtual address to unmap. Must be page-aligned. + * @param size Size of the memory region to unmap. Must be page-aligned. + * + * @note The caller must ensure that both `v_addr` and `size` are page-aligned. + * + * @details The function operates in a loop, unmapping memory in chunks. It uses the + * `_unmap_area` function to perform the actual unmapping, which is called within a + * locked section to ensure thread safety. The loop continues until the entire region + * is unmapped. + * + * @see _unmap_area + * @note unmap is different from map that it can handle multiple pages + */ +void rt_hw_mmu_unmap(struct rt_aspace *aspace, void *v_addr, size_t size) +{ + size_t unmapped; + + /* caller guarantee that v_addr & size are page aligned */ + if (!aspace->page_table) + { + return; + } + + while (size > 0) + { + MM_PGTBL_LOCK(aspace); + unmapped = _unmap_area(aspace, v_addr, size); + MM_PGTBL_UNLOCK(aspace); + + if (unmapped && unmapped <= size) + { + size -= unmapped; + v_addr += unmapped; + + continue; + } + + /* Region not exist in pgtbl */ + break; + } +} + +rt_inline void _init_region(void *vaddr, size_t size) +{ + rt_ioremap_start = vaddr; + rt_ioremap_size = size; + rt_mpr_start = rt_ioremap_start - rt_mpr_size; + LOG_D("rt_ioremap_start: %p, rt_mpr_start: %p", rt_ioremap_start, + rt_mpr_start); +} + +rt_inline rt_ubase_t get_top_vpn(rt_ubase_t va, rt_uint8_t satp_level) +{ + return (va >> (VPN_BITS * satp_level + 12)) & VPN_MASK; +} + +/** + * @brief Initialize the MMU (Memory Management Unit) mapping. + * + * 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. + * 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 + * using _init_region. + * + * @param aspace Pointer to the address space. Must not be NULL. + * @param v_address The starting virtual address. + * @param size The size of the virtual address space. + * @param vtable Pointer to the page table. Must not be NULL. + * @param pv_off The page table offset. + * + * @return Returns 0 if the initialization is successful. Returns -1 if any input parameter is invalid + * or the page table initialization check fails. + */ +int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, + rt_ubase_t *vtable, rt_ubase_t pv_off) +{ + rt_size_t off, va_s, va_e; + + if ((!aspace) || (!vtable)) + { + return -1; + } + + va_s = (rt_ubase_t)v_address; + va_e = (rt_ubase_t)v_address + size - 1; + + if (va_e < va_s) + { + return -1; + } + + /* convert address to top-level index */ + va_s = get_top_vpn(va_s, satp_level_4k); + va_e = get_top_vpn(va_e, satp_level_4k); + + if (va_s == 0) + { + return -1; + } + + /* vtable initialization check */ + for (off = va_s; off <= va_e; off++) + { + rt_size_t v = vtable[off]; + + if (v) + { + return -1; + } + } + + rt_aspace_init(aspace, (void *)KERNEL_VADDR_START, 0UL - KERNEL_VADDR_START, + vtable); + + _init_region(v_address, size); + + return 0; +} + +static void *mmu_v2p(void *tbl, void *vaddr, int *out_level, rt_base_t **out_pte) +{ + unsigned long page, entry; + rt_ubase_t off, level_shift, pa, va = (unsigned long)vaddr, *table = (unsigned long *)tbl; + +#ifdef MMU_PERCPU + if (tbl == rt_kernel_space.page_table) + { + table = (unsigned long *)(tbl + PERCPU_OFFSET); + } +#endif /* MMU_PERCPU */ + + /* Calculate initial shift based on virtual address width */ + level_shift = rt_hw_arch_vaddr_width - VPN_BITS; + + /* 4k is the max level, translate to the last level */ + for (*out_level = 0; *out_level <= satp_level_4k; ++(*out_level)) + { + /* Extract VPN (Virtual Page Number) for this level */ + off = (va >> level_shift) & VPN_MASK; + /* Fetch the page table entry */ + entry = table[off]; + + /* If entry is invalid (V bit not set), address translation fails */ + if (!(entry & PTE_V)) + { + goto _translate_fail; + } + + /* If entry has any RWX permission bits set, it is a leaf entry */ + if (entry & PTE_ATTR_RWX) + { + if (out_pte) + { + *out_pte = table + off; + } + + /* Extract physical page base address and add page offset */ + pa = ((entry >> PTE_BITS) << ARCH_PAGE_SHIFT); + + if (*out_level >= satp_level_4k) + { + pa |= va & ARCH_PAGE_MASK; + } + else + { + pa |= va & SUPPER_PAGE_MASK; + } + + return (void *)pa; + } + + /* Otherwise, walk to the next level page table */ + page = (entry >> PTE_BITS) << ARCH_PAGE_SHIFT; + table = (unsigned long *)(page - rt_kmem_pvoff()); + + level_shift -= VPN_BITS; + } + +_translate_fail: + /* If reached here, it is not a valid mapped address */ + LOG_D("%s: failed at %p", __func__, vaddr); + return ARCH_MAP_FAILED; +} + +/** + * @brief Translate a virtual address to a physical address. + * + * This function translates a given virtual address (`vaddr`) to its corresponding + * physical address (`paddr`) using the page table in the specified address space (`aspace`). + * + * @param aspace Pointer to the address space structure containing the page table. + * @param vaddr The virtual address to be translated. + * + * @return The translated physical address. If the translation fails, `ARCH_MAP_FAILED` is returned. + * + * @note The function queries the page table entry (PTE) for the virtual address using `mmu_v2p`. + * If a valid PTE is found, the physical address is extracted and combined with the offset + * from the virtual address. If no valid PTE is found, a debug log is recorded, and + * `ARCH_MAP_FAILED` is returned. + */ +void *rt_hw_mmu_v2p(struct rt_aspace *aspace, void *vaddr) +{ + int level; + + return mmu_v2p(aspace->page_table, vaddr, &level, RT_NULL); +} + +static int _noncache(rt_base_t *pte) +{ + rt_ubase_t entry; + + if (!riscv_isa_ext_test(SVPBMT)) + { + return -RT_ENOSYS; + } + + entry = *pte; + *pte = (entry & ~PTE_VENDOR_MTMASK) | PTE_VENDOR_NOCACHE; + + return 0; +} + +static int _cache(rt_base_t *pte) +{ + rt_ubase_t entry; + + if (!riscv_isa_ext_test(SVPBMT)) + { + return -RT_ENOSYS; + } + + entry = *pte; + *pte = (entry & ~PTE_VENDOR_MTMASK) | PTE_VENDOR_PMA; + + return 0; +} + +static int (*control_handler[MMU_CNTL_DUMMY_END])(rt_base_t *pte)= +{ + [MMU_CNTL_CACHE] = _cache, + [MMU_CNTL_NONCACHE] = _noncache, +}; + +/** + * @brief Control the page table entries (PTEs) for a specified virtual address range. + * + * This function applies a control command (e.g., cache control) to the page table entries + * (PTEs) corresponding to the specified virtual address range (`vaddr` to `vaddr + size`). + * + * @param aspace Pointer to the address space structure containing the page table. + * @param vaddr The starting virtual address of the range. + * @param size The size of the virtual address range. + * @param cmd The control command to apply (e.g., `MMU_CNTL_CACHE`, `MMU_CNTL_NONCACHE`.etc.). + * + * @return `RT_EOK` on success, or an error code (`-RT_EINVAL` or `-RT_ENOSYS`) on failure. + * + * @note The function uses the `control_handler` array to map the command to a handler function. + * It iterates over the virtual address range, queries the PTEs, and applies the handler + * to each valid PTE. If the command is invalid, `-RT_ENOSYS` is returned. + */ +int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, + enum rt_mmu_cntl cmd) +{ + int level; + int err = -RT_EINVAL; + void *vend = vaddr + size; + + int (*handler)(rt_base_t *pte); + if (cmd >= 0 && cmd < MMU_CNTL_DUMMY_END) + { + handler = control_handler[cmd]; + + while (vaddr < vend) + { + void *range_end; + rt_base_t *pte = RT_NULL; + + mmu_v2p(aspace->page_table, vaddr, &level, &pte); + + if (level == satp_level_4k) + { + range_end = vaddr + ARCH_PAGE_SIZE; + } + else if (level == satp_level_2M) + { + range_end = vaddr + SUPPER_PAGE_SIZE; + } + else + { + /* 1G or larger is not supported. */ + RT_ASSERT(0); + } + + if (pte) + { + err = handler(pte); + RT_ASSERT(err == RT_EOK); + } + vaddr = range_end; + } + } + else + { + err = -RT_ENOSYS; + } + + return err; +} + +/** + * @brief setup Page Table for kernel space. It's a fixed map + * and all mappings cannot be changed after initialization. + * + * Memory region in struct mem_desc must be page aligned, + * otherwise is a failure and no report will be + * returned. + * + * @param aspace Pointer to the address space structure. + * @param mdesc Pointer to the array of memory descriptors. + * @param desc_nr Number of memory descriptors in the array. + */ +void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr) +{ + void *err; + + for (size_t i = 0; i < desc_nr; ++i) + { + size_t attr; + struct rt_mm_va_hint hint = + { + .flags = MMF_MAP_FIXED, + .limit_start = aspace->start, + .limit_range_size = aspace->size, + .map_size = mdesc->vaddr_end - mdesc->vaddr_start + 1, + .prefer = (void *)mdesc->vaddr_start + }; + + switch (mdesc->attr) + { + case NORMAL_MEM: + attr = MMU_MAP_K_RWCB; + break; + case NORMAL_NOCACHE_MEM: + attr = MMU_MAP_K_RWCB; + break; + case DEVICE_MEM: + attr = MMU_MAP_K_DEVICE; + break; + default: + attr = MMU_MAP_K_DEVICE; + } + + if (mdesc->paddr_start == (rt_uintptr_t)ARCH_MAP_FAILED) + { + mdesc->paddr_start = mdesc->vaddr_start + rt_kmem_pvoff(); + } + + rt_aspace_map_phy_static(aspace, &mdesc->varea, &hint, attr, + mdesc->paddr_start >> MM_PAGE_SHIFT, &err); + mdesc++; + } + + rt_hw_mmu_tbl_set((unsigned long)rt_kernel_space.page_table); + rt_page_cleanup(); +} + +/** + * @brief Early memory setup function for hardware initialization. + * + * This function performs early memory setup tasks, including: + * - Calculating the physical-to-virtual (PV) offset. + * - Setting up initial page tables for identity mapping and text region relocation. + * - Applying new memory mappings by updating the SATP register. + * + * @note This function is typically called during the early stages of system initialization (startup_gcc.S), + * before the memory management system is fully operational. + */ +void rt_hw_mem_setup_early(rt_ubase_t vaddr_start, rt_ubase_t paddr_start, void *pgtbl) +{ + extern char __text_start, __text_end; + + rt_size_t size = ARCH_EARLY_MAP_SIZE; + rt_ubase_t *early_pgtbl = pgtbl, paddr_end = paddr_start + size; + + rt_kmem_pvoff_set(paddr_start - vaddr_start); + + switch (rt_hw_arch_vaddr_width) + { + case 0: + satp_mode = SATP_MODE_BARE; + satp_level_4k = 0; + satp_level_2M = 0; + #ifdef RT_USING_SMART + RT_ASSERT(0); + #else + RT_ASSERT(paddr_start == vaddr_start); + #endif + /* Do nothing */ + return; +#if __riscv_xlen != 32 + case 64: + satp_mode = SATP_MODE_64; + satp_level_4k = 5; + satp_level_2M = 4; + break; + case 57: + satp_mode = SATP_MODE_57; + satp_level_4k = 4; + satp_level_2M = 3; + break; + case 48: + satp_mode = SATP_MODE_48; + satp_level_4k = 3; + satp_level_2M = 2; + break; + case 39: + default: + satp_mode = SATP_MODE_39; + satp_level_4k = 2; + satp_level_2M = 1; + rt_hw_arch_vaddr_width = 39; +#else + case 32: + default: + satp_mode = SATP_MODE_32; + satp_level_4k = 1; + satp_level_2M = 0; + rt_hw_arch_vaddr_width = 32; +#endif /* __riscv_xlen != 32 */ + break; + } + + vaddr_start = RT_ALIGN_DOWN(vaddr_start, SUPPER_PAGE_SIZE); + paddr_start = RT_ALIGN_DOWN(paddr_start, SUPPER_PAGE_SIZE); + paddr_end = RT_ALIGN(paddr_end, SUPPER_PAGE_SIZE); + + rt_memset(early_pgtbl, 0, RT_CPUS_NR * ARCH_PAGE_SIZE); + + if (!rt_kmem_pvoff()) + { + goto _map_vaddress; + } + + /* Identical mapping, only map for 'text' */ + size = RT_ALIGN((rt_ubase_t)(&__text_end - &__text_start), SUPPER_PAGE_SIZE); + + /* Check whether the virtual address area and identical area overlap */ + RT_ASSERT(size < rt_kmem_pvoff()); + + for (rt_ssize_t pages = size / SUPPER_PAGE_SIZE; pages > 0; --pages) + { + mmu_map_early(early_pgtbl, satp_level_2M, paddr_start, paddr_start, MMU_MAP_K_RWCB, RT_FALSE); + + paddr_start += SUPPER_PAGE_SIZE; + } + + /* Page array for map early */ + paddr_start = RT_ALIGN_DOWN((rt_ubase_t)early_pgtbl, SUPPER_PAGE_SIZE); + mmu_map_early(early_pgtbl, satp_level_2M, paddr_start, paddr_start, MMU_MAP_K_RWCB, RT_FALSE); + + if ((rt_ubase_t)__init_page_array - paddr_start >= SUPPER_PAGE_SIZE) + { + paddr_start = RT_ALIGN_DOWN((rt_ubase_t)__init_page_array, SUPPER_PAGE_SIZE); + mmu_map_early(early_pgtbl, satp_level_2M, paddr_start, paddr_start, MMU_MAP_K_RWCB, RT_FALSE); + } + +_map_vaddress: + /* Virtual mapping */ + while (paddr_start < paddr_end) + { + #ifdef MMU_PERCPU + if (paddr_start < (rt_ubase_t)&__percpu_start || + paddr_start >= (rt_ubase_t)&__percpu_real_end) + #endif + { + mmu_map_early(early_pgtbl, satp_level_2M, vaddr_start, paddr_start, MMU_MAP_K_RWCB, RT_FALSE); + } + + paddr_start += SUPPER_PAGE_SIZE; + vaddr_start += SUPPER_PAGE_SIZE; + } + +#ifdef MMU_PERCPU + for (int cpu_id = 0; cpu_id < RT_CPUS_NR; ++cpu_id) + { + paddr_start = (rt_ubase_t)&__percpu_start; + vaddr_start = paddr_start - rt_kmem_pvoff(); + size = (rt_size_t)(&__percpu_end - &__percpu_start); + /* Offset to per-CPU partition for current CPU */ + paddr_start += cpu_id * size; + paddr_end = paddr_start + size; + + while (paddr_start < paddr_end) + { + /* Map physical address per-CPU partition */ + mmu_map_percpu_early(early_pgtbl, (void *)early_pgtbl + cpu_id * ARCH_PAGE_SIZE, vaddr_start, paddr_start); + + paddr_start += ARCH_PAGE_SIZE; + vaddr_start += ARCH_PAGE_SIZE; + } + } +#endif /* MMU_PERCPU */ +} + +rt_ubase_t mmu_satp_load(void *pgtbl, rt_ubase_t hartid) +{ +#ifdef MMU_PERCPU + pgtbl += riscv_hartid_to_cpu_id(hartid) * ARCH_PAGE_SIZE; +#endif + + return satp_mode | ((rt_ubase_t)pgtbl >> ARCH_PAGE_SHIFT); +} + +/** + * @brief Creates and initializes a new MMU page table. + * + * This function allocates a new MMU page table, copies the kernel space + * page table into it, and flushes the data cache to ensure consistency. + * + * @return + * - A pointer to the newly allocated MMU page table on success. + * - RT_NULL if the allocation fails. + */ +void *rt_hw_mmu_pgtbl_create(void) +{ + rt_ubase_t *mmu_table; + mmu_table = (rt_ubase_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE); + if (!mmu_table) + { + return RT_NULL; + } + rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE); + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); + + return mmu_table; +} + +/** + * @brief Deletes an MMU page table. + * + * This function frees the memory allocated for the given MMU page table. + * + * @param pgtbl Pointer to the MMU page table to be deleted. + */ +void rt_hw_mmu_pgtbl_delete(void *pgtbl) +{ + rt_pages_free(pgtbl, 0); +} diff --git a/libcpu/risc-v/common/mmu_dummy.c b/libcpu/risc-v/common/mmu_dummy.c new file mode 100644 index 00000000000..ed6915a6fa7 --- /dev/null +++ b/libcpu/risc-v/common/mmu_dummy.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2025 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-26 GuEe-GUI first version + */ + +#include +#include + +#define DBG_TAG "hw.mmu" +#define DBG_LVL DBG_INFO +#include + +void *rt_ioremap(void *paddr, size_t size) +{ + RT_UNUSED(size); + return paddr; +} + +void rt_iounmap(void *vaddr) +{ + RT_UNUSED(vaddr); +} diff --git a/libcpu/risc-v/common/pic/Kconfig b/libcpu/risc-v/common/pic/Kconfig new file mode 100644 index 00000000000..662e54a23b4 --- /dev/null +++ b/libcpu/risc-v/common/pic/Kconfig @@ -0,0 +1,18 @@ +config RT_PIC_RISCV_AIA + bool "RISC-V AIA (Advanced Interrupt Architecture)" + depends on RT_USING_PIC + help + with APLIC (Advanced Platform-Level Interrupt Controller) and + IMSIC (Incoming MSI Controller) + +config RT_PIC_RISCV_CLIC + bool "RISC-V CLIC (Core-Local Interrupt Controller)" + depends on RT_USING_PIC + +config RT_PIC_RISCV_INTC + bool "RISC-V CPU interrupt controller" + depends on RT_USING_PIC + +config RT_PIC_SIFIVE_PLIC + bool "SiFive PLIC (Platform-Level Interrupt Controller)" + depends on RT_USING_PIC diff --git a/libcpu/risc-v/common/pic/SConscript b/libcpu/risc-v/common/pic/SConscript new file mode 100644 index 00000000000..21658b16718 --- /dev/null +++ b/libcpu/risc-v/common/pic/SConscript @@ -0,0 +1,23 @@ +from building import * + +group = [] + +if not GetDepend(['RT_USING_PIC']): + Return('group') + +src = [] +cwd = GetCurrentDir() +CPPPATH = [cwd] + +if GetDepend(['RT_PIC_RISCV_AIA']): + src += ['pic-riscv-aplic.c', 'pic-riscv-imsic.c'] + +if GetDepend(['RT_PIC_RISCV_INTC']): + src += ['pic-riscv-intc.c'] + +if GetDepend(['RT_PIC_SIFIVE_PLIC']): + src += ['pic-sifive-plic.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/risc-v/common/pic/pic-riscv-aplic.c b/libcpu/risc-v/common/pic/pic-riscv-aplic.c new file mode 100644 index 00000000000..3d1b8f2b60c --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-aplic.c @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include +#include +#include + +#define DBG_TAG "pic.aplic" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include "pic-riscv-imsic.h" + +#define APLIC_MAX_IDC RT_BIT(14) +#define APLIC_MAX_SOURCE 1024 + +#define APLIC_DOMAINCFG 0x0000 +#define APLIC_DOMAINCFG_RDONLY 0x80000000 +#define APLIC_DOMAINCFG_IE RT_BIT(8) +#define APLIC_DOMAINCFG_DM RT_BIT(2) +#define APLIC_DOMAINCFG_BE RT_BIT(0) + +#define APLIC_SOURCECFG_BASE 0x0004 +#define APLIC_SOURCECFG_D RT_BIT(10) +#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff +#define APLIC_SOURCECFG_SM_MASK 0x00000007 +#define APLIC_SOURCECFG_SM_INACTIVE 0x0 +#define APLIC_SOURCECFG_SM_DETACH 0x1 +#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4 +#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5 +#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6 +#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7 + +#define APLIC_MMSICFGADDR 0x1bc0 +#define APLIC_MMSICFGADDRH 0x1bc4 +#define APLIC_SMSICFGADDR 0x1bc8 +#define APLIC_SMSICFGADDRH 0x1bcc + +#ifdef ARCH_RISCV_M_MODE +#define APLIC_xMSICFGADDR APLIC_MMSICFGADDR +#define APLIC_xMSICFGADDRH APLIC_MMSICFGADDRH +#else +#define APLIC_xMSICFGADDR APLIC_SMSICFGADDR +#define APLIC_xMSICFGADDRH APLIC_SMSICFGADDRH +#endif + +#define APLIC_xMSICFGADDRH_L RT_BIT(31) +#define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f +#define APLIC_xMSICFGADDRH_HHXS_SHIFT 24 +#define APLIC_xMSICFGADDRH_HHXS (APLIC_xMSICFGADDRH_HHXS_MASK << APLIC_xMSICFGADDRH_HHXS_SHIFT) +#define APLIC_xMSICFGADDRH_LHXS_MASK 0x7 +#define APLIC_xMSICFGADDRH_LHXS_SHIFT 20 +#define APLIC_xMSICFGADDRH_LHXS (APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) +#define APLIC_xMSICFGADDRH_HHXW_MASK 0x7 +#define APLIC_xMSICFGADDRH_HHXW_SHIFT 16 +#define APLIC_xMSICFGADDRH_HHXW (APLIC_xMSICFGADDRH_HHXW_MASK << APLIC_xMSICFGADDRH_HHXW_SHIFT) +#define APLIC_xMSICFGADDRH_LHXW_MASK 0xf +#define APLIC_xMSICFGADDRH_LHXW_SHIFT 12 +#define APLIC_xMSICFGADDRH_LHXW (APLIC_xMSICFGADDRH_LHXW_MASK << APLIC_xMSICFGADDRH_LHXW_SHIFT) +#define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff +#define APLIC_xMSICFGADDRH_BAPPN_SHIFT 0 +#define APLIC_xMSICFGADDRH_BAPPN (APLIC_xMSICFGADDRH_BAPPN_MASK << APLIC_xMSICFGADDRH_BAPPN_SHIFT) + +#define APLIC_xMSICFGADDR_PPN_SHIFT 12 + +#define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \ + (RT_BIT(__lhxs) - 1) + +#define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \ + (RT_BIT(__lhxw) - 1) +#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \ + ((__lhxs)) +#define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \ + (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs)) + +#define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \ + (RT_BIT(__hhxw) - 1) +#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \ + ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT) +#define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \ + (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs)) + +#define APLIC_IRQBITS_PER_REG 32 + +#define APLIC_SETIP_BASE 0x1c00 +#define APLIC_SETIPNUM 0x1cdc + +#define APLIC_CLRIP_BASE 0x1d00 +#define APLIC_CLRIPNUM 0x1ddc + +#define APLIC_SETIE_BASE 0x1e00 +#define APLIC_SETIENUM 0x1edc + +#define APLIC_CLRIE_BASE 0x1f00 +#define APLIC_CLRIENUM 0x1fdc + +#define APLIC_SETIPNUM_LE 0x2000 +#define APLIC_SETIPNUM_BE 0x2004 + +#define APLIC_GENMSI 0x3000 + +#define APLIC_TARGET_BASE 0x3004 +#define APLIC_TARGET_HART_IDX_SHIFT 18 +#define APLIC_TARGET_HART_IDX_MASK 0x3fff +#define APLIC_TARGET_HART_IDX (APLIC_TARGET_HART_IDX_MASK << APLIC_TARGET_HART_IDX_SHIFT) +#define APLIC_TARGET_GUEST_IDX_SHIFT 12 +#define APLIC_TARGET_GUEST_IDX_MASK 0x3f +#define APLIC_TARGET_GUEST_IDX (APLIC_TARGET_GUEST_IDX_MASK << APLIC_TARGET_GUEST_IDX_SHIFT) +#define APLIC_TARGET_IPRIO_SHIFT 0 +#define APLIC_TARGET_IPRIO_MASK 0xff +#define APLIC_TARGET_IPRIO (APLIC_TARGET_IPRIO_MASK << APLIC_TARGET_IPRIO_SHIFT) +#define APLIC_TARGET_EIID_SHIFT 0 +#define APLIC_TARGET_EIID_MASK 0x7ff +#define APLIC_TARGET_EIID (APLIC_TARGET_EIID_MASK << APLIC_TARGET_EIID_SHIFT) + +#define APLIC_IDC_BASE 0x4000 +#define APLIC_IDC_SIZE 32 + +#define APLIC_IDC_IDELIVERY 0x00 + +#define APLIC_IDC_IFORCE 0x04 + +#define APLIC_IDC_ITHRESHOLD 0x08 + +#define APLIC_IDC_TOPI 0x18 +#define APLIC_IDC_TOPI_ID_SHIFT 16 +#define APLIC_IDC_TOPI_ID_MASK 0x3ff +#define APLIC_IDC_TOPI_ID (APLIC_IDC_TOPI_ID_MASK << APLIC_IDC_TOPI_ID_SHIFT) +#define APLIC_IDC_TOPI_PRIO_SHIFT 0 +#define APLIC_IDC_TOPI_PRIO_MASK 0xff +#define APLIC_IDC_TOPI_PRIO (APLIC_IDC_TOPI_PRIO_MASK << APLIC_IDC_TOPI_PRIO_SHIFT) + +#define APLIC_IDC_CLAIMI 0x1c + +#define APLIC_ENABLE_IDELIVERY 1 +#define APLIC_ENABLE_ITHRESHOLD 0 + +#define APLIC_DEFAULT_PRIORITY 1 + +struct riscv_aplic_idc +{ + void *regs; +}; + +struct riscv_aplic_msicfg +{ + rt_ubase_t base_ppn; + rt_uint32_t hhxs; + rt_uint32_t hhxw; + rt_uint32_t lhxs; + rt_uint32_t lhxw; +}; + +struct riscv_aplic +{ + struct rt_pic parent; + struct rt_pic *msi_ic; + + struct rt_ofw_node *np; + + void *regs; + int parent_irq; + int init_cpu_id; + + rt_uint32_t gsi_base; + rt_uint32_t nr_irqs; + rt_uint32_t nr_idcs; + + struct riscv_aplic_msicfg msicfg; + struct riscv_aplic_idc idc[RT_CPUS_NR]; +}; + +rt_always_inline rt_uint32_t irq_cfg_offset(int hwirq) +{ + return (hwirq - 1) * sizeof(rt_uint32_t); +} + +static void aplic_handler(int hwirq, void *data); + +static rt_err_t aplic_irq_init(struct rt_pic *pic) +{ + struct riscv_aplic *aplic = pic->priv_data; + + if (!aplic->msi_ic) + { + if (aplic->parent_irq < 0) + { + struct rt_ofw_cell_args irq_args; + + if (rt_ofw_parse_irq_cells(aplic->np, 0, &irq_args)) + { + LOG_E("%s: Parent IRQ is not available", rt_ofw_node_full_name(aplic->np)); + return RT_EOK; + } + + /* Create mapping */ + irq_args.args[0] = RV_IRQ_EXT; + + aplic->parent_irq = rt_ofw_map_irq(&irq_args); + + rt_hw_interrupt_install(aplic->parent_irq, aplic_handler, aplic, "APLIC"); + } + + rt_pic_irq_unmask(aplic->parent_irq); + } + + return RT_EOK; +} + +static void aplic_irq_unmask(struct rt_pic_irq *pirq) +{ + struct riscv_aplic *aplic = pirq->pic->priv_data; + + HWREG32(aplic->regs + APLIC_SETIENUM) = pirq->hwirq; +} + +static void aplic_irq_mask(struct rt_pic_irq *pirq) +{ + struct riscv_aplic *aplic = pirq->pic->priv_data; + + HWREG32(aplic->regs + APLIC_CLRIENUM) = pirq->hwirq; +} + +static void aplic_msi_irq_eoi(struct rt_pic_irq *pirq) +{ + struct riscv_aplic *aplic = pirq->pic->priv_data; + + switch (pirq->mode) + { + case RT_IRQ_MODE_LEVEL_HIGH: + case RT_IRQ_MODE_LEVEL_LOW: + HWREG32(aplic->regs + APLIC_SETIPNUM_LE) = pirq->hwirq; + break; + + default: + break; + } +} + +static rt_err_t aplic_direct_irq_set_priority(struct rt_pic_irq *pirq, rt_uint32_t priority) +{ + rt_uint32_t value; + struct riscv_aplic *aplic = pirq->pic->priv_data; + + /* Start with 1 not 0 */ + priority += 1; + priority = rt_min_t(rt_uint32_t, priority, APLIC_TARGET_IPRIO_MASK); + + value = HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)); + value &= ~APLIC_TARGET_IPRIO; + value |= priority << APLIC_TARGET_IPRIO_SHIFT; + + HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)) = value; + + return RT_EOK; +} + +static rt_err_t aplic_direct_irq_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *affinity) +{ + rt_uint32_t value; + struct riscv_aplic *aplic = pirq->pic->priv_data; + + value = RT_FIELD_PREP(APLIC_TARGET_HART_IDX, rt_bitmap_next_set_bit(affinity, 0, RT_CPUS_NR)); + value |= RT_FIELD_PREP(APLIC_TARGET_IPRIO, pirq->priority); + + HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)) = value; + + return RT_EOK; +} + +static rt_err_t aplic_msi_irq_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *affinity) +{ + int cpu_id; + rt_uint32_t value; + struct riscv_aplic *aplic = pirq->pic->priv_data; + + cpu_id = rt_bitmap_next_set_bit(affinity, 0, RT_CPUS_NR); + value = RT_FIELD_PREP(APLIC_TARGET_HART_IDX, cpu_id); + value |= RT_FIELD_PREP(APLIC_TARGET_EIID, pirq->parent->hwirq); + + HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)) = value; + + return RT_EOK; +} + +static rt_err_t aplic_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode) +{ + struct riscv_aplic *aplic = pirq->pic->priv_data; + + switch (mode) + { + case RT_IRQ_MODE_NONE: + mode = APLIC_SOURCECFG_SM_INACTIVE; + break; + case RT_IRQ_MODE_LEVEL_LOW: + mode = APLIC_SOURCECFG_SM_LEVEL_LOW; + break; + case RT_IRQ_MODE_LEVEL_HIGH: + mode = APLIC_SOURCECFG_SM_LEVEL_HIGH; + break; + case RT_IRQ_MODE_EDGE_FALLING: + mode = APLIC_SOURCECFG_SM_EDGE_FALL; + break; + case RT_IRQ_MODE_EDGE_RISING: + mode = APLIC_SOURCECFG_SM_EDGE_RISE; + break; + default: + return -RT_EINVAL; + } + + HWREG32(aplic->regs + APLIC_SOURCECFG_BASE + irq_cfg_offset(pirq->hwirq)) = mode; + + return RT_EOK; +} + +static void aplic_msi_irq_write_msg(struct rt_pic_irq *pirq, struct rt_pci_msi_msg *msg) +{ + rt_ubase_t tppn, tbppn, msg_addr; + rt_uint32_t group_index, hart_index, guest_index, val; + struct riscv_aplic *aplic = pirq->pic->priv_data; + struct riscv_aplic_msicfg *msicfg = &aplic->msicfg; + + /* For zeroed MSI, simply write zero into the target register */ + if (!msg->address_hi && !msg->address_lo && !msg->data) + { + HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)) = 0; + return; + } + + /* Sanity check on message data */ + if (msg->data > APLIC_TARGET_EIID_MASK) + { + LOG_W("MSI msg out of EIID mask"); + } + + /* Compute target MSI address */ + msg_addr = (((rt_uint64_t)msg->address_hi) << 32) | msg->address_lo; + tppn = msg_addr >> APLIC_xMSICFGADDR_PPN_SHIFT; + + /* Compute target HART Base PPN */ + tbppn = tppn; + tbppn &= ~APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs); + tbppn &= ~APLIC_xMSICFGADDR_PPN_LHX(msicfg->lhxw, msicfg->lhxs); + tbppn &= ~APLIC_xMSICFGADDR_PPN_HHX(msicfg->hhxw, msicfg->hhxs); + + /* Compute target group and hart indexes */ + group_index = (tppn >> APLIC_xMSICFGADDR_PPN_HHX_SHIFT(msicfg->hhxs)) & + APLIC_xMSICFGADDR_PPN_HHX_MASK(msicfg->hhxw); + hart_index = (tppn >> APLIC_xMSICFGADDR_PPN_LHX_SHIFT(msicfg->lhxs)) & + APLIC_xMSICFGADDR_PPN_LHX_MASK(msicfg->lhxw); + hart_index |= (group_index << msicfg->lhxw); + + if (hart_index > APLIC_TARGET_HART_IDX_MASK) + { + LOG_W("HART index out of IDX mask"); + } + + /* Compute target guest index */ + guest_index = tppn & APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs); + + if (guest_index > APLIC_TARGET_GUEST_IDX_MASK) + { + LOG_W("Guest index out of IDX mask"); + } + + /* Update IRQ TARGET register */ + val = RT_FIELD_PREP(APLIC_TARGET_HART_IDX, hart_index); + val |= RT_FIELD_PREP(APLIC_TARGET_GUEST_IDX, guest_index); + val |= RT_FIELD_PREP(APLIC_TARGET_EIID, msg->data); + + HWREG32(aplic->regs + APLIC_TARGET_BASE + irq_cfg_offset(pirq->hwirq)) = val; +} + +static int aplic_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + int irq; + struct riscv_aplic *aplic = pic->priv_data; + struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq); + + if (aplic->msi_ic) + { + int msi_irq = aplic->msi_ic->ops->irq_alloc_msi(aplic->msi_ic, RT_NULL); + + if (msi_irq < 0) + { + return msi_irq; + } + + irq = rt_pic_config_irq(pic, hwirq, hwirq); + + rt_pic_cascade(pirq, msi_irq); + } + else + { + irq = rt_pic_config_irq(pic, hwirq, hwirq); + } + + rt_memset(pirq->affinity, 0, sizeof(pirq->affinity)); + + RT_IRQ_AFFINITY_SET(pirq->affinity, aplic->init_cpu_id); + pic->ops->irq_set_affinity(pirq, pirq->affinity); + + pirq->mode = mode; + pic->ops->irq_set_triger_mode(pirq, mode); + + return irq; +} + +static rt_err_t aplic_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + struct riscv_aplic *aplic = pic->priv_data; + + if (args->args_count < 2 || !args->args[0]) + { + return -RT_EINVAL; + } + + out_pirq->hwirq = args->args[0] - aplic->gsi_base; + out_pirq->mode = args->args[1] & RT_IRQ_MODE_MASK; + + return RT_EOK; +} + +const static struct rt_pic_ops aplic_direct_ops = +{ + .name = "APLIC-DIRECT", + .irq_init = aplic_irq_init, + .irq_mask = aplic_irq_mask, + .irq_unmask = aplic_irq_unmask, + .irq_set_priority = aplic_direct_irq_set_priority, + .irq_set_affinity = aplic_direct_irq_set_affinity, + .irq_set_triger_mode = aplic_irq_set_triger_mode, + .irq_map = aplic_irq_map, + .irq_parse = aplic_irq_parse, +}; + +const static struct rt_pic_ops aplic_msi_ops = +{ + .name = "APLIC-MSI", + .irq_init = aplic_irq_init, + .irq_mask = aplic_irq_mask, + .irq_unmask = aplic_irq_unmask, + .irq_eoi = aplic_msi_irq_eoi, + .irq_set_affinity = aplic_msi_irq_set_affinity, + .irq_set_triger_mode = aplic_irq_set_triger_mode, + .irq_write_msi_msg = aplic_msi_irq_write_msg, + .irq_map = aplic_irq_map, + .irq_parse = aplic_irq_parse, + .flags = RT_PIC_F_IRQ_ROUTING, +}; + +static void aplic_handler(int hwirq, void *data) +{ + struct rt_pic_irq *pirq; + struct riscv_aplic *aplic = data; + struct riscv_aplic_idc *idc = &aplic->idc[rt_hw_cpu_id()]; + + while ((hwirq = HWREG32(idc->regs + APLIC_IDC_CLAIMI))) + { + hwirq >>= APLIC_IDC_TOPI_ID_SHIFT; + + pirq = rt_pic_find_irq(&aplic->parent, hwirq); + + rt_pic_handle_isr(pirq); + } +} + +static rt_err_t aplic_ofw_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id) +{ + rt_err_t err; + rt_uint32_t val; + struct rt_ofw_node *msi_np; + struct riscv_aplic *aplic = rt_calloc(1, sizeof(*aplic)); + + aplic->regs = rt_ofw_iomap(np, 0); + + if (!aplic->regs) + { + err = -RT_ENOMEM; + goto _fail; + } + + if ((err = rt_ofw_prop_read_u32(np, "riscv,num-sources", &aplic->nr_irqs))) + { + goto _fail; + } + + msi_np = rt_ofw_parse_phandle(np, "msi-parent", 0); + + /* Disable all interrupts */ + for (int i = 0; i <= aplic->nr_irqs; i += 32) + { + HWREG32(aplic->regs + APLIC_CLRIE_BASE + (i / 32) * sizeof(rt_uint32_t)) = RT_UINT32_MAX; + } + + /* Clear APLIC domaincfg */ + HWREG32(aplic->regs + APLIC_DOMAINCFG) = 0; + + aplic->np = np; + aplic->init_cpu_id = rt_hw_cpu_id(); + rt_ofw_data(np) = &aplic->parent; + + if (msi_np) + { + const struct imsic_global_config *imsic_global; + struct riscv_aplic_msicfg *msicfg = &aplic->msicfg; + + if ((err = imsic_ofw_probe(msi_np, np, id))) + { + goto _fail; + } + + if (!(imsic_global = imsic_global_config_read(msi_np))) + { + LOG_E("%s: IMSIC global config not found", rt_ofw_node_full_name(np)); + err = -RT_EINVAL; + goto _fail; + } + + /* Find number of guest index bits (LHXS) */ + msicfg->lhxs = imsic_global->guest_index_bits; + if (APLIC_xMSICFGADDRH_LHXS_MASK < msicfg->lhxs) + { + LOG_E("%s: IMSIC guest index bits big for APLIC LHXS", rt_ofw_node_full_name(np)); + err = -RT_EINVAL; + goto _fail; + } + + /* Find number of HART index bits (LHXW) */ + msicfg->lhxw = imsic_global->hart_index_bits; + if (APLIC_xMSICFGADDRH_LHXW_MASK < msicfg->lhxw) + { + LOG_E("%s: IMSIC hart index bits big for APLIC LHXW", rt_ofw_node_full_name(np)); + err = -RT_EINVAL; + goto _fail; + } + + /* Find number of group index bits (HHXW) */ + msicfg->hhxw = imsic_global->group_index_bits; + if (APLIC_xMSICFGADDRH_HHXW_MASK < msicfg->hhxw) + { + LOG_E("%s: IMSIC group index bits big for APLIC HHXW", rt_ofw_node_full_name(np)); + err = -RT_EINVAL; + goto _fail; + } + + /* Find first bit position of group index (HHXS) */ + msicfg->hhxs = imsic_global->group_index_shift; + if (msicfg->hhxs < (2 * APLIC_xMSICFGADDR_PPN_SHIFT)) + { + LOG_E("%s: IMSIC group index shift should be >= %d", + rt_ofw_node_full_name(np), (2 * APLIC_xMSICFGADDR_PPN_SHIFT)); + err = -RT_EINVAL; + goto _fail; + } + msicfg->hhxs -= (2 * APLIC_xMSICFGADDR_PPN_SHIFT); + if (APLIC_xMSICFGADDRH_HHXS_MASK < msicfg->hhxs) + { + LOG_E("%s: IMSIC group index shift big for APLIC HHXS", rt_ofw_node_full_name(np)); + err = -RT_EINVAL; + goto _fail; + } + + /* Compute PPN base */ + msicfg->base_ppn = imsic_global->base_addr >> APLIC_xMSICFGADDR_PPN_SHIFT; + msicfg->base_ppn &= ~APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs); + msicfg->base_ppn &= ~APLIC_xMSICFGADDR_PPN_LHX(msicfg->lhxw, msicfg->lhxs); + msicfg->base_ppn &= ~APLIC_xMSICFGADDR_PPN_HHX(msicfg->hhxw, msicfg->hhxs); + } + else + { + int hwirq, cpu_id; + rt_ubase_t hartid; + struct riscv_aplic_idc *idc; + struct rt_ofw_cell_args idcs; + struct rt_ofw_node *cpu_np; + + while (!rt_ofw_parse_irq_cells(np, aplic->nr_idcs, &idcs)) + { + cpu_np = rt_ofw_get_parent(idcs.data); + + hwirq = idcs.args[0]; + hartid = rt_ofw_get_cpu_hwid(cpu_np, 0); + + rt_ofw_node_put(cpu_np); + + if (hwirq != RV_IRQ_EXT) + { + continue; + } + + cpu_id = riscv_hartid_to_cpu_id(hartid); + + if (cpu_id >= RT_CPUS_NR) + { + continue; + } + + idc = &aplic->idc[cpu_id]; + idc->regs = aplic->regs + APLIC_IDC_BASE + aplic->nr_idcs * APLIC_IDC_SIZE; + + /* Priority must be less than threshold for interrupt triggering */ + HWREG32(idc->regs + APLIC_IDC_ITHRESHOLD) = APLIC_ENABLE_ITHRESHOLD; + + /* Delivery must be set to 1 for interrupt triggering */ + HWREG32(idc->regs + APLIC_IDC_IDELIVERY) = APLIC_ENABLE_IDELIVERY; + + ++aplic->nr_idcs; + } + } + + /* Setup global config and interrupt delivery */ +#ifdef ARCH_RISCV_M_MODE + if (msi_np) + { + rt_uint32_t valh; + + val = rt_lower_32_bits(aplic->msicfg.base_ppn); + valh = RT_FIELD_PREP(APLIC_xMSICFGADDRH_BAPPN, rt_upper_32_bits(aplic->msicfg.base_ppn)); + valh |= RT_FIELD_PREP(APLIC_xMSICFGADDRH_LHXW, aplic->msicfg.lhxw); + valh |= RT_FIELD_PREP(APLIC_xMSICFGADDRH_HHXW, aplic->msicfg.hhxw); + valh |= RT_FIELD_PREP(APLIC_xMSICFGADDRH_LHXS, aplic->msicfg.lhxs); + valh |= RT_FIELD_PREP(APLIC_xMSICFGADDRH_HHXS, aplic->msicfg.hhxs); + + HWREG32(aplic->regs + APLIC_xMSICFGADDR) = val; + HWREG32(aplic->regs + APLIC_xMSICFGADDRH) = valh; + } +#endif /* ARCH_RISCV_M_MODE */ + + /* Setup APLIC domaincfg register */ + val = HWREG32(aplic->regs + APLIC_DOMAINCFG); + val |= APLIC_DOMAINCFG_IE; + + if (msi_np) + { + val |= APLIC_DOMAINCFG_DM; + } + + HWREG32(aplic->regs + APLIC_DOMAINCFG) = val; + + if (HWREG32(aplic->regs + APLIC_DOMAINCFG) != val) + { + LOG_W("Unable to write 0x%x in domaincfg", val); + } + + aplic->parent_irq = -1; + + aplic->parent.priv_data = aplic; + + if (msi_np) + { + aplic->parent.ops = &aplic_msi_ops; + aplic->msi_ic = rt_ofw_data(msi_np); + } + else + { + aplic->parent.ops = &aplic_direct_ops; + } + + rt_pic_linear_irq(&aplic->parent, aplic->nr_irqs); + + rt_pic_user_extends(&aplic->parent); + + return RT_EOK; + +_fail: + if (aplic->regs) + { + rt_iounmap(aplic->regs); + } + + rt_free(aplic); + + return err; +} + +static const struct rt_ofw_node_id aplic_ofw_ids[] = +{ + { .compatible = "riscv,aplic" }, + { /* sentinel */ } +}; +RT_PIC_OFW_DECLARE(aplic, aplic_ofw_ids, aplic_ofw_init); diff --git a/libcpu/risc-v/common/pic/pic-riscv-clic.c b/libcpu/risc-v/common/pic/pic-riscv-clic.c new file mode 100644 index 00000000000..9a95f0c518a --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-clic.c @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI The first version + */ + +#include +#include +#include +#include + +#define DBG_TAG "pic.clic" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include + +#define CLIC_CFG 0x0000 +#define CLIC_INFO 0x0004 +#define CLIC_VENDOR_MINTTHRESH 0x0008 +#define CLIC_INT_TRIG 0x0040 +#define CLIC_INT_IP 0x1000 +#define CLIC_INT_IE 0x1001 +#define CLIC_INT_ATTR 0x1002 +#define CLIC_INT_CTL 0x1003 + +#define CLIC_CFG_VECTORED_ENABLE BIT(0) +#define CLIC_CFG_LEVEL_SHIFT 1 +#define CLIC_CFG_LEVEL_MASK GENMASK(4, CLIC_CFG_LEVEL_SHIFT) +#define CLIC_CFG_MODE_SHIFT 5 +#define CLIC_CFG_MODE_MASK GENMASK(6, CLIC_CFG_MODE_SHIFT) + +#define CLIC_INFO_NUM_INTERRUPT(val) (val & GENMASK(12, 0)) +#define CLIC_INFO_VERSION(val) ((val & GENMASK(20, 13)) >> 13) +#define CLIC_INFO_VERSION_ARCH(val) ((val & GENMASK(20, 17)) >> 17) +#define CLIC_INFO_VERSION_IMPL(val) ((val & GENMASK(16, 13)) >> 13) +#define CLIC_INFO_INT_CTL_BITS(val) ((val & GENMASK(24, 21)) >> 21) +#define CLIC_INFO_NUM_TRIGGER(val) ((val & GENMASK(30, 25)) >> 25) + +#define CLIC_INT_TRIG_ENABLE BIT(31) +#define CLIC_INT_TRIG_IRQ_SHIFT 0 +#define CLIC_INT_TRIG_IRQ_MASK GENMASK(12, 0) + +#define CLIC_INT_IP_PENDING 1 + +#define CLIC_INT_IE_ENABLE 1 + +#define CLIC_INT_ATTR_MODE_SHIFT 6 +#define CLIC_INT_ATTR_MODE_MACHINE (0x11 << CLIC_INT_ATTR_MODE_SHIFT) +#define CLIC_INT_ATTR_MODE_SUPERVISOR (0x01 << CLIC_INT_ATTR_MODE_SHIFT) +#define CLIC_INT_ATTR_MODE_USER (0x00 << CLIC_INT_ATTR_MODE_SHIFT) +#define CLIC_INT_ATTR_TRIGGERED_SHIFT 1 +#define CLIC_INT_ATTR_TRIGGERED_MASK GENMASK(2, CLIC_INT_ATTR_TRIGGERED_SHIFT) +#define CLIC_INT_ATTR_TRIGGERED_LEVEL (0x0 << CLIC_INT_ATTR_TRIGGERED_SHIFT) +#define CLIC_INT_ATTR_TRIGGERED_EDGE (0x1 << CLIC_INT_ATTR_TRIGGERED_SHIFT) +#define CLIC_INT_ATTR_SHV BIT(0) + +#define CLIC_INT_CTL_LEVEL(nlbits, val) ((val) << (nlbits)) +#define CLIC_INT_CTL_LEVEL_MASK(nlbits) GENMASK(8, nlbits) +#define CLIC_INT_CTL_PRIORITY(nlbits, val) (val) +#define CLIC_INT_CTL_PRIORITY_MASK(nlbits) GENMASK(nlbits, 0) + +#define CLIC_INT_ID_USIP 0 /* User software Interrupt */ +#define CLIC_INT_ID_SSIP 1 /* Supervisor software Interrupt */ +#define CLIC_INT_ID_MSIP 3 /* Machine software interrupt */ +#define CLIC_INT_ID_UTIP 4 /* User timer interrupt */ +#define CLIC_INT_ID_STIP 5 /* Supervisor timer interrupt */ +#define CLIC_INT_ID_MTIP 7 /* Machine timer interrupt */ +#define CLIC_INT_ID_UEIP 8 /* User external (PLIC) interrupt */ +#define CLIC_INT_ID_SEIP 9 /* Supervisor external (PLIC) interrupt */ +#define CLIC_INT_ID_MEIP 11 /* Machine external (PLIC) interrupt */ +#define CLIC_INT_ID_CSIP 12 /* CLIC software interrupt */ +#define CLIC_INT_ID_EXT_BASE 16 /* CLIC external base */ + +#ifdef ARCH_RISCV_M_MODE +#define CLIC_INT_ID_xSIP CLIC_INT_ID_SSIP +#define CLIC_INT_ID_xTIP CLIC_INT_ID_MTIP +#define CLIC_INT_ID_xEIP CLIC_INT_ID_MEIP +#else +#define CLIC_INT_ID_xSIP CLIC_INT_ID_MSIP +#define CLIC_INT_ID_xTIP CLIC_INT_ID_STIP +#define CLIC_INT_ID_xEIP CLIC_INT_ID_SEIP +#endif + +#define CLIC_QUIRK_MODE_FIXED 0 +#define CLIC_QUIRK_MINTTHRESH 1 + +#ifdef ARCH_RISCV_M_MODE +#include "pic-riscv-clint.c" +#endif + +struct riscv_clic +{ +#ifndef PIC_DISABLE_DM + struct rt_pic parent; +#endif + + void *regs; + + rt_bitmap_t quirks; + rt_bool_t shv; + rt_uint32_t irqs_count:16; + rt_uint32_t int_ctl_bits:8; + +#ifdef RT_USING_SMP + rt_uint32_t ipi_base; + rt_atomic_t ipi_enable[RT_CPUS_NR]; + rt_atomic_t ipi_pending[RT_CPUS_NR]; +#endif +}; + +extern void fast_irq_vectors(void); + +static void riscv_clic_set_mintthresh(struct riscv_clic *clic, rt_uint32_t mintthresh) +{ + if (rt_bitmap_test_bit(&clic->quirks, CLIC_QUIRK_MINTTHRESH)) + { + HWREG32(clic->regs + CLIC_VENDOR_MINTTHRESH) = mintthresh; + } +} + +static void riscv_clic_irq_ack_raw(struct riscv_clic *clic, int hwirq) +{ + if (clic->shv) + { + return; + } + + hwirq = csr_swap(CSR_MNXTI, 0UL); +} + +static void riscv_clic_irq_mask_raw(struct riscv_clic *clic, int hwirq) +{ +#ifdef RT_USING_SMP + if (hwirq >= clic->ipi_base) + { + rt_atomic_t *ipi_enable = &clic->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_and(ipi_enable, ~BIT(hwirq - clic->ipi_base)); + + if (rt_atomic_load(ipi_enable) != 0) + { + return; + } + + hwirq = CLIC_INT_ID_xSIP; + } +#endif /* RT_USING_SMP */ + + HWREG8(clic->regs + CLIC_INT_IE + 4 * hwirq) = CLIC_INT_IE_ENABLE; +} + +static void riscv_clic_irq_unmask_raw(struct riscv_clic *clic, int hwirq) +{ +#ifdef RT_USING_SMP + if (hwirq >= clic->ipi_base) + { + rt_atomic_t *ipi_enable = &clic->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_or(ipi_enable, BIT(hwirq - clic->ipi_base)); + hwirq = CLIC_INT_ID_xSIP; + } +#endif /* RT_USING_SMP */ + + HWREG8(clic->regs + CLIC_INT_IE + 4 * hwirq) = !CLIC_INT_IE_ENABLE; +} + +static void riscv_clic_irq_send_ipi_raw(struct riscv_clic *clic, int ipi, rt_bitmap_t *cpumask) +{ + int cpu; + + rt_bitmap_for_each_set_bit(cpumask, cpu, RT_CPUS_NR) + { + rt_atomic_or(&clic->ipi_pending[cpu], BIT(ipi)); + + #ifdef ARCH_RISCV_M_MODE + clint_send_ipi(cpu); + #endif + } + +#ifndef ARCH_RISCV_M_MODE + sbi_send_ipi((const unsigned long *)cpumask); +#endif +} + +static rt_bool_t riscv_clic_handler_isr_raw(struct riscv_clic *clic, int hwirq, + rt_bool_t (*callback)(int hwirq, void *data), void *data) +{ + if (hwirq >= CLIC_INT_ID_EXT_BASE) + { + return callback(hwirq, data); + } + else if (hwirq == CLIC_INT_ID_xTIP) + { + riscv_timer_isr(); + return RT_TRUE; + } +#ifdef RT_USING_SMP + else if (hwirq == CLIC_INT_ID_xSIP) + { + int ipi; + rt_bool_t res; + rt_bitmap_t pending; + + #ifdef ARCH_RISCV_M_MODE + clint_clear_ipi(); + #endif + + pending = rt_atomic_exchange(&clic->ipi_pending[rt_hw_cpu_id()], 0); + + rt_bitmap_for_each_set_bit(&pending, ipi, RT_MAX_IPI) + { + res = callback(clic->ipi_base + ipi, data); + } + + return res; + } +#endif /* RT_USING_SMP */ + else if (hwirq != CLIC_INT_ID_xEIP) + { + LOG_E("Unhandled IRQ: %d", hwirq); + } + + return RT_FALSE; +} + +static void riscv_clic_percpu_common_init(struct riscv_clic *clic) +{ + RT_UNUSED(clic); + + csr_set(CSR_MTVT, &fast_irq_vectors); +} + +static struct riscv_clic *riscv_clic_common_init(rt_ubase_t clic_base, rt_size_t clic_size, + rt_bitmap_t quirks) +{ + rt_uint32_t value; + struct riscv_clic *clic = rt_calloc(1, sizeof(*clic)); + + if (!clic) + { + rt_set_errno(-RT_ENOMEM); + return RT_NULL; + } + + clic->regs = rt_ioremap((void *)clic_base, clic_size); + + if (!clic->regs) + { + rt_set_errno(-RT_EIO); + + rt_free(clic); + return RT_NULL; + } + + clic->quirks = quirks; + + riscv_clic_set_mintthresh(clic, 0); + + value = HWREG32(clic->regs + CLIC_INFO); + clic->int_ctl_bits = CLIC_INFO_INT_CTL_BITS(value); + clic->irqs_count = CLIC_INFO_NUM_INTERRUPT(value); + + HWREG32(clic->regs + CLIC_CFG) |= CLIC_CFG_VECTORED_ENABLE; + HWREG32(clic->regs + CLIC_CFG) |= 8 << CLIC_CFG_LEVEL_SHIFT; + HWREG32(clic->regs + CLIC_CFG) |= CLIC_CFG_MODE_MASK << CLIC_CFG_MODE_SHIFT; + + clic->shv = !!(HWREG32(clic->regs + CLIC_CFG) & CLIC_CFG_VECTORED_ENABLE); + + LOG_D("Version %d.%d, %d IRQs implemented", + CLIC_INFO_VERSION_ARCH(value), CLIC_INFO_VERSION_IMPL(value), + clic->irqs_count); + +#ifdef RT_USING_SMP + clic->irqs_count += RT_MAX_IPI; +#endif + + value = clic->shv ? CLIC_INT_ATTR_SHV : 0; +#ifdef ARCH_RISCV_M_MODE + value |= CLIC_INT_ATTR_MODE_MACHINE << CLIC_INT_ATTR_MODE_SHIFT; +#else + value |= CLIC_INT_ATTR_MODE_SUPERVISOR << CLIC_INT_ATTR_MODE_SHIFT; +#endif + + for (int hwirq = 0; hwirq < clic->irqs_count; ++hwirq) + { + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) &= CLIC_INT_ATTR_TRIGGERED_MASK; + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) |= value; + } + + return clic; +} + +#ifndef PIC_DISABLE_DM +static rt_err_t riscv_clic_irq_init(struct rt_pic *pic) +{ + struct riscv_clic *clic = pirq->pic->priv_data; + + riscv_clic_percpu_common_init(clic); + + return RT_EOK; +} + +static void riscv_clic_irq_ack(struct rt_pic_irq *pirq) +{ + return riscv_clic_irq_ack_raw(pirq->hwirq); +} + +static void riscv_clic_irq_mask(struct rt_pic_irq *pirq) +{ + struct riscv_clic *clic = pirq->pic->priv_data; + + return riscv_clic_irq_mask_raw(clic, pirq->hwirq); +} + +static void riscv_clic_irq_unmask(struct rt_pic_irq *pirq) +{ + struct riscv_clic *clic = pirq->pic->priv_data; + + return riscv_clic_irq_unmask_raw(clic, pirq->hwirq); +} + +static rt_err_t riscv_clic_irq_set_priority(struct rt_pic_irq *pirq, rt_uint32_t priority) +{ + struct riscv_clic *clic = pirq->pic->priv_data; + + priority = rt_min_t(rt_uint32_t, priority, GENMASK(8, 8 - clic->int_ctl_bits)); + + HWREG8(clic->regs + CLIC_INT_CTL + pirq->hwirq * 4) = + CLIC_INT_CTL_LEVEL_MASK(clic->int_ctl_bits) | + CLIC_INT_CTL_PRIORITY(clic->int_ctl_bits, priority); + + return RT_EOK; +} + +static rt_err_t riscv_clic_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode) +{ + int hwirq = pirq->hwirq; + struct riscv_clic *clic = pirq->pic->priv_data; + + if (rt_bitmap_test_bit(&clic->quirks, PLIC_QUIRK_EDGE_INTERRUPT)) + { + return -RT_ENOSYS; + } + + if (mode == RT_IRQ_MODE_EDGE_RISING) + { + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) &= CLIC_INT_ATTR_TRIGGERED_MASK; + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) |= CLIC_INT_ATTR_TRIGGERED_EDGE; + + return RT_EOK; + } + else if (mode == RT_IRQ_MODE_LEVEL_HIGH) + { + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) &= CLIC_INT_ATTR_TRIGGERED_MASK; + HWREG8(clic->regs + CLIC_INT_ATTR + 4 * hwirq) |= CLIC_INT_ATTR_TRIGGERED_LEVEL; + + return RT_EOK; + } + + return -RT_ENOSYS; +} + +static void riscv_clic_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask) +{ + struct riscv_clic *clic = pirq->pic->priv_data; + + riscv_clic_irq_send_ipi_raw(clic, pirq->hwirq, cpumask); +} + +static int riscv_clic_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + return rt_pic_config_irq(pic, hwirq, hwirq); +} + +static rt_err_t riscv_clic_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + struct riscv_clic *clic = pic->priv_data; + + out_pirq->hwirq = args->args[0]; + + if (rt_bitmap_test_bit(&clic->quirks, CLIC_QUIRK_MODE_FIXED)) + { + out_pirq->mode = args->args[1]; + out_pirq->priority = args->args[2]; + } + else + { + out_pirq->mode = RT_IRQ_MODE_LEVEL_HIGH; + out_pirq->priority = args->args[1]; + } + + return RT_EOK; +} + +const static struct rt_pic_ops riscv_clic_ops = +{ + .name = "CLIC", + .irq_init = riscv_clic_irq_init, + .irq_ack = riscv_clic_irq_ack, + .irq_mask = riscv_clic_irq_mask, + .irq_unmask = riscv_clic_irq_unmask, + .irq_set_priority = riscv_clic_irq_set_priority, + .irq_set_triger_mode = riscv_clic_irq_set_triger_mode, + .irq_send_ipi = riscv_clic_irq_send_ipi, + .irq_map = riscv_clic_irq_map, + .irq_parse = riscv_clic_irq_parse, +}; + +static rt_bool_t clic_common_handler_isr(int hwirq, void *data) +{ + struct rt_pic_irq *pirq; + struct riscv_clic *clic = data; + + if (hwirq < clic->ipi_base) + { + pirq = rt_pic_find_irq(&clic->parent, hwirq); + } + else + { + pirq = rt_pic_find_ipi(&clic->parent, hwirq - clic->ipi_base); + } + + riscv_clic_irq_ack(pirq); + + return rt_pic_handle_isr(pirq); +} + +static rt_bool_t clic_handler(void *data) +{ + rt_ubase_t cause; + struct riscv_clic *clic = data; + + cause = csr_read(CSR_CAUSE) & ~CAUSE_IRQ_FLAG; + + return riscv_clic_handler_isr_raw(clic, cause, clic_common_handler_isr, clic); +} + +static rt_err_t riscv_clic_ofw_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id) +{ + rt_err_t err; + rt_uint64_t clic_base, clic_size; + rt_bitmap_t quirks; + struct riscv_clic *clic; + + if ((err = rt_ofw_get_address(np, 0, &clic_base, &clic_size))) + { + return err; + } + + quirks = id->data ? *(rt_ubase_t *)id->data : 0; + + if (!(clic = clic_common_init(clic_base, clic_size, quirks))) + { + return rt_get_errno(); + } + +#ifdef ARCH_RISCV_M_MODE + riscv_clint_ofw_init(); +#endif + + clic->parent.priv_data = clic; + clic->parent.ops = &riscv_clic_ops; + rt_ofw_data(np) = &clic->parent; + + rt_pic_linear_irq(&clic->parent, clic->irqs_count); + + rt_pic_add_traps(clic_handler, clic); + +#ifdef RT_USING_SMP + clic->ipi_base = clic->irqs_count - RT_MAX_IPI; + + for (int ipi = 0; ipi < RT_MAX_IPI; ++ipi) + { + rt_pic_config_ipi(&clic->parent, ipi, clic->ipi_base + ipi); + } +#endif /* RT_USING_SMP */ + + rt_pic_user_extends(&clic->parent); + + return RT_EOK; +} + +static rt_bitmap_t xtensa_clic_quirk = RT_BIT(CLIC_QUIRK_MODE_FIXED) | RT_BIT(CLIC_QUIRK_MINTTHRESH); + +static const struct rt_ofw_node_id clic_ofw_ids[] = +{ + { .compatible = "cdns,xtensa-core-intc", .data = &xtensa_clic_quirk }, + { .compatible = "nuclei,eclic" }, + { .compatible = "nordic,nrf-clic" }, + { /* sentinel */ } +}; +RT_PIC_OFW_DECLARE(riscv_clic, riscv_clic_ofw_ids, riscv_clic_ofw_init); +#endif /* PIC_DISABLE_DM */ diff --git a/libcpu/risc-v/common/pic/pic-riscv-clint.c b/libcpu/risc-v/common/pic/pic-riscv-clint.c new file mode 100644 index 00000000000..a03c886e081 --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-clint.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include +#include + +#include +#include + +#define CLINT_IPI_OFF 0 +#define CLINT_TIMER_CMP_OFF 0x4000 +#define CLINT_TIMER_VAL_OFF 0xbff8 + +#define CLINT_QUICKS_IPI_FORCE 0 + +rt_uint32_t *riscv_clint_ipi_base, *riscv_aclint_ipi_base; + +rt_inline void clint_send_ipi(int cpu) +{ + if (riscv_clint_ipi_base) + { + HWREG32(riscv_clint_ipi_base + riscv_cpu_id_to_hartid(cpu)) = 1; + } +} + +rt_inline void clint_clear_ipi(void) +{ + if (riscv_clint_ipi_base) + { + HWREG32(riscv_clint_ipi_base + csr_read(CSR_MHARTID)) = 0; + } +} + +static rt_err_t riscv_clint_common_init(rt_ubase_t *mmio_ranges, unsigned mmio_count) +{ + void *clint_timer_val, *clint_timer_cmp; + + if (mmio_count == 1) + { + void *base = rt_ioremap((void *)mmio_ranges[0], mmio_ranges[1]); + + if (!base) + { + return -RT_EIO; + } + + riscv_clint_ipi_base = base + CLINT_IPI_OFF; + clint_timer_cmp = base + CLINT_TIMER_CMP_OFF; + clint_timer_val = base + CLINT_TIMER_VAL_OFF; + } + else + { + riscv_clint_ipi_base = RT_NULL; + + clint_timer_val = rt_ioremap((void *)mmio_ranges[0], mmio_ranges[1]); + + if (!clint_timer_val) + { + return -RT_EIO; + } + + clint_timer_cmp = rt_ioremap((void *)mmio_ranges[2], mmio_ranges[3]); + + if (!clint_timer_cmp) + { + rt_iounmap(clint_timer_val); + return -RT_EIO; + } + } + + riscv_timer_probe(clint_timer_cmp, clint_timer_val); + + return RT_EOK; +} + +#ifndef PIC_DISABLE_DM +static rt_ubase_t aclint_quicks = RT_BIT(CLINT_QUICKS_IPI_FORCE); + +static const struct rt_ofw_node_id riscv_clint_ofw_ids[] = +{ + { .compatible = "riscv,clint0", }, + { .compatible = "sifive,clint0", }, +#ifdef ARCH_RISCV_M_MODE + { .compatible = "riscv,aclint-mtimer", }, + { .compatible = "riscv,aclint-mswi", .data = &aclint_quicks }, +#else + { .compatible = "riscv,aclint-sswi", .data = &aclint_quicks }, +#endif + { /* sentinel */ } +}; + +static rt_err_t riscv_clint_ofw_init(void) +{ + rt_err_t err; + rt_ubase_t quicks; + unsigned mmio_count; + rt_uint64_t addr, size; + rt_ubase_t mmio_ranges[4]; + struct rt_ofw_node *np; + const struct rt_ofw_node_id *id; + + if (!(np = rt_ofw_find_node_by_ids_r(RT_NULL, riscv_clint_ofw_ids, &id))) + { + return -RT_ENOSYS; + } + quicks = id->data ? *(rt_ubase_t *)id->data : 0; + + if ((err = rt_ofw_get_address(np, 0, &addr, &size))) + { + return err; + } + + mmio_ranges[0] = addr; + mmio_ranges[1] = size; + mmio_count = 1; + + if (!rt_ofw_get_address(np, 1, &addr, &size)) + { + mmio_ranges[2] = addr; + mmio_ranges[3] = size; + mmio_count = 2; + } + + rt_ofw_node_set_flag(np, RT_OFW_F_READLY); + + if (!(err = riscv_clint_common_init(mmio_ranges, mmio_count))) + { + if (quicks & CLINT_QUICKS_IPI_FORCE) + { + riscv_aclint_ipi_base = riscv_clint_ipi_base; + } + } + + return err; +} +#endif /* !PIC_DISABLE_DM */ diff --git a/libcpu/risc-v/common/pic/pic-riscv-imsic.c b/libcpu/risc-v/common/pic/pic-riscv-imsic.c new file mode 100644 index 00000000000..4cc73cbd17e --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-imsic.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include +#include +#include + +#define DBG_TAG "pic.imsic" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include "pic-riscv-imsic.h" + +#define IMSIC_ID_START 1 +#define IMSIC_IPI_ID IMSIC_ID_START + +#define IMSIC_ENABLE_EIDELIVERY 1 +#define IMSIC_DISABLE_EIDELIVERY 0 +#define IMSIC_ENABLE_EITHRESHOLD 0 +#define IMSIC_DISABLE_EITHRESHOLD 1 + +struct riscv_imsic_mmio +{ + rt_uint64_t addr; + rt_uint64_t size; + + void *mapped; +}; + +struct riscv_imsic +{ + struct rt_pic parent; + struct rt_pic *parent_ic; + + struct rt_ofw_node *np; + + int parent_irq; + int msi_id_start; + int init_cpu_id; + + struct imsic_global_config global; + + rt_bitmap_t *vectors; + struct rt_spinlock lock; +}; + +extern rt_uint32_t *riscv_aclint_ipi_base; + +rt_inline unsigned int __fls(unsigned long word) +{ + unsigned int num = RT_BITS_PER_LONG - 1; + +#if RT_BITS_PER_LONG == 64 + if (!(word & (~0UL << 32))) + { + num -= 32; + word <<= 32; + } +#endif + if (!(word & (~0UL << (RT_BITS_PER_LONG - 16)))) + { + num -= 16; + word <<= 16; + } + if (!(word & (~0UL << (RT_BITS_PER_LONG - 8)))) + { + num -= 8; + word <<= 8; + } + if (!(word & (~0UL << (RT_BITS_PER_LONG - 4)))) + { + num -= 4; + word <<= 4; + } + if (!(word & (~0UL << (RT_BITS_PER_LONG - 2)))) + { + num -= 2; + word <<= 2; + } + if (!(word & (~0UL << (RT_BITS_PER_LONG - 1)))) + { + num -= 1; + } + return num; +} + +rt_inline void imsic_csr_write(rt_ubase_t reg, rt_ubase_t val) +{ + csr_write(CSR_ISELECT, reg); + csr_write(CSR_IREG, val); +} + +rt_inline rt_ubase_t imsic_csr_read(rt_ubase_t reg) +{ + csr_write(CSR_ISELECT, reg); + return csr_read(CSR_IREG); +} + +rt_inline rt_ubase_t imsic_csr_read_clear(rt_ubase_t reg, rt_ubase_t val) +{ + csr_write(CSR_ISELECT, reg); + return csr_read_clear(CSR_IREG, val); +} + +rt_inline void imsic_csr_set(rt_ubase_t reg, rt_ubase_t val) +{ + csr_write(CSR_ISELECT, reg); + csr_set(CSR_IREG, val); +} + +rt_inline void imsic_csr_clear(rt_ubase_t reg, rt_ubase_t val) +{ + csr_write(CSR_ISELECT, reg); + csr_clear(CSR_IREG, val); +} + +static void imsic_eix_update(rt_ubase_t base_id, rt_ubase_t num_id, rt_bool_t pend, rt_bool_t val) +{ + rt_ubase_t id = base_id, last_id = base_id + num_id, isel, ireg; + + while (id < last_id) + { + isel = id / RT_BITS_PER_LONG; + isel *= RT_BITS_PER_LONG / IMSIC_EIPx_BITS; + isel += pend ? IMSIC_EIP0 : IMSIC_EIE0; + + /* + * Prepare the ID mask to be programmed in the + * IMSIC EIEx and EIPx registers. These registers + * are XLEN-wide and we must not touch IDs which + * are < base_id and >= (base_id + num_id). + */ + ireg = 0; + for (rt_ubase_t i = id & (__riscv_xlen - 1); id < last_id && i < __riscv_xlen; ++i) + { + ireg |= RT_BIT(i); + id++; + } + + /* + * The IMSIC EIEx and EIPx registers are indirectly + * accessed via using ISELECT and IREG CSRs so we + * need to access these CSRs without getting preempted. + * + * All existing users of this function call this + * function with local IRQs disabled so we don't + * need to do anything special here. + */ + if (val) + { + imsic_csr_set(isel, ireg); + } + else + { + imsic_csr_clear(isel, ireg); + } + } +} + +rt_inline void imsic_id_clear_enable(rt_ubase_t id) +{ + imsic_eix_update(id, 1, RT_FALSE, RT_FALSE); +} + +rt_inline void imsic_id_set_enable(rt_ubase_t id) +{ + imsic_eix_update(id, 1, RT_FALSE, RT_TRUE); +} + +rt_inline void imsic_local_delivery(rt_bool_t enable) +{ + if (enable) + { + imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD); + imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY); + } + else + { + imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_DISABLE_EIDELIVERY); + imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_DISABLE_EITHRESHOLD); + } +} + +static void imsic_handler(int hwirq, void *data); + +static rt_err_t riscv_imsic_irq_init(struct rt_pic *pic) +{ + struct riscv_imsic *imsic = pic->priv_data; + + imsic_local_delivery(RT_TRUE); + + for (int hwirq = IMSIC_ID_START; hwirq < imsic->global.nr_ids; ++hwirq) + { + /* + * Enable all ID in current CPU + * that will not sync by IPI in mask/umask. + */ + imsic_id_set_enable(hwirq); + } + + if (imsic->parent_irq < 0) + { + struct rt_ofw_cell_args irq_args; + + if (rt_ofw_parse_irq_cells(imsic->np, 0, &irq_args)) + { + LOG_E("%s: Parent IRQ is not available", rt_ofw_node_full_name(imsic->np)); + return RT_EOK; + } + + /* Create mapping */ + irq_args.args[0] = RV_IRQ_EXT; + + imsic->parent_irq = rt_ofw_map_irq(&irq_args); + + rt_hw_interrupt_install(imsic->parent_irq, imsic_handler, imsic, "IMSIC"); + } + + rt_pic_irq_unmask(imsic->parent_irq); + + return RT_EOK; +} + +static void riscv_imsic_irq_mask(struct rt_pic_irq *pirq) +{ + if (pirq->msi_desc) + { + rt_pci_msi_mask_irq(pirq); + } + +#if defined(RT_USING_SMP) && defined(ARCH_RISCV_M_MODE) + if (pirq->irq < RT_MAX_IPI) + { + imsic_id_clear_enable(pirq->hwirq); + } +#endif +} + +static void riscv_imsic_irq_unmask(struct rt_pic_irq *pirq) +{ + if (pirq->msi_desc) + { + rt_pci_msi_unmask_irq(pirq); + } + +#if defined(RT_USING_SMP) && defined(ARCH_RISCV_M_MODE) + if (pirq->irq < RT_MAX_IPI) + { + imsic_id_set_enable(pirq->hwirq); + } +#endif +} + +static rt_err_t riscv_imsic_irq_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *affinity) +{ + struct rt_pci_msi_desc *desc = pirq->msi_desc; + + if (desc) + { + int old_cpu, cpu; + + cpu = rt_bitmap_next_set_bit(affinity, 0, RT_CPUS_NR); + + /* IMSIC supports only one HART affinity */ + if (rt_bitmap_next_set_bit(affinity, cpu, RT_CPUS_NR) != RT_CPUS_NR) + { + return -RT_ENOSYS; + } + + old_cpu = rt_bitmap_next_set_bit(pirq->affinity, 0, RT_CPUS_NR); + + if (cpu == old_cpu) + { + return RT_EOK; + } + + RT_IRQ_AFFINITY_CLEAR(pirq->affinity, old_cpu); + RT_IRQ_AFFINITY_SET(pirq->affinity, cpu); + + /* Update MSI info */ + pirq->pic->ops->irq_compose_msi_msg(pirq, &desc->msg); + + /* Update for PCI device */ + rt_pci_msi_write_msg(desc, &desc->msg); + + return RT_EOK; + } + + return -RT_EINVAL; +} + +#ifdef ARCH_RISCV_M_MODE +static void riscv_imsic_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask) +{ + int cpu_id; + struct imsic_local_config *local; + struct riscv_imsic *imsic = pirq->pic->priv_data; + + rt_bitmap_for_each_set_bit(cpumask, cpu_id, RT_CPUS_NR) + { + local = &imsic->global.local[cpu_id]; + + HWREG32(local->msi) = pirq->hwirq; + } +} +#endif /* ARCH_RISCV_M_MODE */ + +static void riscv_imsic_irq_compose_msi_msg(struct rt_pic_irq *pirq, struct rt_pci_msi_msg *msg) +{ + struct imsic_local_config *local; + struct imsic_global_config *global; + struct riscv_imsic *imsic = pirq->pic->priv_data; + + global = &imsic->global; + + if (RT_BIT(global->guest_index_bits) <= 0) + { + LOG_W("Global guest disabled"); + return; + } + + local = &global->local[rt_bitmap_next_set_bit(pirq->affinity, 0, RT_CPUS_NR)]; + + msg->address_hi = rt_upper_32_bits(local->msi_phy); + msg->address_lo = rt_lower_32_bits(local->msi_phy); + msg->data = pirq->hwirq; +} + +static void riscv_imsic_irq_write_msi_msg(struct rt_pic_irq *pirq, struct rt_pci_msi_msg *msg) +{ + struct rt_pic_irq virtual_pirq; + struct riscv_imsic *imsic = pirq->pic->priv_data; + + virtual_pirq.pic = imsic->parent_ic; + virtual_pirq.hwirq = pirq->hwirq; + + imsic->parent_ic->ops->irq_write_msi_msg(&virtual_pirq, msg); +} + +static int riscv_imsic_irq_alloc_msi(struct rt_pic *pic, struct rt_pci_msi_desc *msi_desc) +{ + rt_ubase_t level; + int irq, hwirq_index; + struct rt_pic_irq *pirq; + struct imsic_global_config *global; + struct riscv_imsic *imsic = pic->priv_data; + + global = &imsic->global; + + level = rt_spin_lock_irqsave(&imsic->lock); + hwirq_index = rt_bitmap_next_clear_bit(imsic->vectors, 0, global->nr_ids); + + if (hwirq_index >= global->nr_ids) + { + irq = -RT_EEMPTY; + goto _out_lock; + } + + irq = rt_pic_config_irq(pic, hwirq_index, hwirq_index + IMSIC_ID_START); + if (irq < 0) + { + goto _out_lock; + } + pirq = rt_pic_find_irq(pic, hwirq_index); + pirq->mode = RT_IRQ_MODE_EDGE_RISING; + RT_IRQ_AFFINITY_SET(pirq->affinity, imsic->init_cpu_id); + + rt_bitmap_set_bit(imsic->vectors, hwirq_index); + +_out_lock: + rt_spin_unlock_irqrestore(&imsic->lock, level); + + return irq; +} + +static void riscv_imsic_irq_free_msi(struct rt_pic *pic, int irq) +{ + rt_ubase_t level; + struct rt_pic_irq *pirq; + struct riscv_imsic *imsic; + + pirq = rt_pic_find_pirq(pic, irq); + + if (!pirq) + { + return; + } + + imsic = pirq->pic->priv_data; + + level = rt_spin_lock_irqsave(&imsic->lock); + rt_bitmap_clear_bit(imsic->vectors, pirq->hwirq - IMSIC_ID_START); + rt_spin_unlock_irqrestore(&imsic->lock, level); +} + +const static struct rt_pic_ops riscv_imsic_ops = +{ + .name = "IMSIC", + .irq_init = riscv_imsic_irq_init, + .irq_mask = riscv_imsic_irq_mask, + .irq_unmask = riscv_imsic_irq_unmask, + .irq_set_affinity = riscv_imsic_irq_set_affinity, +#ifdef ARCH_RISCV_M_MODE + .irq_send_ipi = riscv_imsic_irq_send_ipi, +#endif + .irq_compose_msi_msg = riscv_imsic_irq_compose_msi_msg, + .irq_write_msi_msg = riscv_imsic_irq_write_msi_msg, + .irq_alloc_msi = riscv_imsic_irq_alloc_msi, + .irq_free_msi = riscv_imsic_irq_free_msi, +}; + +static void imsic_handler(int hwirq, void *data) +{ + rt_ubase_t local_id; + struct rt_pic_irq *pirq; + struct riscv_imsic *imsic = data; + + while ((local_id = csr_swap(CSR_TOPEI, 0))) + { + local_id >>= TOPEI_ID_SHIFT; + + if (local_id >= imsic->msi_id_start) + { + pirq = rt_pic_find_irq(&imsic->parent, local_id - IMSIC_ID_START); + } + else + { + #if defined(RT_USING_SMP) && defined(ARCH_RISCV_M_MODE) + pirq = rt_pic_find_ipi(&imsic->parent, local_id - IMSIC_IPI_ID); + #else + LOG_E("It's is impossible"); + RT_ASSERT(0); + #endif + } + + rt_pic_handle_isr(pirq); + } +} + +const struct imsic_global_config *imsic_global_config_read(struct rt_ofw_node *np) +{ + struct riscv_imsic *imsic = rt_container_of(rt_ofw_data(np), struct riscv_imsic, parent); + + return imsic ? &imsic->global : RT_NULL; +} + +static const struct rt_ofw_node_id riscv_imsic_ofw_ids[] = +{ + { .compatible = "riscv,imsics" }, + { /* sentinel */ } +}; + +rt_err_t imsic_ofw_probe(struct rt_ofw_node *np, + struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *ic_id) +{ + rt_err_t err; + int irq_count, mmio_count, i; + struct rt_ofw_node_id *id; + struct riscv_imsic *imsic; + struct imsic_global_config *global; + struct riscv_imsic_mmio *mmio = RT_NULL; + + if (!(id = rt_ofw_node_match(np, riscv_imsic_ofw_ids))) + { + return -RT_EINVAL; + } + + if (!(imsic = rt_calloc(1, sizeof(*imsic)))) + { + return -RT_ENOMEM; + } + global = &imsic->global; + + irq_count = rt_ofw_get_irq_count(np); + + rt_ofw_prop_read_u32(np, "riscv,guest-index-bits", &global->guest_index_bits); + + if (rt_ofw_prop_read_u32(np, "riscv,hart-index-bits", &global->hart_index_bits)) + { + global->hart_index_bits = __fls(irq_count); + + if (RT_BIT(global->hart_index_bits) < irq_count) + { + ++global->hart_index_bits; + } + } + + rt_ofw_prop_read_u32(np, "riscv,group-index-bits", &global->guest_index_bits); + + if (rt_ofw_prop_read_u32(np, "riscv,group-index-shift", &global->group_index_shift)) + { + global->group_index_shift = IMSIC_MMIO_PAGE_SHIFT * 2; + } + + if ((err = rt_ofw_prop_read_u32(np, "riscv,num-ids", &global->nr_ids))) + { + LOG_E("%s: Number of IRQ is unknown", rt_ofw_node_full_name(np)); + goto _fail; + } + + if (rt_ofw_prop_read_u32(np, "riscv,num-guest-ids", &global->nr_guest_ids)) + { + global->nr_guest_ids = global->nr_ids; + } + + /* Sanity check guest index bits */ + i = RT_BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT; + if (i < global->guest_index_bits) + { + LOG_E("%s: %s index %s too big", "Guest", "bits", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + /* Sanity check HART index bits */ + i = RT_BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT - global->guest_index_bits; + if (i < global->hart_index_bits) + { + LOG_E("%s: %s index %s too big", "HART", "bits", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + /* Sanity check group index bits */ + i = RT_BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT - global->guest_index_bits - global->hart_index_bits; + if (i < global->group_index_bits) + { + LOG_E("%s: %s index %s too big", "Group", "bits", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + /* Sanity check group index shift */ + i = global->group_index_bits + global->group_index_shift - 1; + if (i >= RT_BITS_PER_LONG) + { + LOG_E("%s: %s index %s too big", "Group", "shift", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + /* Sanity check number of interrupt identities */ + if (global->nr_ids < IMSIC_MIN_ID || + global->nr_ids >= IMSIC_MAX_ID || + (global->nr_ids & IMSIC_MIN_ID) != IMSIC_MIN_ID) + { + LOG_E("%s: Invalid number of %sinterrupt identities", "", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + /* Sanity check number of guest interrupt identities */ + if (global->nr_guest_ids < IMSIC_MIN_ID || + global->nr_guest_ids >= IMSIC_MAX_ID || + (global->nr_guest_ids & IMSIC_MIN_ID) != IMSIC_MIN_ID) + { + LOG_E("%s: Invalid number of %sinterrupt identities", "guest ", rt_ofw_node_full_name(np)); + + err = -RT_EINVAL; + goto _fail; + } + + mmio_count = rt_ofw_get_address_count(np); + mmio = rt_calloc(mmio_count, sizeof(*mmio)); + + if (!mmio) + { + err = -RT_ENOMEM; + goto _fail; + } + + for (int i = 0; i < mmio_count; ++i) + { + rt_ubase_t base_addr; + + if ((err = rt_ofw_get_address(np, 0, &mmio[i].addr, &mmio[i].size))) + { + goto _fail; + } + + if (i == 0) + { + global->base_addr = mmio[i].addr; + global->base_addr &= ~(RT_BIT(global->guest_index_bits + + global->hart_index_bits + IMSIC_MMIO_PAGE_SHIFT) - 1); + global->base_addr &= ~((RT_BIT(global->group_index_bits) - 1) << + global->group_index_shift); + } + + base_addr = mmio[i].addr; + base_addr &= ~(RT_BIT(global->guest_index_bits + + global->hart_index_bits + IMSIC_MMIO_PAGE_SHIFT) - 1); + base_addr &= ~((RT_BIT(global->group_index_bits) - 1) << + global->group_index_shift); + + if (base_addr != global->base_addr) + { + err = -RT_EINVAL; + goto _fail; + } + + mmio[i].mapped = rt_ioremap((void *)mmio[i].addr, mmio[i].size); + + if (!mmio[i].mapped) + { + err = -RT_EIO; + goto _fail; + } + } + + for (int i = 0; i < irq_count; ++i) + { + int cpu_id; + int index, reloff; + rt_ubase_t hartid; + struct rt_ofw_node *cpu_np; + struct rt_ofw_cell_args arg; + struct imsic_local_config *local; + + if (rt_ofw_parse_irq_cells(np, i, &arg)) + { + continue; + } + + cpu_np = rt_ofw_get_parent(arg.data); + hartid = rt_ofw_get_cpu_hwid(cpu_np, 0); + rt_ofw_node_put(cpu_np); + + cpu_id = riscv_hartid_to_cpu_id(hartid); + + if (cpu_id >= RT_CPUS_NR) + { + continue; + } + + /* Find MMIO location of MSI page */ + index = mmio_count; + reloff = i * RT_BIT(global->guest_index_bits) * IMSIC_MMIO_PAGE_SZ; + for (int j = 0; mmio_count; ++j) + { + if (reloff < mmio[j].size) + { + index = j; + break; + } + + /* + * MMIO region size may not be aligned to + * RT_BIT(global->guest_index_bits) * IMSIC_MMIO_PAGE_SZ + * if holes are present. + */ + reloff -= RT_ALIGN(mmio[j].size, RT_BIT(global->guest_index_bits) * IMSIC_MMIO_PAGE_SZ); + } + + if (index >= mmio_count) + { + LOG_E("%s: MMIO not found for parent IRQ[%d]", rt_ofw_node_full_name(np), i); + continue; + } + + local = &global->local[cpu_id]; + local->msi_phy = mmio[index].addr + reloff; + local->msi = mmio[index].mapped + reloff; + } + rt_free(mmio); + + if (!(imsic->vectors = rt_calloc(1, RT_BITMAP_LEN(global->nr_ids) * sizeof(rt_bitmap_t)))) + { + err = -RT_ENOMEM; + goto _fail; + } + + rt_spin_lock_init(&imsic->lock); + + imsic->np = np; + imsic->parent_irq = -1; + imsic->init_cpu_id = rt_hw_cpu_id(); + + imsic->parent.priv_data = imsic; + imsic->parent.ops = &riscv_imsic_ops; + + imsic->parent_ic = rt_ofw_data(ic_np); + + rt_ofw_data(np) = &imsic->parent; + rt_ofw_node_set_flag(np, RT_OFW_F_READLY); + + rt_pic_linear_irq(&imsic->parent, global->nr_ids); + + imsic->msi_id_start = IMSIC_ID_START; + +#if defined(RT_USING_SMP) && defined(ARCH_RISCV_M_MODE) + if (!riscv_aclint_ipi_base) + { + for (int ipi = 0; ipi < RT_MAX_IPI; ++ipi) + { + int hwirq = IMSIC_IPI_ID + ipi; + + rt_bitmap_set_bit(imsic->vectors, hwirq); + rt_pic_config_ipi(&imsic->parent, ipi, hwirq); + } + + imsic->msi_id_start += RT_MAX_IPI; + } +#endif /* RT_USING_SMP && ARCH_RISCV_M_MODE */ + + rt_pic_user_extends(&imsic->parent); + + return RT_EOK; + +_fail: + if (mmio) + { + for (int i = 0; mmio[i].mapped && i < mmio_count; ++i) + { + rt_iounmap(mmio[i].mapped); + } + + rt_free(mmio); + } + + rt_free(imsic); + + return err; +} diff --git a/libcpu/risc-v/common/pic/pic-riscv-imsic.h b/libcpu/risc-v/common/pic/pic-riscv-imsic.h new file mode 100644 index 00000000000..523526c70a1 --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-imsic.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#ifndef __PIC_RISCV_IMSIC_H__ +#define __PIC_RISCV_IMSIC_H__ + +#include +#include +#include + +#define IMSIC_MMIO_PAGE_SHIFT 12 +#define IMSIC_MMIO_PAGE_SZ RT_BIT(IMSIC_MMIO_PAGE_SHIFT) +#define IMSIC_MMIO_PAGE_LE 0x00 +#define IMSIC_MMIO_PAGE_BE 0x04 + +#define IMSIC_MIN_ID 63 +#define IMSIC_MAX_ID 2048 + +#define IMSIC_EIDELIVERY 0x70 + +#define IMSIC_EITHRESHOLD 0x72 + +#define IMSIC_EIP0 0x80 +#define IMSIC_EIP63 0xbf +#define IMSIC_EIPx_BITS 32 + +#define IMSIC_EIE0 0xc0 +#define IMSIC_EIE63 0xff +#define IMSIC_EIEx_BITS 32 + +#define IMSIC_FIRST IMSIC_EIDELIVERY +#define IMSIC_LAST IMSIC_EIE63 + +#define IMSIC_MMIO_SETIPNUM_LE 0x00 +#define IMSIC_MMIO_SETIPNUM_BE 0x04 + +struct imsic_local_config +{ + void *msi; + rt_uint64_t msi_phy; +}; + +struct imsic_global_config +{ + /* + * MSI Target Address Scheme + * + * XLEN-1 12 0 + * | | | + * ------------------------------------------------------------- + * |xxxxxx|Group Index|xxxxxxxxxxx|HART Index|Guest Index| 0 | + * ------------------------------------------------------------- + */ + + /* Bits representing Guest index, HART index, and Group index */ + rt_uint32_t guest_index_bits; + rt_uint32_t hart_index_bits; + rt_uint32_t group_index_bits; + rt_uint32_t group_index_shift; + + /* Global base address matching all target MSI addresses */ + rt_ubase_t base_addr; + + /* Number of interrupt identities */ + rt_uint32_t nr_ids; + + /* Number of guest interrupt identities */ + rt_uint32_t nr_guest_ids; + + /* IMSIC addresses */ + struct imsic_local_config local[RT_CPUS_NR]; +}; + +const struct imsic_global_config *imsic_global_config_read(struct rt_ofw_node *np); +rt_err_t imsic_ofw_probe(struct rt_ofw_node *np, + struct rt_ofw_node *ic_np, const struct rt_ofw_node_id *ic_id); + +#endif /* __PIC_RISCV_IMSIC_H__ */ diff --git a/libcpu/risc-v/common/pic/pic-riscv-intc-andes.h b/libcpu/risc-v/common/pic/pic-riscv-intc-andes.h new file mode 100644 index 00000000000..e9358510db6 --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-intc-andes.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#ifndef __PIC_RISCV_INTC_ANDES_H__ +#define __PIC_RISCV_INTC_ANDES_H__ + +/* Andes PMU irq number */ +#define ANDES_RV_IRQ_PMOVI 18 +#define ANDES_RV_IRQ_LAST ANDES_RV_IRQ_PMOVI +#define ANDES_SLI_CAUSE_BASE 256 + +/* Andes PMU related registers */ +#define ANDES_CSR_SLIE 0x9c4 +#define ANDES_CSR_SLIP 0x9c5 +#define ANDES_CSR_SCOUNTEROF 0x9d4 + +#endif /* __PIC_RISCV_INTC_ANDES_H__ */ diff --git a/libcpu/risc-v/common/pic/pic-riscv-intc.c b/libcpu/risc-v/common/pic/pic-riscv-intc.c new file mode 100644 index 00000000000..c3987536b8e --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-riscv-intc.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include +#include +#include +#include + +#define DBG_TAG "pic.riscv" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include +#include +#include + +#include "pic-riscv-intc-andes.h" + +#include "pic-riscv-clint.c" + +struct riscv_intc +{ +#ifndef PIC_DISABLE_DM + struct rt_pic parent; +#endif /* !PIC_DISABLE_DM */ + + rt_uint32_t irqs_base; + rt_uint32_t irqs_count; + rt_uint32_t irqs_def_count; + +#ifdef RT_USING_SMP + rt_uint32_t ipi_base; + rt_atomic_t ipi_enable[RT_CPUS_NR]; + rt_atomic_t ipi_pending[RT_CPUS_NR]; +#endif +}; + +static struct riscv_intc system_rv_intc; + +rt_inline void riscv_intc_irq_mask_raw(struct riscv_intc *rv_intc, int hwirq) +{ +#ifdef RT_USING_SMP + if (hwirq >= rv_intc->ipi_base) + { + rt_atomic_t *ipi_enable = &rv_intc->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_and(ipi_enable, ~BIT(hwirq - rv_intc->ipi_base)); + + if (rt_atomic_load(ipi_enable) != 0) + { + return; + } + + hwirq = RV_IRQ_SOFT; + } +#endif /* RT_USING_SMP */ + +#if BITS_PER_LONG == 32 + if (hwirq >= BITS_PER_LONG) + { + csr_clear(CSR_IEH, BIT(hwirq - BITS_PER_LONG)); + } + else +#endif /* BITS_PER_LONG == 32 */ + { + csr_clear(CSR_IE, BIT(hwirq)); + } +} + +rt_inline void riscv_intc_irq_unmask_raw(struct riscv_intc *rv_intc, int hwirq) +{ +#ifdef RT_USING_SMP + if (hwirq >= rv_intc->ipi_base) + { + rt_atomic_t *ipi_enable = &rv_intc->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_or(ipi_enable, BIT(hwirq - rv_intc->ipi_base)); + hwirq = RV_IRQ_SOFT; + } +#endif /* RT_USING_SMP */ + +#if BITS_PER_LONG == 32 + if (hwirq >= BITS_PER_LONG) + { + csr_set(CSR_IEH, BIT(hwirq - BITS_PER_LONG)); + } + else +#endif /* BITS_PER_LONG == 32 */ + { + csr_set(CSR_IE, BIT(hwirq)); + } +} + +rt_inline void andes_intc_irq_mask_raw(struct riscv_intc *rv_intc, int hwirq) +{ + /* + * Andes specific S-mode local interrupt causes (hwirq) + * are defined as (256 + n) and controlled by n-th bit of SLIE. + */ + rt_uint32_t mask; + +#ifdef RT_USING_SMP + if (hwirq >= rv_intc->ipi_base) + { + rt_atomic_t *ipi_enable = &rv_intc->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_and(ipi_enable, ~BIT(hwirq - rv_intc->ipi_base)); + + if (rt_atomic_load(ipi_enable) != 0) + { + return; + } + + hwirq = RV_IRQ_SOFT; + } +#endif /* RT_USING_SMP */ + + mask = BIT(hwirq % BITS_PER_LONG); + + if (hwirq < ANDES_SLI_CAUSE_BASE) + { + csr_clear(CSR_IE, mask); + } + else + { + csr_clear(ANDES_CSR_SLIE, mask); + } +} + +rt_inline void andes_intc_irq_unmask_raw(struct riscv_intc *rv_intc, int hwirq) +{ + rt_uint32_t mask; + +#ifdef RT_USING_SMP + if (hwirq >= rv_intc->ipi_base) + { + rt_atomic_t *ipi_enable = &rv_intc->ipi_enable[rt_hw_cpu_id()]; + + rt_atomic_or(ipi_enable, BIT(hwirq - rv_intc->ipi_base)); + hwirq = RV_IRQ_SOFT; + } +#endif /* RT_USING_SMP */ + + mask = BIT(hwirq % BITS_PER_LONG); + + if (hwirq < ANDES_SLI_CAUSE_BASE) + { + csr_set(CSR_IE, mask); + } + else + { + csr_set(ANDES_CSR_SLIE, mask); + } +} + +rt_inline void riscv_intc_irq_send_ipi_raw(struct riscv_intc *rv_intc, int ipi, rt_bitmap_t *cpumask) +{ + int cpu; + +#if defined(RT_USING_SMP) || defined(ARCH_RISCV_M_MODE) + rt_bitmap_for_each_set_bit(cpumask, cpu, RT_CPUS_NR) + { + #ifdef RT_USING_SMP + rt_atomic_or(&rv_intc->ipi_pending[cpu], BIT(ipi)); + #endif + + #ifndef ARCH_RISCV_M_MODE + if (riscv_aclint_ipi_base) + #endif + { + clint_send_ipi(cpu); + } + } +#endif /* RT_USING_SMP || ARCH_RISCV_M_MODE */ + +#ifndef ARCH_RISCV_M_MODE + if (!riscv_aclint_ipi_base) + { + sbi_send_ipi((const unsigned long *)cpumask); + } +#endif /* !ARCH_RISCV_M_MODE */ +} + +rt_inline rt_bool_t riscv_intc_common_handler_raw(struct riscv_intc *rv_intc, int hwirq, + rt_bool_t (*callback)(int hwirq, void *data), void *data) +{ +#ifdef RT_USING_SMP + if (hwirq != RV_IRQ_SOFT) +#endif + { + if (hwirq != RV_IRQ_TIMER) + { + return callback(hwirq, data); + } + else + { + riscv_timer_isr(); + return RT_TRUE; + } + } +#ifdef RT_USING_SMP + else + { + int ipi; + rt_bool_t res; + rt_bitmap_t pending; + + #ifndef ARCH_RISCV_M_MODE + if (riscv_aclint_ipi_base) + #endif + { + clint_clear_ipi(); + } + #ifndef ARCH_RISCV_M_MODE + else + { + csr_clear(CSR_IP, IE_SIE); + } + #endif + + pending = rt_atomic_exchange(&rv_intc->ipi_pending[rt_hw_cpu_id()], 0); + + rt_bitmap_for_each_set_bit(&pending, ipi, RT_MAX_IPI) + { + res = callback(rv_intc->ipi_base + ipi, data); + } + + return res; + } +#endif /* RT_USING_SMP */ +} + +rt_inline rt_bool_t riscv_intc_handler_raw(struct riscv_intc *rv_intc, rt_ubase_t scause, + rt_bool_t (*callback)(int hwirq, void *data), void *data) +{ + return riscv_intc_common_handler_raw(rv_intc, scause & ~CAUSE_IRQ_FLAG, callback, data); +} + +rt_inline rt_bool_t riscv_intc_aia_handler_raw(struct riscv_intc *rv_intc, + rt_bool_t (*callback)(int hwirq, void *data), void *data) +{ + rt_ubase_t topi; + rt_bool_t res = RT_FALSE; + + while ((topi = csr_read(CSR_TOPI) >> TOPI_IID_SHIFT)) + { + res = riscv_intc_common_handler_raw(rv_intc, topi, callback, data); + } + + return res; +} + +static void riscv_intc_common_init(struct riscv_intc *rv_intc, rt_bool_t is_andes) +{ + rt_memset(rv_intc, 0, sizeof(*rv_intc)); + rv_intc->irqs_def_count = RT_BITS_PER_LONG; + + if (is_andes) + { + rv_intc->irqs_base = ANDES_SLI_CAUSE_BASE; + rv_intc->irqs_count = ANDES_RV_IRQ_LAST; + } + else + { + rv_intc->irqs_base = BITS_PER_LONG; + rv_intc->irqs_count = 0; + } + + if (riscv_isa_ext_test(SxAIA)) + { + rv_intc->irqs_def_count = 64; + } + else + { + rv_intc->irqs_def_count = IRQ_LOCAL_MAX; + } + +#ifdef RT_USING_SMP + rv_intc->irqs_def_count += RT_MAX_IPI; +#endif +} + +#ifndef PIC_DISABLE_DM +static void riscv_intc_irq_mask(struct rt_pic_irq *pirq) +{ + RT_IRQ_AFFINITY_CLEAR(pirq->affinity, rt_hw_cpu_id()); + riscv_intc_irq_mask_raw(pirq->pic->priv_data, pirq->hwirq); +} + +static void riscv_intc_irq_unmask(struct rt_pic_irq *pirq) +{ + RT_IRQ_AFFINITY_SET(pirq->affinity, rt_hw_cpu_id()); + riscv_intc_irq_unmask_raw(pirq->pic->priv_data, pirq->hwirq); +} + +static void andes_intc_irq_mask(struct rt_pic_irq *pirq) +{ + andes_intc_irq_mask_raw(pirq->pic->priv_data, pirq->hwirq); + RT_IRQ_AFFINITY_CLEAR(pirq->affinity, rt_hw_cpu_id()); +} + +static void andes_intc_irq_unmask(struct rt_pic_irq *pirq) +{ + RT_IRQ_AFFINITY_SET(pirq->affinity, rt_hw_cpu_id()); + andes_intc_irq_unmask_raw(pirq->pic->priv_data, pirq->hwirq); +} + +static void riscv_intc_irq_send_ipi(struct rt_pic_irq *pirq, rt_bitmap_t *cpumask) +{ + struct riscv_intc *rv_intc = pirq->pic->priv_data; + + riscv_intc_irq_send_ipi_raw(rv_intc, pirq->hwirq, cpumask); +} + +static int riscv_intc_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + int irq, irq_index = -1; + struct riscv_intc *rv_intc = rt_container_of(pic, struct riscv_intc, parent); + + if (hwirq >= rv_intc->irqs_def_count && + (hwirq < rv_intc->irqs_base || hwirq >= rv_intc->irqs_base + rv_intc->irqs_count)) + { + return -RT_EINVAL; + } + + if (hwirq < rv_intc->irqs_def_count) + { + irq_index = hwirq; + } + else if (hwirq >= rv_intc->irqs_base && + hwirq < rv_intc->irqs_base + rv_intc->irqs_count) + { + irq_index = rv_intc->irqs_def_count + hwirq - rv_intc->irqs_base; + } + + if (irq_index >= 0) + { + irq = rt_pic_config_irq(pic, hwirq, irq_index); + } + else + { + irq = -1; + } + + return irq; +} + +static rt_err_t riscv_intc_irq_parse(struct rt_pic *pic, + struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + rt_err_t err = RT_EOK; + + if (args->args_count == 1) + { + out_pirq->hwirq = args->args[0]; + out_pirq->mode = RT_IRQ_MODE_EDGE_RISING; + } + else + { + err = -RT_EINVAL; + } + + return err; +} + +const static struct rt_pic_ops riscv_intc_ops = +{ + .name = "RISC-V-INTC", + .irq_mask = riscv_intc_irq_mask, + .irq_unmask = riscv_intc_irq_unmask, + .irq_send_ipi = riscv_intc_irq_send_ipi, + .irq_map = riscv_intc_irq_map, + .irq_parse = riscv_intc_irq_parse, +}; + +const static struct rt_pic_ops andes_intc_ops = +{ + .name = "ANDES-INTC", + .irq_mask = andes_intc_irq_mask, + .irq_unmask = andes_intc_irq_unmask, + .irq_send_ipi = riscv_intc_irq_send_ipi, + .irq_map = riscv_intc_irq_map, + .irq_parse = riscv_intc_irq_parse, +}; + +static rt_bool_t riscv_intc_common_handler_isr(int hwirq, void *data) +{ + struct rt_pic_irq *pirq; + struct riscv_intc *rv_intc = data; + +#ifdef RT_USING_SMP + if (hwirq < rv_intc->ipi_base) +#endif + { + pirq = rt_pic_find_irq(&rv_intc->parent, hwirq); + } +#ifdef RT_USING_SMP + else + { + pirq = rt_pic_find_ipi(&rv_intc->parent, hwirq - rv_intc->ipi_base); + } +#endif + + return rt_pic_handle_isr(pirq) == RT_EOK; +} + +static rt_bool_t riscv_intc_handler(void *data) +{ + rt_ubase_t cause; + struct riscv_intc *rv_intc = data; + + cause = csr_read(CSR_CAUSE); + + return riscv_intc_handler_raw(rv_intc, cause, riscv_intc_common_handler_isr, data); +} + +static rt_bool_t riscv_intc_aia_handler(void *data) +{ + struct riscv_intc *rv_intc = data; + + return riscv_intc_aia_handler_raw(rv_intc, riscv_intc_common_handler_isr, data); +} + +static rt_err_t riscv_intc_ofw_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id) +{ + const struct rt_pic_ops *ops; + struct riscv_intc *rv_intc = &system_rv_intc; + struct rt_ofw_node *pnp = rt_ofw_get_parent(np); + + /* Only boot CPU to init */ + if (rt_ofw_get_cpu_hwid(pnp, 0) != boot_cpu_hartid) + { + rt_ofw_node_put(pnp); + rt_ofw_data(np) = &rv_intc->parent; + + return RT_EOK; + } + rt_ofw_node_put(pnp); + + ops = id->data; + riscv_intc_common_init(rv_intc, ops == &andes_intc_ops); + + riscv_clint_ofw_init(); + + if (riscv_isa_ext_test(SxAIA)) + { + rt_pic_add_traps(riscv_intc_aia_handler, rv_intc); + } + else + { + rt_pic_add_traps(riscv_intc_handler, rv_intc); + } + + rv_intc->parent.priv_data = rv_intc; + rv_intc->parent.ops = ops; + rt_ofw_data(np) = &rv_intc->parent; + + rt_pic_linear_irq(&rv_intc->parent, rv_intc->irqs_def_count + rv_intc->irqs_count); + +#ifdef RT_USING_SMP + rv_intc->ipi_base = rv_intc->parent.irq_nr - RT_MAX_IPI; + + for (int ipi = 0; ipi < RT_MAX_IPI; ++ipi) + { + rt_pic_config_ipi(&rv_intc->parent, ipi, rv_intc->ipi_base + ipi); + } +#endif /* RT_USING_SMP */ + + rt_pic_user_extends(&rv_intc->parent); + + return RT_EOK; +} + +static const struct rt_ofw_node_id riscv_intc_ofw_ids[] = +{ + { .compatible = "riscv,cpu-intc", (void *)&riscv_intc_ops }, + { .compatible = "andestech,cpu-intc", (void *)&andes_intc_ops }, + { /* sentinel */ } +}; +RT_PIC_OFW_DECLARE(riscv_intc, riscv_intc_ofw_ids, riscv_intc_ofw_init); +#endif /* !PIC_DISABLE_DM */ diff --git a/libcpu/risc-v/common/pic/pic-sifive-plic.c b/libcpu/risc-v/common/pic/pic-sifive-plic.c new file mode 100644 index 00000000000..bdc37461527 --- /dev/null +++ b/libcpu/risc-v/common/pic/pic-sifive-plic.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include +#include +#include + +#define DBG_TAG "pic.plic" +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include +#include +#include + +/* + * This driver implements a version of the RISC-V PLIC with the actual layout + * specified in chapter 8 of the SiFive U5 Coreplex Series Manual: + * + * https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf + */ + +#define MAX_DEVICES 1024 +#define MAX_CONTEXTS 15872 + +/* + * Each interrupt source has a priority register associated with it. + * We always hardwire it to one in Linux. + */ +#define PRIORITY_BASE 0 +#define PRIORITY_PER_ID 4 + +#ifdef ARCH_RISCV_M_MODE +#define CONTEXT_ENABLE_MODE_OFFSET 0 +#define CONTEXT_BASE_MODE_OFFSET 0 +#else +#define CONTEXT_ENABLE_MODE_OFFSET 0x80 +#define CONTEXT_BASE_MODE_OFFSET 0x1000 +#endif + +/* + * Each hart context has a vector of interrupt enable bits associated with it. + * There's one bit for each interrupt source. + */ +#define CONTEXT_ENABLE_BASE (0x2000 + CONTEXT_ENABLE_MODE_OFFSET) +#define CONTEXT_ENABLE_SIZE(hartid) ((2 * hartid) * 0x80) + +/* + * Each hart context has a set of control registers associated with it. Right + * now there's only two: a source priority threshold over which the hart will + * take an interrupt, and a register to claim interrupts. + */ +#define CONTEXT_BASE (0x200000 + CONTEXT_BASE_MODE_OFFSET) +#define CONTEXT_SIZE(hartid) ((2 * hartid) * 0x1000) +#define CONTEXT_THRESHOLD 0x00 +#define CONTEXT_CLAIM 0x04 + +#define PLIC_DISABLE_THRESHOLD 0x7 +#define PLIC_ENABLE_THRESHOLD 0 + +#define PLIC_HWIRQ_START 1 + +#define PLIC_QUIRK_EDGE_INTERRUPT 0 + +struct plic +{ +#ifndef PIC_DISABLE_DM + struct rt_pic parent; + struct rt_ofw_node *np; + + int parent_irq; +#endif + + void *regs; + + rt_bitmap_t quirks; + + rt_uint32_t irqs_count; +}; + +struct plic_percpu +{ + void *hart_base; + void *enable_base; + + struct rt_spinlock enable_lock; +}; + +static struct plic_percpu plic_percpu[RT_CPUS_NR] rt_align(L1_CACHE_BYTES); + +static void plic_set_threshold(struct plic_percpu *percpu, rt_uint32_t threshold) +{ + /* Priority must be > threshold to trigger an interrupt */ + HWREG32(percpu->hart_base + CONTEXT_THRESHOLD) = threshold; +} + +static void plic_toggle(struct plic_percpu *percpu, int hwirq, rt_bool_t enable) +{ + rt_ubase_t level; + rt_uint32_t *reg, hwirq_mask; + + level = rt_spin_lock_irqsave(&percpu->enable_lock); + + reg = percpu->enable_base + (hwirq / 32) * sizeof(rt_uint32_t); + hwirq_mask = 1 << (hwirq % 32); + + if (enable) + { + HWREG32(reg) |= hwirq_mask; + } + else + { + HWREG32(reg) &= ~hwirq_mask; + } + + rt_spin_unlock_irqrestore(&percpu->enable_lock, level); +} + +static void plic_irq_unmask_raw(int cpu, int hwirq) +{ + struct plic_percpu *percpu = &plic_percpu[cpu]; + + plic_toggle(percpu, hwirq, RT_TRUE); +} + +static void plic_irq_mask_raw(int cpu, int hwirq) +{ + struct plic_percpu *percpu = &plic_percpu[cpu]; + + plic_toggle(percpu, hwirq, RT_FALSE); +} + +static void plic_irq_ack_or_eoi(int cpu, int hwirq) +{ + struct plic_percpu *percpu = &plic_percpu[cpu]; + + HWREG32(percpu->hart_base + CONTEXT_CLAIM) = hwirq; +} + +static rt_bool_t plic_handler_isr_raw(struct plic *plic, + rt_bool_t (*callback)(int hwirq, void *data), void *data) +{ + int hwirq; + void *claim; + rt_bool_t res = RT_FALSE; + struct plic_percpu *percpu = &plic_percpu[rt_hw_cpu_id()]; + + claim = percpu->hart_base + CONTEXT_CLAIM; + + while ((hwirq = HWREG32(claim))) + { + res = callback(hwirq, data); + } + + return res; +} + +static void plic_percpu_common_init(struct plic *plic) +{ + struct plic_percpu *percpu = &plic_percpu[rt_hw_cpu_id()]; + + plic_set_threshold(percpu, PLIC_ENABLE_THRESHOLD); +} + +static struct plic *plic_common_init(rt_ubase_t plic_base, rt_size_t plic_size, + rt_size_t ndev, rt_bitmap_t quirks) +{ + struct plic *plic = rt_calloc(1, sizeof(*plic)); + + if (!plic) + { + rt_set_errno(-RT_ENOMEM); + return RT_NULL; + } + + plic->regs = rt_ioremap((void *)plic_base, plic_size); + + if (!plic->regs) + { + rt_set_errno(-RT_EIO); + + rt_free(plic); + return RT_NULL; + } + + plic->quirks = quirks; + plic->irqs_count = ndev; + + for (int cpu = 0, hartid; cpu < RT_CPUS_NR; ++cpu) + { + struct plic_percpu *percpu = &plic_percpu[cpu]; + + #ifndef RT_USING_SMP + hartid = boot_cpu_hartid; + #else + hartid = riscv_cpu_id_to_hartid(cpu); + #endif + + percpu->hart_base = plic->regs + CONTEXT_BASE + CONTEXT_SIZE(hartid); + percpu->enable_base = plic->regs + CONTEXT_ENABLE_BASE + CONTEXT_ENABLE_SIZE(hartid); + + rt_spin_lock_init(&percpu->enable_lock); + } + + /* Set default priority */ + for (int hwirq = PLIC_HWIRQ_START; hwirq <= plic->irqs_count; ++hwirq) + { + HWREG32(plic->regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID) = PLIC_ENABLE_THRESHOLD + 1; + } + + return plic; +} + +#ifndef PIC_DISABLE_DM +static void plic_handler(int hwirq, void *data); + +static rt_err_t plic_irq_init(struct rt_pic *pic) +{ + struct plic *plic = pic->priv_data; + + if (plic->parent_irq < 0) + { + struct rt_ofw_cell_args irq_args; + + if (rt_ofw_parse_irq_cells(plic->np, 0, &irq_args)) + { + LOG_E("%s: Parent IRQ is not available", rt_ofw_node_full_name(plic->np)); + goto _percpu_init; + } + + /* Create mapping */ + irq_args.args[0] = RV_IRQ_EXT; + + plic->parent_irq = rt_ofw_map_irq(&irq_args); + rt_hw_interrupt_install(plic->parent_irq, plic_handler, plic, "PLIC"); + } + + rt_hw_interrupt_umask(plic->parent_irq); + +_percpu_init: + plic_percpu_common_init(plic); + + return RT_EOK; +} + +static void plic_irq_ack(struct rt_pic_irq *pirq) +{ + if (pirq->mode == RT_IRQ_MODE_EDGE_RISING) + { + plic_irq_ack_or_eoi(rt_hw_cpu_id(), pirq->hwirq); + } +} + +static void plic_irq_unmask(struct rt_pic_irq *pirq) +{ + int cpu, count = 0; + + rt_bitmap_for_each_set_bit(pirq->affinity, cpu, RT_CPUS_NR) + { + plic_irq_unmask_raw(cpu, pirq->hwirq); + ++count; + } + + if (!count) + { + int boot_cpu_id = riscv_hartid_to_cpu_id(boot_cpu_hartid); + + RT_IRQ_AFFINITY_SET(pirq->affinity, boot_cpu_id); + plic_irq_unmask_raw(boot_cpu_id, pirq->hwirq); + } +} + +static void plic_irq_mask(struct rt_pic_irq *pirq) +{ + int cpu; + + rt_bitmap_for_each_set_bit(pirq->affinity, cpu, RT_CPUS_NR) + { + plic_irq_mask_raw(cpu, pirq->hwirq); + } +} + +static void plic_irq_eoi(struct rt_pic_irq *pirq) +{ + if (pirq->mode == RT_IRQ_MODE_LEVEL_HIGH) + { + plic_irq_ack_or_eoi(rt_hw_cpu_id(), pirq->hwirq); + } +} + +static rt_err_t plic_irq_set_priority(struct rt_pic_irq *pirq, rt_uint32_t priority) +{ + struct plic *plic = pirq->pic->priv_data; + + priority = rt_min_t(rt_uint32_t, priority, PLIC_DISABLE_THRESHOLD); + + HWREG32(plic->regs + PRIORITY_BASE + pirq->hwirq * PRIORITY_PER_ID) = priority; + + return RT_EOK; +} + +static rt_err_t plic_irq_set_affinity(struct rt_pic_irq *pirq, rt_bitmap_t *affinity) +{ + int cpu; + + rt_bitmap_for_each_clear_bit(affinity, cpu, RT_CPUS_NR) + { + plic_toggle(&plic_percpu[cpu], pirq->hwirq, RT_FALSE); + } + + rt_bitmap_for_each_set_bit(affinity, cpu, RT_CPUS_NR) + { + plic_toggle(&plic_percpu[cpu], pirq->hwirq, RT_TRUE); + } + + return RT_EOK; +} + +static rt_err_t plic_irq_set_triger_mode(struct rt_pic_irq *pirq, rt_uint32_t mode) +{ + struct plic *plic = pirq->pic->priv_data; + + if (rt_bitmap_test_bit(&plic->quirks, PLIC_QUIRK_EDGE_INTERRUPT)) + { + return -RT_ENOSYS; + } + + if (mode == RT_IRQ_MODE_EDGE_RISING || mode == RT_IRQ_MODE_LEVEL_HIGH) + { + return RT_EOK; + } + + return -RT_ENOSYS; +} + +static int plic_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode) +{ + struct rt_pic_irq *pirq = rt_pic_find_irq(pic, hwirq - PLIC_HWIRQ_START); + + pirq->mode = mode; + + return rt_pic_config_irq(pic, hwirq - PLIC_HWIRQ_START, hwirq); +} + +static rt_err_t plic_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq) +{ + struct plic *plic = pic->priv_data; + + out_pirq->hwirq = args->args[0]; + + if (rt_bitmap_test_bit(&plic->quirks, PLIC_QUIRK_EDGE_INTERRUPT)) + { + out_pirq->mode = args->args[1]; + } + else + { + out_pirq->mode = RT_IRQ_MODE_LEVEL_HIGH; + } + + return RT_EOK; +} + +const static struct rt_pic_ops plic_ops = +{ + .name = "SiFive-PLIC", + .irq_init = plic_irq_init, + .irq_ack = plic_irq_ack, + .irq_mask = plic_irq_mask, + .irq_unmask = plic_irq_unmask, + .irq_eoi = plic_irq_eoi, + .irq_set_priority = plic_irq_set_priority, + .irq_set_affinity = plic_irq_set_affinity, + .irq_set_triger_mode = plic_irq_set_triger_mode, + .irq_map = plic_irq_map, + .irq_parse = plic_irq_parse, +}; + +static rt_bool_t plic_common_handler_isr(int hwirq, void *data) +{ + rt_bool_t res; + struct plic *plic = data; + struct rt_pic_irq *pirq = rt_pic_find_irq(&plic->parent, hwirq - PLIC_HWIRQ_START); + + plic_irq_ack(pirq); + + res = rt_pic_handle_isr(pirq); + + plic_irq_eoi(pirq); + + return res; +} + +static void plic_handler(int hwirq, void *data) +{ + struct plic *plic = data; + + plic_handler_isr_raw(plic, plic_common_handler_isr, plic); +} + +static rt_err_t plic_ofw_init(struct rt_ofw_node *np, const struct rt_ofw_node_id *id) +{ + rt_err_t err; + rt_uint32_t irqs_count; + rt_uint64_t plic_base, plic_size; + rt_bitmap_t quirks; + struct plic *plic; + + if ((err = rt_ofw_get_address(np, 0, &plic_base, &plic_size))) + { + return err; + } + + if ((err = rt_ofw_prop_read_u32(np, "riscv,ndev", &irqs_count))) + { + return err; + } + + quirks = id->data ? *(rt_ubase_t *)id->data : 0; + + if (!(plic = plic_common_init(plic_base, plic_size, irqs_count, quirks))) + { + return rt_get_errno(); + } + + plic->np = np; + plic->parent_irq = -1; + + plic->parent.priv_data = plic; + plic->parent.ops = &plic_ops; + rt_ofw_data(np) = &plic->parent; + + rt_pic_linear_irq(&plic->parent, plic->irqs_count); + + rt_pic_user_extends(&plic->parent); + + return RT_EOK; +} + +static rt_bitmap_t andestech_nceplic100_quirk_edge = RT_BIT(PLIC_QUIRK_EDGE_INTERRUPT); +static rt_bitmap_t thead_c900_quirk_edge = RT_BIT(PLIC_QUIRK_EDGE_INTERRUPT); + +static const struct rt_ofw_node_id plic_ofw_ids[] = +{ + { .compatible = "sifive,plic-1.0.0" }, + { .compatible = "riscv,plic0" }, + { .compatible = "andestech,nceplic100", .data = &andestech_nceplic100_quirk_edge }, + { .compatible = "thead,c900-plic", .data = &thead_c900_quirk_edge }, + { /* sentinel */ } +}; +RT_PIC_OFW_DECLARE(plic, plic_ofw_ids, plic_ofw_init); +#endif /* PIC_DISABLE_DM */ diff --git a/libcpu/risc-v/common/readme.md b/libcpu/risc-v/common/readme.md deleted file mode 100644 index 42be5a20253..00000000000 --- a/libcpu/risc-v/common/readme.md +++ /dev/null @@ -1,187 +0,0 @@ -### RV32移植指南 - -#### 1.概述 - -为了简化32位RISC-V架构内核移植RT-Thread的流程,RT-Thread提供一分通用代码于common文件夹 - -| 文件名 | 文件内容 | -| :-----------------: | :----------------------------: | -| context_gcc.S | 开关全局中断,线程上下文切换等 | -| cpuport.c | 线程栈初始化,软件中断触发等 | -| cpuport.h | 数据加载写入指令 | -| interrupt_gcc.S | 线程间上下文切换 | -| riscv-ops.h | 控制状态寄存器读写 | -| rt_hw_stack_frame.h | 线程栈格式 | -| trap_common.c | 中断注册,中断查询分发 | - -#### 2.移植接口 - -(1)软件中断触发函数,通常向量管理中断方式需实现该函数,非向量中断管理方式一般不需要 - -```c -void rt_trigger_software_interrupt(void) -``` - -(2)保存上文后执行函数,该函数向量中断与非向量中断均需实现 - -```c -void rt_hw_do_after_save_above(void) -``` - -该函数需要实现的工作如下: - -步骤1:将函数返回地址(ra)保存栈中 - -步骤2:加载中断处理函数的入口参数 - -步骤3:调用中断处理函数(新移植的BSP推荐使用RT-Thread common_trap.c文件中提供的统一中断处理函数:rt_rv32_system_irq_handler) - -步骤4:从栈中加载返回地址(ra),返回至SW_handler函数 - -#### 3.准备工作 - -- 准备一个基础的裸机工程,需具备以下条件: - - - 明确中断管理方式(向量中断/非向量中断) - - - 实现系统节拍定时器中断 - - 实现一个串口中断 - -#### 4.移植步骤 - -- 步骤一:配置中断管理入口,相关中断入口函数位于**common/interrupt_gcc.S**,入口函数为**SW_handler** - - - 根据使用的中断管理方式,执行下述操作 - - - 向量中断管理方式 - - > 通常会使用一个软件中断(该中断的优先级被配置为最低)作为在中断中触发上下文切换的入口函数。SW_handler在此仅作为触发软件中断时的入口参数,其他类型中断触发时跳转至各自的中断入口函数。 - > - - 移植方法:修改原有的中断向量表中软件中断所在位置,将原有软件中断函数名修改为**SW_handler** - - 示例(ch32系列): - - ```assembly - _vector_base: - .option norvc; - .word _start - ... - .word SW_handler /* 将这里原来放置的软件中断函数名修改为SW_handler */ - ``` - - - 非向量中断 - - > 当有中断触发时,会进入一个统一的中断入口函数进行中断查询分发。SW_handler在此处不仅作为作为在中断中触发上下文切换的入口函数,同时承担中断查询分发与执行。 - > - - 移植方法:将**SW_handler**的地址加载到保存统一中断入口地址的寄存器(通常为mtevc,具体名称需要根据具体的内核指定) - - 示例(hpm6750系列): - - ```assembly - la t0, SW_handler - csrw mtvec, t0 - ``` - -- 步骤二:修改链接脚本,在中断栈顶名称后添加示例代码 - - - 将下述代码放置于链接脚本中中断栈顶名称之后 - - ```assembly - PROVIDE( __rt_rvstack = . ); - ``` - - - 示例(core-v-mcu链接脚本): - - ```assembly - .stack : ALIGN(16) - { - stack_start = .; - __stack_bottom = .; - . += __stack_size; - __stack_top = .; - PROVIDE( __rt_rvstack = . );//移植时添加 - stack = .; - } > L2 - ``` - -> __stack_top为core-v-mcu工程的中断栈顶名 不同工程此处的名称可能不一致 按上述方法将给出的代码放到具体工程链接脚本中断栈顶名称之后即可。 - -- 步骤三:实现在中断上下文切换的函数接口 - - RISC-V架构的内核通常采用非向量中断的管理方式,为了进一步降低难度,针对非向量模式的中断管理方式,common文件夹中的trap_common.c为用户提供了一套统一的中断查询分发、中断入口函数注册以及中断初始化函数,在rthw.h中声明,对于移植一个新的RV32内核,若采用非向量中断管理的方式,推荐使用方式一,若采用向量中断管理方式或针对中断的处理有专门的优化时推荐使用方式二,期望采用原有裸机工程的统一的中断查询与处理函数也可使用方式二。以下是两种实现方式的示例: - - 方式一:面向非向量中断管理方式(例:core-v-mcu) - - 在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,该函数的实现如下(用户直接使用,无需修改): - - ```assembly - #include "cpuport.h" - - .globl rt_hw_do_after_save_above - .type rt_hw_do_after_save_above,@function - rt_hw_do_after_save_above: - addi sp, sp, -4 - STORE ra, 0 * REGBYTES(sp) - - csrr a0, mcause - csrr a1, mepc - mv a2, sp - call rt_rv32_system_irq_handler - - LOAD ra, 0 * REGBYTES(sp) - addi sp, sp, 4 - ret - ``` - - 随后用户仅需调用rt_hw_interrupt_init进行初始化,再将中断入口函数通过rt_hw_interrupt_install函数注册即可,注册的中断入口函数为裸机原有的中断入口函数,示例代码如下(相关设备的中断入口函数注册之前不可使用该设备): - - ```c - rt_hw_interrupt_init();//中断入口函数初始化 - rt_hw_interrupt_install(0x7, timer_irq_handler, RT_NULL, "timerirq");//注册系统定时器中断入口函数 - rt_hw_interrupt_install(0xb, fc_soc_event_handler1, RT_NULL, "eventirq");//注册外部中断入口函数 - ``` - - 方式二:面向向量中断管理方式(例:CH32)与针对中断管理有专门优化的内核(例:GD32) - - - 向量中断(可参考ch32) - - 在RT-Thread的BSP框架中的board文件夹创建需要的文件,实现下述的两个函数: - - - 在void rt_trigger_software_interrupt(void) 中实现触发软件中断的操作 - - - 在void rt_hw_do_after_save_above(void) 中实现触发软件中断之后的工作,通常是清除软件中断置位标志位或类似操作 - - - 非向量中断(期望采用原有裸机工程的统一的中断查询与处理函数) - - 在RT-Thread的BSP框架中的board文件夹创建一个统一名称的汇编文件:trap_gcc.S,将该文件添加到编译环境即可,此步骤与方式一提供的方法相似,仅在调用中断处理函数以及传递的参数不同,需要根据具体的移植工程实现,方式二下该函数的实现如下: - - 示例代码: - - ```assembly - #include "cpuport.h" - - .globl rt_hw_do_after_save_above - .type rt_hw_do_after_save_above,@function - rt_hw_do_after_save_above: - addi sp, sp, -4 // 移动栈指针 - STORE ra, 0 * REGBYTES(sp) // 将返回地址寄存器值保存至栈中 - - csrr a0, mscratch// 加载函数入口参数 - call trap_entry// 调用中断处理函数 - - LOAD ra, 0 * REGBYTES(sp) // 从栈中恢复返回地址寄存器值 - addi sp, sp, 4// 移动栈指针 - ret // 返回SW_handler - ``` - - trap_entry为用户实现的中断源查询分发的函数,在移植时仅需要将该函数名修改为用户的中断查询分发函数即可。 - - - -#### 5.验证 - -- 创建一个静态线程,在线程中调用RT-Thread提供的与系统时基相关函数接口,例如rt_thread_mdelay,调试观察系统是否可以正常运行 -- 移植RT-Thread的shell进一步验证系统是否移植成功 - diff --git a/libcpu/risc-v/common/riscv-ops.h b/libcpu/risc-v/common/riscv-ops.h deleted file mode 100644 index 35d009ad538..00000000000 --- a/libcpu/risc-v/common/riscv-ops.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-03 Bernard The first version - */ - -#ifndef RISCV_OPS_H__ -#define RISCV_OPS_H__ - -#if defined(__GNUC__) && !defined(__ASSEMBLER__) - -#define read_csr(reg) ({ unsigned long __tmp; \ - asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ - __tmp; }) - -#define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) - -#define set_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) - -#define clear_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) -#endif /* end of __GNUC__ */ - -#endif diff --git a/libcpu/risc-v/common/riscv-plic.h b/libcpu/risc-v/common/riscv-plic.h deleted file mode 100644 index 53e19d29628..00000000000 --- a/libcpu/risc-v/common/riscv-plic.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-03 Bernard The first version - */ - -#ifndef RISCV_PLIC_H__ -#define RISCV_PLIC_H__ - -#ifndef PLIC_BASE_ADDR -#define PLIC_BASE_ADDR 0x0 -#endif - -/* Priority Register - 32 bits per source */ -#define PLIC_PRIORITY_OFFSET (0x00000000UL) -#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2 - -/* Pending Register - 1 bit per soirce */ -#define PLIC_PENDING_OFFSET (0x00001000UL) -#define PLIC_PENDING_SHIFT_PER_SOURCE 0 - -/* Enable Register - 0x80 per target */ -#define PLIC_ENABLE_OFFSET (0x00002000UL) -#define PLIC_ENABLE_SHIFT_PER_TARGET 7 - -/* Priority Threshold Register - 0x1000 per target */ -#define PLIC_THRESHOLD_OFFSET (0x00200000UL) -#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12 - -/* Claim Register - 0x1000 per target */ -#define PLIC_CLAIM_OFFSET (0x00200004UL) -#define PLIC_CLAIM_SHIFT_PER_TARGET 12 - -#if defined(__GNUC__) && !defined(__ASSEMBLER__) -__attribute__((always_inline)) static inline void __plic_set_feature(unsigned int feature) -{ - volatile unsigned int *feature_ptr = (volatile unsigned int *)PLIC_BASE_ADDR; - *feature_ptr = feature; -} - -__attribute__((always_inline)) static inline void __plic_set_threshold(unsigned int threshold) -{ - unsigned int hart_id = read_csr(mhartid); - volatile unsigned int *threshold_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_THRESHOLD_OFFSET + - (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET)); - *threshold_ptr = threshold; -} - -__attribute__((always_inline)) static inline void __plic_set_priority(unsigned int source, unsigned int priority) -{ - volatile unsigned int *priority_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_PRIORITY_OFFSET + - (source << PLIC_PRIORITY_SHIFT_PER_SOURCE)); - *priority_ptr = priority; -} - -__attribute__((always_inline)) static inline void __plic_set_pending(unsigned int source) -{ - volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_PENDING_OFFSET + - ((source >> 5) << 2)); - *current_ptr = (1 << (source & 0x1F)); -} - -__attribute__((always_inline)) static inline void __plic_irq_enable(unsigned int source) -{ - unsigned int hart_id = read_csr(mhartid); - volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_ENABLE_OFFSET + - (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) + - ((source >> 5) << 2)); - unsigned int current = *current_ptr; - current = current | (1 << (source & 0x1F)); - *current_ptr = current; -} - -__attribute__((always_inline)) static inline void __plic_irq_disable(unsigned int source) -{ - unsigned int hart_id = read_csr(mhartid); - volatile unsigned int *current_ptr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_ENABLE_OFFSET + - (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) + - ((source >> 5) << 2)); - unsigned int current = *current_ptr; - current = current & ~((1 << (source & 0x1F))); - *current_ptr = current; -} - -__attribute__((always_inline)) static inline unsigned int __plic_irq_claim(void) -{ - unsigned int hart_id = read_csr(mhartid); - volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_CLAIM_OFFSET + - (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET)); - return *claim_addr; -} - -__attribute__((always_inline)) static inline void __plic_irq_complete(unsigned int source) -{ - unsigned int hart_id = read_csr(mhartid); - volatile unsigned int *claim_addr = (volatile unsigned int *)(PLIC_BASE_ADDR + - PLIC_CLAIM_OFFSET + - (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET)); - *claim_addr = source; -} -#endif /* end of __GNUC__ */ - -#endif diff --git a/libcpu/risc-v/common/riscv_timer.c b/libcpu/risc-v/common/riscv_timer.c new file mode 100755 index 00000000000..77f9b78d4a2 --- /dev/null +++ b/libcpu/risc-v/common/riscv_timer.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-28 Bernard The unify RISC-V porting code. + * 2024-07-08 Shell Using CPUTIME as tick + * 2025-04-20 GuEe-GUI Port to the DM + */ + +#include + +#include +#include +#include +#ifdef RT_USING_KTIME +#include +#endif +#include +#include +#include + +static rt_uint32_t timebase_frequency; +static volatile rt_ubase_t tick_cycles; + +static rt_bool_t riscv_sstc_available; + +#ifdef ARCH_RISCV_M_MODE +static void *riscv_clint_timer_val, *riscv_clint_timer_cmp; +#endif + +void riscv_timer_set_frequency(rt_uint32_t freq) +{ + HWREG32(&timebase_frequency) = freq; + rt_hw_wmb(); +} + +rt_uint32_t riscv_timer_get_frequency(void) +{ + rt_hw_rmb(); + return HWREG32(&timebase_frequency); +} + +rt_uint64_t riscv_timer_rdtime(void) +{ +#ifdef ARCH_RISCV_M_MODE +#ifdef ARCH_CPU_64BIT + return HWREG64(riscv_clint_timer_val); +#else + rt_uint32_t hi, lo; + + do { + hi = HWREG32(riscv_clint_timer_val); + lo = HWREG32(riscv_clint_timer_val + sizeof(rt_uint32_t)); + } while (hi != HWREG32(riscv_clint_timer_val)); + + return ((rt_uint64_t)hi << 32) | lo; +#endif /* ARCH_CPU_64BIT */ +#else + uint64_t cycles64; + + __asm__ volatile ("rdtime %0":"=r"(cycles64)); + + return cycles64; +#endif /* ARCH_RISCV_M_MODE */ +} + +static void riscv_timer_next_event(void) +{ + rt_uint64_t stime_value = clock_cpu_gettime() + tick_cycles; + +#ifdef ARCH_RISCV_M_MODE + HWREG64(riscv_clint_timer_cmp + csr_read(CSR_MHARTID)) = stime_value; +#else + if (riscv_sstc_available) + { + #ifdef ARCH_CPU_64BIT + csr_write(CSR_STIMECMP, stime_value); + #else + csr_write(CSR_STIMECMP, stime_value & RT_UINT32_MAX); + csr_write(CSR_STIMECMPH, stime_value >> 32); + #endif + } + else + { + sbi_set_timer(stime_value); + } +#endif +} + +void riscv_timer_isr(void) +{ + rt_tick_increase(); + + riscv_timer_next_event(); +} + +/* Sets and enable the timer interrupt */ +void riscv_timer_init(void) +{ + rt_uint32_t freq = riscv_timer_get_frequency(); + +#ifdef RT_USING_SMP + if (rt_hw_cpu_id() == riscv_hartid_to_cpu_id(boot_cpu_hartid)) +#endif + { + if (!freq && !(freq = CPUTIME_TIMER_FREQ)) + { + riscv_timer_set_frequency(freq); + } + RT_ASSERT(freq > 0); + + /* RISC-V cputime will call init in `rt_components_board_init` */ + + #ifdef RT_USING_KTIME + rt_ktime_cputimer_init(); + #endif + + /* Calculate the tick cycles */ + tick_cycles = freq / RT_TICK_PER_SECOND; + + /* Check if timer interrupt in S-mode is available via sstc extension */ + riscv_sstc_available = riscv_isa_ext_test(SSTC); + } + + /* Clear the Supervisor-Timer bit in SIE */ + csr_clear(CSR_IE, BIT(IRQ_S_TIMER)); + + /* Set timer */ + riscv_timer_next_event(); + + /* Enable the Supervisor-Timer bit in SIE */ + csr_set(CSR_IE, BIT(IRQ_S_TIMER)); +} + +void riscv_timer_probe(void *clint_timer_cmp, void *clint_timer_val) +{ +#ifdef ARCH_RISCV_M_MODE + riscv_clint_timer_cmp = clint_timer_cmp; + riscv_clint_timer_val = clint_timer_val; +#endif +} + +void riscv_timer_us_delay(rt_uint32_t us) +{ + rt_ubase_t delay_time; + + delay_time = clock_cpu_gettime(); + delay_time += us * (riscv_timer_get_frequency() / 1000000); + + while (clock_cpu_gettime() < delay_time) + { + rt_hw_cpu_relax(); + } +} + +#if !defined(RT_USING_DM) || !defined(RT_USING_HWTIMER) +/** + * This function will delay for some us. + * + * @param us the delay time of us + */ +void rt_hw_us_delay(rt_uint32_t us) +{ + riscv_timer_us_delay(us); +} +#endif /* !RT_USING_DM || !RT_USING_HWTIMER */ diff --git a/libcpu/risc-v/common/rt_hw_stack_frame.h b/libcpu/risc-v/common/rt_hw_stack_frame.h deleted file mode 100644 index 75a9c2d45a4..00000000000 --- a/libcpu/risc-v/common/rt_hw_stack_frame.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-03 Bernard The first version - */ -#ifndef RISCV_STACKFRAME_H - -#define RISCV_STACKFRAME_H - -#include "cpuport.h" - -typedef struct rt_hw_stack_frame -{ - rt_ubase_t epc; /* epc - epc - program counter */ - rt_ubase_t ra; /* x1 - ra - return address for jumps */ - rt_ubase_t mstatus; /* - machine status register */ - rt_ubase_t gp; /* x3 - gp - global pointer */ - rt_ubase_t tp; /* x4 - tp - thread pointer */ - rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ - rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ - rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ - rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ - rt_ubase_t s1; /* x9 - s1 - saved register 1 */ - rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ - rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ - rt_ubase_t a2; /* x12 - a2 - function argument 2 */ - rt_ubase_t a3; /* x13 - a3 - function argument 3 */ - rt_ubase_t a4; /* x14 - a4 - function argument 4 */ - rt_ubase_t a5; /* x15 - a5 - function argument 5 */ -#ifndef __riscv_32e - rt_ubase_t a6; /* x16 - a6 - function argument 6 */ - rt_ubase_t a7; /* x17 - a7 - function argument 7 */ - rt_ubase_t s2; /* x18 - s2 - saved register 2 */ - rt_ubase_t s3; /* x19 - s3 - saved register 3 */ - rt_ubase_t s4; /* x20 - s4 - saved register 4 */ - rt_ubase_t s5; /* x21 - s5 - saved register 5 */ - rt_ubase_t s6; /* x22 - s6 - saved register 6 */ - rt_ubase_t s7; /* x23 - s7 - saved register 7 */ - rt_ubase_t s8; /* x24 - s8 - saved register 8 */ - rt_ubase_t s9; /* x25 - s9 - saved register 9 */ - rt_ubase_t s10; /* x26 - s10 - saved register 10 */ - rt_ubase_t s11; /* x27 - s11 - saved register 11 */ - rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ - rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ - rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ - rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ -#endif -#ifdef ARCH_RISCV_FPU - rv_floatreg_t f0; /* f0 */ - rv_floatreg_t f1; /* f1 */ - rv_floatreg_t f2; /* f2 */ - rv_floatreg_t f3; /* f3 */ - rv_floatreg_t f4; /* f4 */ - rv_floatreg_t f5; /* f5 */ - rv_floatreg_t f6; /* f6 */ - rv_floatreg_t f7; /* f7 */ - rv_floatreg_t f8; /* f8 */ - rv_floatreg_t f9; /* f9 */ - rv_floatreg_t f10; /* f10 */ - rv_floatreg_t f11; /* f11 */ - rv_floatreg_t f12; /* f12 */ - rv_floatreg_t f13; /* f13 */ - rv_floatreg_t f14; /* f14 */ - rv_floatreg_t f15; /* f15 */ - rv_floatreg_t f16; /* f16 */ - rv_floatreg_t f17; /* f17 */ - rv_floatreg_t f18; /* f18 */ - rv_floatreg_t f19; /* f19 */ - rv_floatreg_t f20; /* f20 */ - rv_floatreg_t f21; /* f21 */ - rv_floatreg_t f22; /* f22 */ - rv_floatreg_t f23; /* f23 */ - rv_floatreg_t f24; /* f24 */ - rv_floatreg_t f25; /* f25 */ - rv_floatreg_t f26; /* f26 */ - rv_floatreg_t f27; /* f27 */ - rv_floatreg_t f28; /* f28 */ - rv_floatreg_t f29; /* f29 */ - rv_floatreg_t f30; /* f30 */ - rv_floatreg_t f31; /* f31 */ -#endif -}rt_hw_stack_frame_t; - -#endif /* RISCV_STACKFRAME_H */ diff --git a/libcpu/risc-v/common64/sbi.c b/libcpu/risc-v/common/sbi.c similarity index 96% rename from libcpu/risc-v/common64/sbi.c rename to libcpu/risc-v/common/sbi.c index b2b1e8e7881..6aa77b50934 100644 --- a/libcpu/risc-v/common64/sbi.c +++ b/libcpu/risc-v/common/sbi.c @@ -35,9 +35,9 @@ * SUCH DAMAGE. */ -#include "sbi.h" #include -#include + +#include /* SBI Implementation-Specific Definitions */ #define OPENSBI_VERSION_MAJOR_OFFSET 16 @@ -47,9 +47,9 @@ unsigned long sbi_spec_version; unsigned long sbi_impl_id; unsigned long sbi_impl_version; -static bool has_time_extension = false; -static bool has_ipi_extension = false; -static bool has_rfnc_extension = false; +bool has_time_extension = false; +bool has_ipi_extension = false; +bool has_rfnc_extension = false; static struct sbi_ret sbi_get_spec_version(void) { @@ -254,11 +254,3 @@ void sbi_init(void) if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0) has_rfnc_extension = true; } - -void rt_hw_console_output(const char *str) -{ - while (*str) - { - sbi_console_putchar(*str++); - } -} diff --git a/libcpu/risc-v/common/serial/Kconfig b/libcpu/risc-v/common/serial/Kconfig new file mode 100644 index 00000000000..1ef9725983d --- /dev/null +++ b/libcpu/risc-v/common/serial/Kconfig @@ -0,0 +1,5 @@ +config RT_SERIAL_EARLY_SBI + bool "Early SBI" + depends on RT_USING_SERIAL + depends on !ARCH_RISCV_M_MODE + default y diff --git a/libcpu/risc-v/common/serial/SConscript b/libcpu/risc-v/common/serial/SConscript new file mode 100644 index 00000000000..675b16a71f8 --- /dev/null +++ b/libcpu/risc-v/common/serial/SConscript @@ -0,0 +1,17 @@ +from building import * + +group = [] + +if not GetDepend(['RT_USING_SERIAL']): + Return('group') + +src = [] +cwd = GetCurrentDir() +CPPPATH = [cwd] + +if GetDepend(['RT_SERIAL_EARLY_SBI']): + src += ['serial-early-sbi.c'] + +group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/risc-v/common/serial/serial-early-sbi.c b/libcpu/risc-v/common/serial/serial-early-sbi.c new file mode 100644 index 00000000000..afbe8d39ab2 --- /dev/null +++ b/libcpu/risc-v/common/serial/serial-early-sbi.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-01-30 GuEe-GUI first version + */ + +#include + +#include + +static void sbi_early_console_putchar(void *data, char c) +{ + sbi_console_putchar(c); +} + +static rt_err_t sbi_early_setup(struct rt_fdt_earlycon *con, const char *options) +{ + con->console_putc = sbi_early_console_putchar; + + return RT_EOK; +} +RT_FDT_EARLYCON_EXPORT(sbi, "sbi", "riscv,sbi-console", sbi_early_setup); diff --git a/libcpu/risc-v/common/setup.c b/libcpu/risc-v/common/setup.c new file mode 100644 index 00000000000..99f4d6c14a8 --- /dev/null +++ b/libcpu/risc-v/common/setup.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI the first version + */ + +#include +#include + +#if __riscv_xlen == 128 +#define DBG_TAG "cpu.rv128" +#elif __riscv_xlen == 64 +#define DBG_TAG "cpu.rv64" +#elif __riscv_xlen == 32 +#define DBG_TAG "cpu.rv32" +#else +#error "Unexpected __riscv_xlen" +#endif +#define DBG_LVL DBG_INFO +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef RT_USING_LWP +#include +#include +#endif + +#ifndef IOREMAP_SIZE +#define IOREMAP_SIZE 0x20000000 +#endif + +extern rt_ubase_t _start, _end; +extern void rt_hw_builtin_fdt(); +extern size_t MMUTable[]; + +static void *fdt_ptr = RT_NULL; +static rt_size_t fdt_size = 0; + +#ifdef RT_USING_SMP +extern struct cpu_ops_t cpu_sbi_ops; +extern struct cpu_ops_t cpu_spinwait_ops; + +static struct cpu_ops_t *cpu_ops = &cpu_spinwait_ops; +static struct rt_ofw_node *cpu_np[RT_CPUS_NR] = { }; +#endif /* RT_USING_SMP */ + +static struct { rt_uint8_t size; const char name[11]; } mmu_type[] = +{ + { 0, "riscv,none" }, +#if __riscv_xlen == 32 + { 32, "riscv,sv32" }, +#else + { 39, "riscv,sv39" }, + { 48, "riscv,sv48" }, + { 57, "riscv,sv57" }, + { 64, "riscv,sv64" }, +#endif +}; + +rt_weak void rt_hw_fdt_vendor_install_early(void *fdt) +{ + RT_UNUSED(fdt); +} + +void rt_hw_fdt_install_early(void *fdt) +{ + int cpu_id = 0, cpus, cpu, size; + +#ifndef RT_USING_BUILTIN_FDT + if (fdt != RT_NULL && !fdt_check_header(fdt)) + { + fdt_ptr = fdt; + fdt_size = fdt_totalsize(fdt); + } +#else + fdt = &rt_hw_builtin_fdt; +#endif + + rt_hw_fdt_vendor_install_early(fdt); + + rt_hw_arch_vaddr_width = ARCH_ADDRESS_WIDTH_BITS; + + cpus = fdt_path_offset(fdt, "/cpus"); + + fdt_for_each_subnode(cpu, fdt, cpus) + { + rt_uint32_t value; + const char *name = fdt_getprop(fdt, cpu, "mmu-type", RT_NULL); + + if (!name || cpu_id >= RT_CPUS_NR) + { + break; + } + + fdt_getprop_u32(fdt, cpu, "reg", &value, RT_NULL); + + riscv_hartid_remap_cpu_id(value, cpu_id); + + if (value == boot_cpu_hartid) + { + if (!fdt_getprop_u32(fdt, cpu, "riscv,cbom-block-size", &value, RT_NULL) && value > 0) + { + riscv_isa_ext_set(ZICBOM); + riscv_cache_set_cbom_block_size(value); + } + } + + size = rt_hw_arch_vaddr_width; + + for (int i = 0; i < RT_ARRAY_SIZE(mmu_type); ++i) + { + rt_typeof(mmu_type[0]) *type = &mmu_type[i]; + + if (!rt_strcmp(name, type->name)) + { + size = type->size; + break; + } + } + + if (size < rt_hw_arch_vaddr_width) + { + rt_hw_arch_vaddr_width = size; + } + ++cpu_id; + } +} + +rt_weak void rt_hw_idle_wfi(void) +{ + __asm__ volatile ("wfi"); +} + +static struct { const char *name; rt_uint8_t size; } isa_ext[] = +{ +#define DECLARE_ISA(isa, name) [RISCV_ISA_EXT_##isa] = { name, sizeof(name) - 1 }, + DECLARE_ISA(I, "i") + DECLARE_ISA(M, "m") + DECLARE_ISA(A, "a") + DECLARE_ISA(F, "f") + DECLARE_ISA(D, "d") + DECLARE_ISA(Q, "q") + DECLARE_ISA(C, "c") + DECLARE_ISA(V, "v") + DECLARE_ISA(H, "h") + DECLARE_ISA(SSCOFPMF, "sscofpmf") + DECLARE_ISA(SSTC, "sstc") + DECLARE_ISA(SVINVAL, "svinval") + DECLARE_ISA(SVPBMT, "svpbmt") + DECLARE_ISA(ZBB, "zbb") + DECLARE_ISA(ZICBOM, "zicbom") + DECLARE_ISA(ZIHINTPAUSE, "zihintpause") + DECLARE_ISA(SVNAPOT, "svnapot") + DECLARE_ISA(ZICBOZ, "zicboz") + DECLARE_ISA(SMAIA, "smaia") + DECLARE_ISA(SSAIA, "ssaia") + DECLARE_ISA(ZBA, "zba") + DECLARE_ISA(ZBS, "zbs") + DECLARE_ISA(ZICNTR, "zicntr") + DECLARE_ISA(ZICSR, "zicsr") + DECLARE_ISA(ZIFENCEI, "zifencei") + DECLARE_ISA(ZIHPM, "zihpm") + DECLARE_ISA(SMSTATEEN, "smstateen") + DECLARE_ISA(ZICOND, "zicond") + DECLARE_ISA(ZBC, "zbc") + DECLARE_ISA(ZBKB, "zbkb") + DECLARE_ISA(ZBKC, "zbkc") + DECLARE_ISA(ZBKX, "zbkx") + DECLARE_ISA(ZKND, "zknd") + DECLARE_ISA(ZKNE, "zkne") + DECLARE_ISA(ZKNH, "zknh") + DECLARE_ISA(ZKR, "zkr") + DECLARE_ISA(ZKSED, "zksed") + DECLARE_ISA(ZKSH, "zksh") + DECLARE_ISA(ZKT, "zkt") + DECLARE_ISA(ZVBB, "zvbb") + DECLARE_ISA(ZVBC, "zvbc") + DECLARE_ISA(ZVKB, "zvkb") + DECLARE_ISA(ZVKG, "zvkg") + DECLARE_ISA(ZVKNED, "zvkned") + DECLARE_ISA(ZVKNHA, "zvknha") + DECLARE_ISA(ZVKNHB, "zvknhb") + DECLARE_ISA(ZVKSED, "zvksed") + DECLARE_ISA(ZVKSH, "zvksh") + DECLARE_ISA(ZVKT, "zvkt") + DECLARE_ISA(ZFH, "zfh") + DECLARE_ISA(ZFHMIN, "zfhmin") + DECLARE_ISA(ZIHINTNTL, "zihintntl") + DECLARE_ISA(ZVFH, "zvfh") + DECLARE_ISA(ZVFHMIN, "zvfhmin") + DECLARE_ISA(ZFA, "zfa") + DECLARE_ISA(ZTSO, "ztso") + DECLARE_ISA(ZACAS, "zacas") + DECLARE_ISA(XANDESPMU, "xandespmu") +#undef DECLARE_ISA +}; + +rt_inline void cpu_info_init(void) +{ + int i = 0; + rt_uint32_t value; + const char *string; + struct rt_ofw_prop *prop; + struct rt_ofw_node *np, *boot_cpu_np = RT_NULL; + + if ((np = rt_ofw_find_node_by_path("/cpus")) && + !rt_ofw_prop_read_u32(np, "timebase-frequency", &value)) + { + riscv_timer_set_frequency(value); + + #ifdef RT_USING_HWTIMER + if (!rt_device_hwtimer_us_delay) + { + rt_device_hwtimer_us_delay = &riscv_timer_us_delay; + } + #endif /* RT_USING_HWTIMER */ + } + else + { + LOG_E("No '%s' in DTS", "timebase-frequency"); + } + rt_ofw_node_put(np); + +#if defined(RT_USING_SMP) && !defined(ARCH_RISCV_M_MODE) + if (sbi_probe_extension(SBI_EXT_ID_HSM)) + { + LOG_I("SBI HSM extension detected"); + cpu_ops = &cpu_sbi_ops; + } +#endif /* RT_USING_SMP && !ARCH_RISCV_M_MODE */ + + rt_ofw_foreach_cpu_node(np) + { + if ((rt_ubase_t)rt_ofw_get_cpu_hwid(np, 0) == boot_cpu_hartid) + { + boot_cpu_np = np; + rt_ofw_node_get(boot_cpu_np); + } + + #ifdef RT_USING_SMP + if (i < RT_CPUS_NR) + { + cpu_np[i] = np; + + if (cpu_ops->cpu_init) + { + cpu_ops->cpu_init(i, np); + } + } + else + { + break; + } + ++i; + #endif /* RT_USING_SMP */ + } + + if (!(np = boot_cpu_np)) + { + LOG_E("No '%s' in DTS", "Boot CPU"); + return; + } + + rt_ofw_foreach_prop_string(np, "riscv,isa-extensions", prop, string) + { + for (i = 0; i < RT_ARRAY_SIZE(isa_ext); ++i) + { + rt_typeof(isa_ext[0]) *ext = &isa_ext[i]; + + if (ext->name && !rt_strcmp(ext->name, string)) + { + riscv_isa_ext_set_raw(i); + break; + } + } + } + + if (!rt_ofw_prop_read_bool(np, "riscv,isa-base")) + { + if (rt_ofw_prop_read_string(np, "riscv,isa", &string)) + { + LOG_E("%s ISA no found", rt_ofw_node_full_name(np)); + goto _exit; + } + + if ((!rt_strncmp(string, "rv32", 4) && __riscv_xlen != 32) || + (!rt_strncmp(string, "rv64", 4) && __riscv_xlen != 64)) + { + LOG_E("%s ISA %.4s is not supported", rt_ofw_node_full_name(np), string); + goto _exit; + } + + string += 4; + + /* ISA: 'i', 'm', 'a', 'f', 'd', 'q', 'c', 'v', 'h'... */ + while (*string && *string != '_') + { + for (i = 0; i < RISCV_ISA_EXT_BASE; ++i) + { + rt_typeof(isa_ext[0]) *ext = &isa_ext[i]; + + if (ext->name && ext->name[0] == *string) + { + riscv_isa_ext_set_raw(i); + break; + } + } + + ++string; + } + + /* Skip '_' */ + while (*string && *(++string)) + { + int size = 0; + + for (i = RISCV_ISA_EXT_BASE; i < RT_ARRAY_SIZE(isa_ext); ++i) + { + rt_typeof(isa_ext[0]) *ext = &isa_ext[i]; + + if (ext->name && !rt_strncmp(ext->name, string, ext->size)) + { + size = ext->size; + riscv_isa_ext_set_raw(i); + break; + } + } + + if (!size) + { + const char *skip = rt_strstr(string, "_"); + + size = skip ? skip - string : rt_strlen(string); + + LOG_E("Unknow ISA %.*s", size, string); + } + + string += size; + } + } + +_exit: + rt_ofw_node_put(np); +} + +rt_inline rt_size_t string_to_size(const char *string, const char *who) +{ + char unit; + rt_size_t size; + const char *cp = string; + + size = atoi(cp); + + while (*cp >= '0' && *cp <= '9') + { + ++cp; + } + + unit = *cp & '_'; + + if (unit == 'M') + { + size *= SIZE_MB; + } + else if (unit == 'K') + { + size *= SIZE_KB; + } + else if (unit == 'G') + { + size *= SIZE_GB; + } + else + { + LOG_W("Unknown unit of '%c' in `%s`", unit, who); + } + + return size; +} + +void rt_hw_common_setup(void) +{ + rt_uint64_t initrd_ranges[3]; + rt_size_t kernel_start, kernel_end; + rt_size_t heap_start, heap_end; + rt_size_t init_page_start, init_page_end; + rt_size_t fdt_start, fdt_end; + rt_region_t init_page_region = { 0 }; + rt_region_t platform_mem_region = { 0 }; + static struct mem_desc platform_mem_desc; + const rt_ubase_t pv_off = PV_OFFSET; + +#ifdef RT_USING_SMART +#if KERNEL_VADDR_START > USER_VADDR_START + rt_hw_mmu_map_init(&rt_kernel_space, (void *)(0UL - IOREMAP_SIZE), IOREMAP_SIZE, MMUTable, pv_off); +#else + rt_hw_mmu_map_init(&rt_kernel_space, (void *)(USER_VADDR_START - IOREMAP_SIZE), IOREMAP_SIZE, MMUTable, pv_off); +#endif +#else +#if __riscv_xlen == 32 + rt_hw_mmu_map_init(&rt_kernel_space, (void *)((rt_ubase_t)&_start - IOREMAP_SIZE), IOREMAP_SIZE, MMUTable, 0); + rt_memblock_reserve_memory("ioremap", (rt_size_t)&_start - IOREMAP_SIZE, (rt_size_t)&_start, MEMBLOCK_NONE); +#else + rt_hw_mmu_map_init(&rt_kernel_space, (void *)(ARCH_PAGE_MASK << RT_ALIGN_DOWN(rt_hw_arch_vaddr_width - ARCH_PAGE_SHIFT, 4)), IOREMAP_SIZE, MMUTable, 0); +#endif +#endif /* RT_USING_SMART */ + + kernel_start = RT_ALIGN_DOWN((rt_size_t)&_start + pv_off - 64, ARCH_PAGE_SIZE); + kernel_end = RT_ALIGN((rt_size_t)&_end + pv_off, ARCH_PAGE_SIZE); + heap_start = kernel_end; + heap_end = RT_ALIGN(heap_start + ARCH_HEAP_SIZE, ARCH_PAGE_SIZE); + init_page_start = heap_end; + init_page_end = RT_ALIGN(init_page_start + ARCH_INIT_PAGE_SIZE, ARCH_PAGE_SIZE); + fdt_start = init_page_end; + fdt_end = RT_ALIGN(fdt_start + fdt_size, ARCH_PAGE_SIZE); + + platform_mem_region.start = kernel_start; +#ifndef RT_USING_BUILTIN_FDT + platform_mem_region.end = fdt_end; +#else + platform_mem_region.end = init_page_end; + (void)fdt_start; + (void)fdt_end; +#endif + + rt_memblock_reserve_memory("kernel", kernel_start, kernel_end, MEMBLOCK_NONE); + rt_memblock_reserve_memory("memheap", heap_start, heap_end, MEMBLOCK_NONE); + rt_memblock_reserve_memory("init-page", init_page_start, init_page_end, MEMBLOCK_NONE); +#ifndef RT_USING_BUILTIN_FDT + rt_memblock_reserve_memory("fdt", fdt_start, fdt_end, MEMBLOCK_NONE); + + /* To virtual address */ + fdt_ptr = (void *)(fdt_ptr - pv_off); +#ifdef KERNEL_VADDR_START + if ((rt_ubase_t)fdt_ptr + fdt_size - KERNEL_VADDR_START > ARCH_EARLY_MAP_SIZE) + { + fdt_ptr = rt_ioremap_early(fdt_ptr + pv_off, fdt_size); + + RT_ASSERT(fdt_ptr != RT_NULL); + } +#endif /* KERNEL_VADDR_START */ + rt_memmove((void *)(fdt_start - pv_off), fdt_ptr, fdt_size); + fdt_ptr = (void *)fdt_start - pv_off; +#else + fdt_ptr = &rt_hw_builtin_fdt; + fdt_size = fdt_totalsize(fdt_ptr); +#endif /* RT_USING_BUILTIN_FDT */ + + rt_system_heap_init((void *)(heap_start - pv_off), (void *)(heap_end - pv_off)); + + init_page_region.start = init_page_start - pv_off; + init_page_region.end = init_page_end - pv_off; + rt_page_init(init_page_region); + + /* Create MMU mapping of kernel memory */ + platform_mem_region.start = RT_ALIGN_DOWN(platform_mem_region.start, ARCH_PAGE_SIZE); + platform_mem_region.end = RT_ALIGN(platform_mem_region.end, ARCH_PAGE_SIZE); + + platform_mem_desc.paddr_start = platform_mem_region.start; + platform_mem_desc.vaddr_start = platform_mem_region.start - pv_off; + platform_mem_desc.vaddr_end = platform_mem_region.end - pv_off - 1; + platform_mem_desc.attr = NORMAL_MEM; + + rt_hw_mmu_setup(&rt_kernel_space, &platform_mem_desc, 1); + + if (rt_fdt_prefetch(fdt_ptr)) + { + /* Platform cannot be initialized */ + RT_ASSERT(0); + } + +#ifdef RT_USING_HWCACHE + rt_hwcache_init(); + + rt_hwcache_icache_enable(); + rt_hwcache_dcache_enable(); +#endif /* RT_USING_HWCACHE */ + + rt_fdt_scan_chosen_stdout(); + + rt_fdt_scan_initrd(initrd_ranges); + + rt_fdt_scan_memory(); + +#ifdef RT_USING_DMA + do { + const char *bootargs; + rt_ubase_t dma_pool_base; + rt_size_t cma_size = 0, coherent_pool_size = 0; + + if (!rt_fdt_bootargs_select("cma=", 0, &bootargs)) + { + cma_size = string_to_size(bootargs, "cma"); + } + + if (!rt_fdt_bootargs_select("coherent_pool=", 0, &bootargs)) + { + coherent_pool_size = string_to_size(bootargs, "coherent-pool"); + } + + if (cma_size <= coherent_pool_size) + { + if (cma_size || coherent_pool_size) + { + LOG_W("DMA pool %s=%u > %s=%u", + "CMA", cma_size, "coherent-pool", coherent_pool_size); + } + + cma_size = 8 * SIZE_MB; + coherent_pool_size = 2 * SIZE_MB; + } + + dma_pool_base = platform_mem_region.end; + rt_memblock_reserve_memory("dma-pool", + dma_pool_base, dma_pool_base + cma_size + coherent_pool_size, MEMBLOCK_NONE); + + if (rt_dma_pool_extract(cma_size, coherent_pool_size)) + { + LOG_E("Alloc DMA pool %s=%u, %s=%u fail", + "CMA", cma_size, "coherent-pool", coherent_pool_size); + } + } while (0); +#endif /* RT_USING_DMA */ + + rt_memblock_setup_memory_environment(); + + rt_fdt_earlycon_kick(FDT_EARLYCON_KICK_UPDATE); + + rt_fdt_unflatten(); + + cpu_info_init(); + + rt_pic_init(); + rt_pic_irq_init(); + + riscv_timer_init(); + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) + rt_ofw_console_setup(); +#endif + + rt_thread_idle_sethook(rt_hw_idle_wfi); + +#ifdef RT_USING_SMP + rt_smp_call_init(); + /* Install the IPI handle */ + rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler); + rt_hw_ipi_handler_install(RT_STOP_IPI, rt_scheduler_ipi_handler); + rt_hw_ipi_handler_install(RT_SMP_CALL_IPI, rt_smp_call_ipi_handler); + rt_hw_interrupt_umask(RT_SCHEDULE_IPI); + rt_hw_interrupt_umask(RT_STOP_IPI); + rt_hw_interrupt_umask(RT_SMP_CALL_IPI); +#endif /* RT_USING_SMP */ +} + +#ifndef ARCH_RISCV_M_MODE +static int system_env_init(void) +{ + rt_dm_machine_shutdown = rt_dm_machine_shutdown ? : sbi_shutdown; + + return 0; +} +INIT_ENV_EXPORT(system_env_init); +#endif /* ARCH_RISCV_M_MODE */ + +#ifdef RT_USING_SMP +rt_weak void rt_hw_secondary_cpu_up(void) +{ + int cpu_id = rt_hw_cpu_id(); + rt_ubase_t entry = (rt_ubase_t)rt_kmem_v2p(_secondary_cpu_entry); + + if (!entry) + { + LOG_E("Failed to translate '_secondary_cpu_entry' to physical address"); + RT_ASSERT(0); + } + + /* Maybe we are no in the first cpu */ + for (int i = 0; i < RT_ARRAY_SIZE(cpu_np); ++i) + { + int err; + + if (!cpu_np[i] || i == cpu_id) + { + continue; + } + + if ((err = cpu_ops->cpu_boot(i, entry))) + { + LOG_W("Call cpu %d on %s", i, "failed"); + } + } +} + +rt_weak void rt_hw_secondary_cpu_bsp_start(void) +{ + int cpu_id = rt_hw_cpu_id(); + + rt_hw_spin_lock(&_cpus_lock); + + rt_hw_mmu_tbl_set((unsigned long)rt_kernel_space.page_table); + + rt_pic_irq_init(); + + riscv_timer_init(); + + rt_dm_secondary_cpu_init(); + + rt_hw_interrupt_umask(RT_SCHEDULE_IPI); + rt_hw_interrupt_umask(RT_STOP_IPI); + rt_hw_interrupt_umask(RT_SMP_CALL_IPI); + + LOG_I("Call cpu %d on %s", cpu_id, "success"); + + rt_system_scheduler_start(); +} + +rt_weak void rt_hw_secondary_cpu_idle_exec(void) +{ + rt_hw_idle_wfi(); +} +#endif /* RT_USING_SMP */ + +void rt_hw_console_output(const char *str) +{ + rt_fdt_earlycon_output(str); +} diff --git a/libcpu/risc-v/common/stack.c b/libcpu/risc-v/common/stack.c new file mode 100644 index 00000000000..d35f96bcb09 --- /dev/null +++ b/libcpu/risc-v/common/stack.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-28 Bernard The unify RISC-V porting code. + * 2021-02-11 lizhirui add gp support + * 2021-11-19 JasonHu add fpu support + * 2025-04-20 GuEe-GUI Port for CPU ID + */ + +#include +#include +#include +#include +#include + +/** + * This function will initialize thread stack, we assuming + * when scheduler restore this new thread, context will restore + * an entry to user first application + * + * s0-s11, ra, sstatus, a0 + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, + rt_uint8_t *stack_addr, + void *texit) +{ + rt_ubase_t *sp; + rt_hw_switch_frame_t frame; + + /* We use a strict alignment requirement for Q extension */ + sp = (rt_ubase_t *)RT_ALIGN_DOWN((rt_ubase_t)stack_addr, 16); + + *(--sp) = (rt_ubase_t)tentry; + *(--sp) = (rt_ubase_t)parameter; + *(--sp) = (rt_ubase_t)texit; + /* Alignment */ + --sp; + + frame = (rt_hw_switch_frame_t)((rt_ubase_t)sp - sizeof(*frame)); + rt_memset(frame, 0, sizeof(*frame)); + + frame->regs[RT_HW_SWITCH_CONTEXT_RA] = (rt_ubase_t)_thread_start; + frame->regs[RT_HW_SWITCH_CONTEXT_XSTATUS] = K_XSTATUS_DEFAULT; +#ifdef RT_USING_SMP +#ifdef ARCH_MM_MMU + /* + * MMU is disabled, pre-CPU is not available, + * Well, LWP is disabled, too. We can use 'TP' to save CPU ID. + */ + if (!ARCH_VADDR_WIDTH) +#endif /* ARCH_MM_MMU */ + { + frame->regs[RT_HW_SWITCH_CONTEXT_TP] = rt_hw_cpu_id(); + } +#endif /* RT_USING_SMP */ + + return (void *)frame; +} diff --git a/libcpu/risc-v/common/stack_gcc.S b/libcpu/risc-v/common/stack_gcc.S new file mode 100644 index 00000000000..c6eaaba7549 --- /dev/null +++ b/libcpu/risc-v/common/stack_gcc.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-19 RT-Thread the first version + */ + +#include "asm-generic.h" + + .section ".text","ax" + +START_POINT(_thread_start) + REG_L ra, SZREG(sp) /* thread exit */ + addi sp, sp, 2 * SZREG + REG_L a0, (sp) /* parameter */ + REG_L t0, SZREG(sp) /* tentry */ + addi sp, sp, 2 * SZREG + mv s1, ra + jalr t0 + jalr s1 + j . /* never here */ +START_POINT_END(_thread_start) diff --git a/libcpu/risc-v/common/startup_gcc.S b/libcpu/risc-v/common/startup_gcc.S new file mode 100755 index 00000000000..d6fa3e2b39a --- /dev/null +++ b/libcpu/risc-v/common/startup_gcc.S @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-01 Bernard The first version + * 2018-12-27 Jesven Add SMP support + * 2020-6-12 Xim Port to QEMU and remove SMP support + * 2024-06-30 Shell Support of kernel remapping + * 2025-04-20 GuEe-GUI Support DM and merge 64I and 32I/E mode with SMP + */ + +#include +#include +#include + +#define RISCV_IMAGE_FLAG_BE_SHIFT 0 +#define RISCV_IMAGE_FLAG_BE_MASK 0x1 + +#define RISCV_IMAGE_FLAG_LE 0 +#define RISCV_IMAGE_FLAG_BE 1 + +#define RISCV_HEADER_VERSION_MAJOR 0 +#define RISCV_HEADER_VERSION_MINOR 2 + +#ifdef ARCH_CPU_BIG_ENDIAN +#error conversion of header fields to LE not yet implemented +#else +#define __HEAD_FLAG_BE RISCV_IMAGE_FLAG_LE +#endif + +#define __HEAD_FLAG(field) (__HEAD_FLAG_##field << RISCV_IMAGE_FLAG_##field##_SHIFT) + +#define __HEAD_FLAGS (__HEAD_FLAG(BE)) + +#define __HEAD_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | RISCV_HEADER_VERSION_MINOR) + + .section ".text.start","ax" + +#ifdef RT_USING_OFW +/* + * We follow the kernel's boot in RISC-V: + * https://www.kernel.org/doc/html/latest/arch/riscv/boot-image-header.html + */ +_head: + j _start /* Executable code */ + .word 0 /* Executable code */ + .balign 8 +#if __riscv_xlen == 64 + .dword 0x200000 /* Image load offset(2MB) from start of RAM */ +#elif __riscv_xlen == 32 + .dword 0x400000 /* Image load offset(4MB) from start of RAM */ +#else +#error "Unexpected __riscv_xlen" +#endif + .dword _end - _head /* Effective Image size, little endian (_end defined in link.lds) */ + .dword __HEAD_FLAGS /* kernel flags, little endian */ + .word __HEAD_VERSION /* Version of this header */ + .word 0 /* Reserved */ + .dword 0 /* Reserved */ + .ascii "RISCV\0\0\0" /* Magic number, little endian */ + .balign 4 + .ascii "RSC\x05" /* Magic number 2, little endian */ + .word 0 /* Reserved for PE COFF offset */ +#endif /* RT_USING_OFW */ + + .global _start +_start: +/* + * Boot CPU general-purpose register settings: + * https://www.kernel.org/doc/html/latest/arch/riscv/boot.html#pre-kernel-requirements-and-constraints + * a0 = hartid of the current core. + * a1 = physical address of device tree blob (dtb) in system RAM. + */ + mv s0, a0 + mv s1, a1 + call init_cpu_common + +#ifdef RT_USING_SMP + /* Pick one hart to run the main boot sequence */ + la t0, .hart_lottery + li t1, 1 + amoadd.w t0, t1, (t0) + bnez t0, secondary_cpu_spin +#endif + + call init_kernel_bss + + /* Just for temporary use, sp will reset later */ + la sp, .percpu_stack_top + + la t0, boot_cpu_hartid + REG_S s0, (t0) + +#ifdef RT_USING_SMP + mv a0, s0 + call riscv_hartid_to_cpu_id + la t0, riscv_master_cpu_id + REG_S s0, (t0) +#endif + +#ifdef RT_USING_OFW + /* Save devicetree info */ + mv a0, a1 + call rt_hw_fdt_install_early +#endif + +#ifndef ARCH_RISCV_M_MODE + call sbi_init +#endif + + /* Now we are in the end of boot cpu process */ + la s1, rtthread_startup + j init_kernel_early + +kernel_start: + /* Set traps vectors (Mode = 0) */ + la t0, system_vectors + csrw CSR_TVEC, t0 + + /* Jump to the PE's system entry */ + mv ra, s1 + mv fp, zero + jalr x0, s1, 0 + +cpu_idle: + wfi + j cpu_idle + +#ifdef RT_USING_SMP +secondary_cpu_spin: + la t0, riscv_spinwait_table + +.wait_for_cpu_up: + REG_L t1, (t0) + beqz t1, .wait_for_cpu_up + fence + j _secondary_cpu_start + + .global _secondary_cpu_entry +_secondary_cpu_entry: + /* a0 = hartid of the current core. */ + mv s0, a0 + + call init_cpu_common + +_secondary_cpu_start: + /* Secondary cpu start to startup */ + la s1, rt_hw_secondary_cpu_bsp_start + j start_kernel_early +#endif /* RT_USING_SMP */ + +init_cpu_common: + /* Mask all interrupts */ + csrw CSR_IE, zero + csrw CSR_IP, zero + + /* Load the global pointer */ + LOAD_GLOBAL_POINTER + + /* + * Disable FPU & VECTOR to detect illegal usage of + * floating point or vector in kernel space + */ + li t0, SR_FS_VS + csrc CSR_STATUS, t0 + + /* + * Set sup0 scratch register to 0, indicating to exception vector that + * we are presently executing in kernel. + */ + csrw CSR_SCRATCH, zero + + ret + +init_kernel_bss: + la t0, __bss_start + la t1, __bss_end + ble t1, t0, .clean_bss_end + +.clean_bss_loop: + REG_S zero, (t0) + add t0, t0, RISCV_SZPTR + blt t0, t1, .clean_bss_loop + +.clean_bss_end: + ret + +init_kernel_early: +#ifdef ARCH_MM_MMU + la a0, .early_page_array + call set_free_page + + /* Get linker address to a0 */ + la a0, .kernel_vaddr_start + REG_L a0, (a0) + /* Get runtime address to a1 */ + la a1, _head + /* Get early page for map to a2 */ + la a2, .early_tbl_page + + /* Try to setup */ + call rt_hw_mem_setup_early +#endif /* ARCH_MM_MMU */ + +start_kernel_early: +#ifdef RT_USING_SMP + /* Only reset sp in SMP mode */ + la t0, cpu_id_to_hartid_map + mv t1, zero + li t2, RT_CPUS_NR + j .cpu_id_confirm + +.cpu_next_id_confirm: + add t1, t1, 1 + /* Out of range? */ + beq t1, t2, cpu_idle + add t0, t0, RISCV_SZPTR + +.cpu_id_confirm: + REG_L t3, (t0) + bne s0, t3, .cpu_next_id_confirm + + /* Set stack top by cpu id (t1) */ + li t0, ARCH_SECONDARY_CPU_STACK_SIZE + mul t0, t0, t1 + la t2, .percpu_stack_top + add t0, t2, t0 + mv sp, t0 + + /* Save CPU ID, if MMU is available, tp will not use */ + mv tp, t1 +#endif /* RT_USING_SMP */ + +#ifdef ARCH_MM_MMU + /* Support MMU? */ + la a0, rt_hw_arch_vaddr_width + REG_L a0, (a0) + beqz a0, .prepare_start_kernel + +#ifdef RT_USING_SMP + la a0, .percpu_hartid + mv a1, s0 + call percpu_hartid_init +#endif /* RT_USING_SMP */ + + la a0, .early_tbl_page + mv a1, s0 + call mmu_satp_load + mv s2, a0 + + /* Read the PV offset to a0 */ + call rt_kmem_pvoff + + /* Set the gp to virtual address */ + sub gp, gp, a0 + +#ifdef RT_USING_SMP + /* The sp is unity in per-CPU */ + la sp, .percpu_stack_top +#endif + /* Set the sp to virtual address */ + sub sp, sp, a0 + + /* Enable MMU */ + csrw satp, s2 + sfence.vma zero, zero + +.prepare_start_kernel: + /* Set kernel entry to the virtual address */ + sub s1, s1, a0 +#else + mv a0, zero +#endif /* ARCH_MM_MMU */ + + /* Set RA to kernel_start function, to return to the virtual address */ + la t0, kernel_start + sub t0, t0, a0 + mv ra, t0 + + ret + + .section ".data" + .balign RISCV_SZPTR +#ifdef RT_USING_SMP +.hart_lottery: + .word 0 +#endif + +.kernel_vaddr_start: + RISCV_PTR __text_start + +/* + * CPU stack builtin + */ + .section ".percpu" +.percpu_stack_bottom: +#if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) +#if ARCH_SECONDARY_CPU_STACK_SIZE < ARCH_PAGE_SIZE +#error ARCH_SECONDARY_CPU_STACK_SIZE MUST >= ARCH_PAGE_SIZE +#endif + .space ARCH_SECONDARY_CPU_STACK_SIZE - 16 +.percpu_stack_top: +.percpu_hartid: + .space 16 +#else + .space ARCH_SECONDARY_CPU_STACK_SIZE +.percpu_stack_top: +#endif /* RT_USING_SMP && ARCH_MM_MMU */ + +#ifdef ARCH_MM_MMU +/* + * Early page builtin, map 4G by 2MB page: + * Sv32 => 1 TBL -> 4 pages + * Sv39 => 1 TBL -> 5 pages + * Sv48 => 1 TBL -> 6 pages + * Sv57 => 1 TBL -> 7 pages + * Sv64 => 1 TBL -> 8 pages + * ioremap early -> 8 pages + * .percpu early -> 5 pages (Sv64) + */ + .section ".bss.noclean.early_page" + .balign ARCH_PAGE_SIZE +.early_tbl_page: + .space 1 * ARCH_PAGE_SIZE +#if defined(RT_USING_SMP) && RT_CPUS_NR > 1 + .space (RT_CPUS_NR - 1) * ARCH_PAGE_SIZE +#endif + +.early_page_array: + .space (8 + 8) * ARCH_PAGE_SIZE +#ifdef RT_USING_SMP + .space RT_CPUS_NR * 5 * ARCH_PAGE_SIZE +#endif +#endif /* ARCH_MM_MMU */ diff --git a/libcpu/risc-v/common64/syscall_c.c b/libcpu/risc-v/common/syscall.c similarity index 90% rename from libcpu/risc-v/common64/syscall_c.c rename to libcpu/risc-v/common/syscall.c index ceffd94dbcd..c8df566c4c2 100644 --- a/libcpu/risc-v/common64/syscall_c.c +++ b/libcpu/risc-v/common/syscall.c @@ -12,20 +12,15 @@ #include #include -#ifdef RT_USING_SMART - #define DBG_TAG "syscall" #define DBG_LVL DBG_WARNING #include -#include #include #include +#include #include -#include "riscv_mmu.h" -#include "stack.h" - typedef rt_ubase_t (*syscallfunc_t)(rt_ubase_t, rt_ubase_t, rt_ubase_t, rt_ubase_t, rt_ubase_t, rt_ubase_t, rt_ubase_t); void syscall_handler(struct rt_hw_stack_frame *regs) @@ -36,8 +31,11 @@ void syscall_handler(struct rt_hw_stack_frame *regs) if (syscallid == 0) { LOG_E("syscall id = 0!\n"); - while (1) - ; + + while (RT_TRUE) + { + rt_hw_cpu_relax(); + } } syscallfunc_t syscallfunc = (syscallfunc_t)lwp_get_sys_api(syscallid); @@ -50,6 +48,8 @@ void syscall_handler(struct rt_hw_stack_frame *regs) #if DBG_LVL >= DBG_INFO syscall_name = lwp_get_syscall_name(syscallid); +#else + RT_UNUSED(syscall_name); #endif LOG_I("[0x%lx] %s(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)", rt_thread_self(), syscall_name, @@ -59,4 +59,3 @@ void syscall_handler(struct rt_hw_stack_frame *regs) regs->epc += 4; // skip ecall instruction LOG_I("[0x%lx] %s ret: 0x%lx", rt_thread_self(), syscall_name, regs->a0); } -#endif /* RT_USING_SMART */ diff --git a/libcpu/risc-v/common/trap.c b/libcpu/risc-v/common/trap.c new file mode 100644 index 00000000000..23b58ea128f --- /dev/null +++ b/libcpu/risc-v/common/trap.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-12-08 RT-Thread first version + * 2025-04-20 GuEe-GUI Port to the DM + */ + +#include +#include + +#include +#include +#include +#include +#include +#ifdef RT_USING_DM +#include +#else +#include +#endif +#ifdef RT_USING_SMART +#include +#endif + +#define DBG_TAG "libcpu.trap" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_FINSH +extern long list_thread(void); +#endif + +#ifdef RT_USING_LWP +#include +#include + +#ifdef LWP_USING_CORE_DUMP +#include +#endif + +static void _check_fault(struct rt_hw_stack_frame *regs, uint32_t pc_adj, char *info) +{ + rt_thread_t th; + rt_bool_t is_user_fault = !!(regs->xstatus & SR_PP); + + if (is_user_fault) + { + rt_kprintf("%s! pc = %p\n", info, regs->epc - pc_adj); + } + + /* User stack backtrace */ + th = rt_thread_self(); + if (th && th->lwp) + { + arch_backtrace_uthread(th); + } + + if (is_user_fault) + { + #ifdef LWP_USING_CORE_DUMP + lwp_core_dump(regs, pc_adj); + #endif + sys_exit_group(-1); + } +} + +rt_inline rt_bool_t user_fault_fixable(struct rt_hw_stack_frame *regs, rt_ubase_t xcause, rt_ubase_t tval) +{ + struct rt_lwp *lwp; + enum rt_mm_fault_op fault_op; + enum rt_mm_fault_type fault_type; + + switch (xcause) + { + case EXC_LOAD_PAGE_FAULT: + fault_op = MM_FAULT_OP_READ; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; + break; + case EXC_LOAD_ACCESS: + fault_op = MM_FAULT_OP_READ; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + case EXC_LOAD_MISALIGNED: + fault_op = MM_FAULT_OP_READ; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + case EXC_STORE_PAGE_FAULT: + fault_op = MM_FAULT_OP_WRITE; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; + break; + case EXC_STORE_ACCESS: + fault_op = MM_FAULT_OP_WRITE; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + case EXC_STORE_MISALIGNED: + fault_op = MM_FAULT_OP_WRITE; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + case EXC_INST_PAGE_FAULT: + fault_op = MM_FAULT_OP_EXECUTE; + fault_type = MM_FAULT_TYPE_GENERIC_MMU; + break; + case EXC_INST_ACCESS: + fault_op = MM_FAULT_OP_EXECUTE; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + case EXC_INST_MISALIGNED: + fault_op = MM_FAULT_OP_EXECUTE; + fault_type = MM_FAULT_TYPE_BUS_ERROR; + break; + default: + fault_op = 0; + break; + } + + if (fault_op) + { + rt_base_t saved_stat; + struct rt_aspace_fault_msg msg = + { + .fault_op = fault_op, + .fault_type = fault_type, + .fault_vaddr = (void *)tval, + }; + + lwp = lwp_self(); + + saved_stat = csr_read_clear(CSR_STATUS, SR_IE); + + if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg)) + { + csr_write(CSR_STATUS, saved_stat); + return RT_TRUE; + } + + csr_write(CSR_STATUS, saved_stat); + } + + return RT_FALSE; +} +#endif /* RT_USING_LWP */ + +#ifdef ARCH_RISCV_VECTOR +rt_inline void vector_enable(struct rt_hw_stack_frame *regs) +{ + regs->xstatus |= SR_VS_INITIAL; +} + +/** + * detect V/D support, and do not distinguish V/D instruction + */ +rt_inline rt_bool_t illegal_inst_recoverable(struct rt_hw_stack_frame *regs, rt_ubase_t tval) +{ + /* first 7 bits is opcode */ + int opcode = tval & 0x7f; + int csr = (tval & 0xfff00000) >> 20; + /* ref riscv-v-spec-1.0, [Vector Instruction Formats] */ + int width = ((tval & 0x7000) >> 12) - 1; + + switch (opcode) + { + case 0x57: /* V */ + case 0x27: /* scalar FLOAT */ + case 0x07: + case 0x73: /* CSR */ + vector_enable(regs); + return RT_TRUE; + + default: + break; + } + + return RT_FALSE; +} +#endif /* ARCH_RISCV_VECTOR */ + +/** + * this function will show registers of CPU + * + * @param regs the registers point + */ +void rt_hw_show_register(struct rt_hw_stack_frame *regs) +{ +#ifndef ARCH_RISCV_M_MODE + const char *sv_mode; + rt_ubase_t satp = csr_read(CSR_SATP); + + switch (satp & SATP_MODE_MASK) + { + case SATP_MODE_BARE: + sv_mode = "Bare"; + break; +#if __riscv_xlen == 32 + case SATP_MODE_32: + sv_mode = "Sv32"; + break; +#else + case SATP_MODE_39: + sv_mode = "Sv39"; + break; + case SATP_MODE_48: + sv_mode = "Sv48"; + break; + case SATP_MODE_57: + sv_mode = "Sv57"; + break; + case SATP_MODE_64: + sv_mode = "Sv64"; + break; +#endif /* __riscv_xlen == 32 */ + default: + sv_mode = "Reserved"; + break; + } +#endif /* !ARCH_RISCV_M_MODE */ + +#if __riscv_xlen == 64 +#define F "0x%016lx" +#elif __riscv_xlen == 32 +#define F "0x%08lx" +#else +#error "Unexpected __riscv_xlen" +#endif + rt_kprintf("Execption:\n"); + rt_kprintf("x0/zero: " F " x1/ra : " F " x2/sp : " F " x3/gp : " F "\n", 0UL, regs->user_sp_exc_stack, regs->ra, regs->gp); + rt_kprintf("x4/tp : " F " x5/t0 : " F " x6/t1 : " F " x7/t2 : " F "\n", regs->tp, regs->t0, regs->t1, regs->t2); + rt_kprintf("x8/s0 : " F " x9/s1 : " F " x10/a0 : " F " x11/a1 : " F "\n", regs->s0_fp, regs->s1, regs->a0, regs->a1); + rt_kprintf("x12/a2 : " F " x13/a3: " F " x14/a4 : " F " x15/a5 : " F "\n", regs->a2, regs->a3, regs->a4, regs->a5); +#ifndef ARCH_RISCV_32E + rt_kprintf("x16/a6 : " F " x17/a7: " F " x18/s2 : " F " x19/s3 : " F "\n", regs->a6, regs->a7, regs->s2, regs->s3); + rt_kprintf("x20/s4 : " F " x21/s5: " F " x22/s6 : " F " x23/s7 : " F "\n", regs->s4, regs->s5, regs->s6, regs->s7); + rt_kprintf("x24/s8 : " F " x25/s9: " F " x26/s10: " F " x27/s11: " F "\n", regs->s8, regs->s9, regs->s10, regs->s11); + rt_kprintf("x28/t3 : " F " x29/t4: " F " x30/t5 : " F " x31/t6 : " F "\n", regs->t3, regs->t4, regs->t5, regs->t6); +#endif /* !ARCH_RISCV_32E */ +#ifdef ARCH_RISCV_M_MODE + rt_kprintf("status : " F " (%s %s %s)\n", regs->xstatus, + (regs->xstatus & SR_IE) ? "IE" : "--", + (regs->xstatus & SR_PIE) ? "PIE" : "---", + (regs->xstatus & SR_PP) ? "PP" : "--"); +#else + rt_kprintf("status : " F " (%s %s %s %s %s)\n", regs->xstatus, + (regs->xstatus & SR_IE) ? "IE" : "--", + (regs->xstatus & SR_PIE) ? "PIE" : "---", + (regs->xstatus & SR_PP) ? "PP" : "--", + (regs->xstatus & SR_SUM) ? "SUM" : "---", + (regs->xstatus & SR_MXR) ? "MXR" : "---"); + rt_kprintf("satp : " F " (ASID: " F ", %s)\n", satp, (satp >> SATP_ASID_SHIFT) & SATP_ASID_MASK, sv_mode); +#endif + rt_kprintf("cause : " F "\n", regs->xcause); + rt_kprintf("pc : " F "\n", regs->epc); +#undef F +} + +static const char * const irq_name[] = +{ + [IRQ_S_SOFT] = "Software Interrupt (User)", + [IRQ_VS_SOFT] = "Software Interrupt (Supervisor)", + [IRQ_M_SOFT] = "Software Interrupt (Machine)", + [IRQ_S_TIMER] = "Timer Interrupt (User)", + [IRQ_VS_TIMER] = "Timer Interrupt (Supervisor)", + [IRQ_M_TIMER] = "Timer Interrupt (Machine)", + [IRQ_S_EXT] = "External Interrupt (User)", + [IRQ_VS_EXT] = "External Interrupt (Supervisor)", + [IRQ_M_EXT] = "External Interrupt (Machine)", + [IRQ_S_GEXT] = "External Interrupt (Supervisor Guest)", + [IRQ_PMU_OVF] = "Performance Monitor Unit Overflow", +}; + +static const char * const exception_name[] = +{ + [EXC_INST_MISALIGNED] = "INST Misaligned", + [EXC_INST_ACCESS] = "INST Access", + [EXC_INST_ILLEGAL] = "INST Illegal", + [EXC_BREAKPOINT] = "Breakpoint", + [EXC_LOAD_MISALIGNED] = "Load Misaligned", + [EXC_LOAD_ACCESS] = "Load Access", + [EXC_STORE_MISALIGNED] = "Store Misaligned", + [EXC_STORE_ACCESS] = "Store Access", + [EXC_SYSCALL] = "Syscall", + [EXC_HYPERVISOR_SYSCALL] = "Hypervisor Syscall", + [EXC_SUPERVISOR_SYSCALL] = "Supervisor Syscall", + [EXC_INST_PAGE_FAULT] = "INST Page Fault", + [EXC_LOAD_PAGE_FAULT] = "Load Page Fault", + [EXC_STORE_PAGE_FAULT] = "Store Page Fault", + [EXC_INST_GUEST_PAGE_FAULT] = "INST Guest Page Fault", + [EXC_LOAD_GUEST_PAGE_FAULT] = "Load Guest Page Fault", + [EXC_VIRTUAL_INST_FAULT] = "Virtual INST Fault", + [EXC_STORE_GUEST_PAGE_FAULT] = "Store Guest Page Fault", +}; + +void rt_hw_trap(struct rt_hw_stack_frame *regs) +{ + rt_ubase_t xcause = regs->xcause; + rt_ubase_t tval = csr_read_clear(CSR_TVAL, 0); + + /* IRQ */ + if (xcause & CAUSE_IRQ_FLAG) + { + rt_interrupt_enter(); + + xcause &= ~CAUSE_IRQ_FLAG; + + switch (xcause) + { + case RV_IRQ_TIMER: + riscv_timer_isr(); + break; + + case RV_IRQ_SOFT: + case RV_IRQ_EXT: + #ifdef RT_USING_DM + rt_pic_do_traps(); + #else + rt_hw_interrupt_handle(xcause, regs); + #endif + break; + + default: + LOG_E("Unhandle IRQ: (%d) %s", xcause, + xcause >= sizeof(irq_name) / sizeof(irq_name[0]) ? "Reserved" : irq_name[xcause]); + break; + } + + rt_interrupt_leave(); + } + /* Execption */ + else + { + struct rt_hw_backtrace_frame frame; + + switch (xcause) + { + case EXC_INST_ILLEGAL: + #ifdef ARCH_RISCV_VECTOR + if (!(regs->xstatus & SR_VS)) + { + if (illegal_inst_recoverable(regs, tval)) + { + return; + } + } + #endif /* ARCH_RISCV_VECTOR */ + break; + + case EXC_LOAD_GUEST_PAGE_FAULT: + case EXC_STORE_GUEST_PAGE_FAULT: + #ifdef RT_USING_SMART + if ((regs->xstatus & SR_PP) && + (tval >= USER_VADDR_START && tval < USER_VADDR_TOP)) + { + if (user_fault_fixable(regs, xcause, tval)) + { + return; + } + } + #endif /* RT_USING_SMART */ + + default: + LOG_E("Unhandle Execption: (%d) %s, TVAL = %p", xcause, + xcause >= sizeof(exception_name) / sizeof(exception_name[0]) ? "Reserved" : exception_name[xcause], + tval); + } + + rt_hw_show_register(regs); + + if (rt_thread_self()) + { + LOG_E("current thread: %s\n", rt_thread_self()->parent.name); + + #ifdef RT_USING_FINSH + list_thread(); + #endif + + #ifdef RT_USING_LWP + _check_fault(regs, 0, "user fault"); + #endif + } + + frame.fp = regs->s0_fp; + frame.pc = regs->epc; + rt_backtrace_frame(rt_thread_self(), &frame); + rt_hw_cpu_shutdown(); + } +} diff --git a/libcpu/risc-v/common/trap_common.c b/libcpu/risc-v/common/trap_common.c deleted file mode 100644 index 0dbd7f2c75c..00000000000 --- a/libcpu/risc-v/common/trap_common.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include "riscv-ops.h" -#include "rt_hw_stack_frame.h" - -#define ISR_NUMBER 32 -static volatile rt_hw_stack_frame_t *s_stack_frame; -static struct rt_irq_desc rv32irq_table[ISR_NUMBER]; -void rt_show_stack_frame(void); - -/** - * Temporary interrupt entry function - * - * @param mcause Machine Cause Register - * @return RT_NULL - */ -rt_weak rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t mcause) -{ - rt_kprintf("UN-handled interrupt %d occurred!!!\n", mcause); - return RT_NULL; -} - -/** - * Interrupt entry function initialization - */ -rt_weak void rt_hw_interrupt_init(void) -{ - int idx = 0; - - for (idx = 0; idx < ISR_NUMBER; idx++) - { - rv32irq_table[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; - rv32irq_table[idx].param = RT_NULL; - } -} - -/** - * Break Entry Function Binding - * - * @param vector interrupt number - * @param handler Break-in function requiring binding - * @param param NULL - * @param name NULL - * @return old handler - */ -rt_weak rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, - void *param, const char *name) -{ - rt_isr_handler_t old_handler = RT_NULL; - - if(vector < ISR_NUMBER) - { - old_handler = rv32irq_table[vector].handler; - if (handler != RT_NULL) - { - rv32irq_table[vector].handler = (rt_isr_handler_t)handler; - rv32irq_table[vector].param = param; - } - } - - return old_handler; -} - -/** - * Query and Distribution Entry for Exception and Interrupt Sources - * - * @param mcause Machine Cause Register - */ -rt_weak void rt_rv32_system_irq_handler(rt_uint32_t mcause) -{ - rt_uint32_t mscratch = read_csr(0x340); - rt_uint32_t irq_id = (mcause & 0x1F); - rt_uint32_t exception = !(mcause & 0x80000000); - if(exception) - { - s_stack_frame = (volatile rt_hw_stack_frame_t *)(uintptr_t)mscratch; - rt_show_stack_frame(); - } - else - { - rv32irq_table[irq_id].handler(irq_id, rv32irq_table[irq_id].param); - } -} - -/** - * Register Print on Exception - */ -rt_weak void rt_show_stack_frame(void) -{ - rt_kprintf("Stack frame:\r\n----------------------------------------\r\n"); - rt_kprintf("ra : 0x%08x\r\n", s_stack_frame->ra); - rt_kprintf("mstatus : 0x%08x\r\n", read_csr(0x300));//mstatus - rt_kprintf("t0 : 0x%08x\r\n", s_stack_frame->t0); - rt_kprintf("t1 : 0x%08x\r\n", s_stack_frame->t1); - rt_kprintf("t2 : 0x%08x\r\n", s_stack_frame->t2); - rt_kprintf("a0 : 0x%08x\r\n", s_stack_frame->a0); - rt_kprintf("a1 : 0x%08x\r\n", s_stack_frame->a1); - rt_kprintf("a2 : 0x%08x\r\n", s_stack_frame->a2); - rt_kprintf("a3 : 0x%08x\r\n", s_stack_frame->a3); - rt_kprintf("a4 : 0x%08x\r\n", s_stack_frame->a4); - rt_kprintf("a5 : 0x%08x\r\n", s_stack_frame->a5); -#ifndef __riscv_32e - rt_kprintf("a6 : 0x%08x\r\n", s_stack_frame->a6); - rt_kprintf("a7 : 0x%08x\r\n", s_stack_frame->a7); - rt_kprintf("t3 : 0x%08x\r\n", s_stack_frame->t3); - rt_kprintf("t4 : 0x%08x\r\n", s_stack_frame->t4); - rt_kprintf("t5 : 0x%08x\r\n", s_stack_frame->t5); - rt_kprintf("t6 : 0x%08x\r\n", s_stack_frame->t6); -#endif -} diff --git a/libcpu/risc-v/vector/SConscript b/libcpu/risc-v/common/vector/SConscript similarity index 100% rename from libcpu/risc-v/vector/SConscript rename to libcpu/risc-v/common/vector/SConscript diff --git a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h b/libcpu/risc-v/common/vector/rvv-1.0/rvv_context.h similarity index 64% rename from libcpu/risc-v/vector/rvv-1.0/rvv_context.h rename to libcpu/risc-v/common/vector/rvv-1.0/rvv_context.h index 4466b3aeff1..22c855aa5bf 100644 --- a/libcpu/risc-v/vector/rvv-1.0/rvv_context.h +++ b/libcpu/risc-v/common/vector/rvv-1.0/rvv_context.h @@ -11,6 +11,8 @@ #ifndef __RVV_CONTEXT_1_0_H__ #define __RVV_CONTEXT_1_0_H__ +#include + #if defined(ARCH_VECTOR_VLEN_128) #define CTX_VECTOR_REGS 64 #elif defined(ARCH_VECTOR_VLEN_256) @@ -29,16 +31,16 @@ * ================================== */ -#define VEC_FRAME_VSTART (0 * REGBYTES) -#define VEC_FRAME_VTYPE (1 * REGBYTES) -#define VEC_FRAME_VL (2 * REGBYTES) -#define VEC_FRAME_VCSR (3 * REGBYTES) -#define VEC_FRAME_V0 (4 * REGBYTES) +#define VEC_FRAME_VSTART (0 * SZREG) +#define VEC_FRAME_VTYPE (1 * SZREG) +#define VEC_FRAME_VL (2 * SZREG) +#define VEC_FRAME_VCSR (3 * SZREG) +#define VEC_FRAME_V0 (4 * SZREG) .macro GET_VEC_FRAME_LEN, xreg - csrr \xreg, vlenb + csrr \xreg, CSR_VLENB slli \xreg, \xreg, 5 - addi \xreg, \xreg, 4 * REGBYTES + addi \xreg, \xreg, 4 * SZREG .endm /** @@ -50,19 +52,21 @@ .macro SAVE_VECTOR, dst mv t1, \dst - csrr t0, vstart - STORE t0, VEC_FRAME_VSTART(t1) - csrr t0, vtype - STORE t0, VEC_FRAME_VTYPE(t1) - csrr t0, vl - STORE t0, VEC_FRAME_VL(t1) - csrr t0, vcsr - STORE t0, VEC_FRAME_VCSR(t1) + csrr t0, CSR_VSTART + REG_S t0, VEC_FRAME_VSTART(t1) + csrr t0, CSR_VTYPE + REG_S t0, VEC_FRAME_VTYPE(t1) + csrr t0, CSR_VL + REG_S t0, VEC_FRAME_VL(t1) + csrr t0, CSR_VCSR + REG_S t0, VEC_FRAME_VCSR(t1) addi t1, t1, VEC_FRAME_V0 - // config vector setting, - // t2 is updated to length of a vector group in bytes + /* + * config vector setting, + * t2 is updated to length of a vector group in bytes + */ VEC_CONFIG_SETVLI(t2, x0, VEC_IMM_SEW_8, VEC_IMM_LMUL_8) vse8.v v0, (t1) @@ -81,7 +85,7 @@ * */ .macro RESTORE_VECTOR, dst - // restore vector registers first since it will modify vector states + /* Restore vector registers first since it will modify vector states */ mv t0, \dst addi t1, t0, VEC_FRAME_V0 @@ -97,16 +101,16 @@ mv t1, t0 - LOAD t0, VEC_FRAME_VSTART(t1) - csrw vstart, t0 - LOAD t0, VEC_FRAME_VCSR(t1) - csrw vcsr, t0 + REG_L t0, VEC_FRAME_VSTART(t1) + csrw CSR_VSTART, t0 + REG_L t0, VEC_FRAME_VCSR(t1) + csrw CSR_VCSR, t0 - LOAD t0, VEC_FRAME_VTYPE(t1) - LOAD t3, VEC_FRAME_VL(t1) + REG_L t0, VEC_FRAME_VTYPE(t1) + REG_L t3, VEC_FRAME_VL(t1) VEC_CONFIG_SET_VL_VTYPE(t3, t0) .endm -#endif +#endif /* __ASSEMBLY__ */ #endif /* __RVV_CONTEXT_H__ */ diff --git a/libcpu/risc-v/vector/rvv-1.0/vector_encoding.h b/libcpu/risc-v/common/vector/rvv-1.0/vector_encoding.h similarity index 53% rename from libcpu/risc-v/vector/rvv-1.0/vector_encoding.h rename to libcpu/risc-v/common/vector/rvv-1.0/vector_encoding.h index 022beb0603a..6332895cbb3 100644 --- a/libcpu/risc-v/vector/rvv-1.0/vector_encoding.h +++ b/libcpu/risc-v/common/vector/rvv-1.0/vector_encoding.h @@ -12,31 +12,24 @@ #ifndef __VECTOR_ENCODING_1_0_H__ #define __VECTOR_ENCODING_1_0_H__ -/* mstatus/sstatus */ -#define MSTATUS_VS 0x00000600 -#define SSTATUS_VS 0x00000600 /* Vector Status */ -#define SSTATUS_VS_INITIAL 0x00000200 -#define SSTATUS_VS_CLEAN 0x00000400 -#define SSTATUS_VS_DIRTY 0x00000600 - #ifdef __ASSEMBLY__ /** * assembler names used for vset{i}vli vtypei immediate */ -#define VEC_IMM_SEW_8 e8 -#define VEC_IMM_SEW_16 e16 -#define VEC_IMM_SEW_32 e32 -#define VEC_IMM_SEW_64 e64 +#define VEC_IMM_SEW_8 e8 +#define VEC_IMM_SEW_16 e16 +#define VEC_IMM_SEW_32 e32 +#define VEC_IMM_SEW_64 e64 /* group setting, encoding by multiplier */ -#define VEC_IMM_LMUL_F8 mf8 -#define VEC_IMM_LMUL_F4 mf4 -#define VEC_IMM_LMUL_F2 mf2 -#define VEC_IMM_LMUL_1 m1 -#define VEC_IMM_LMUL_2 m2 -#define VEC_IMM_LMUL_4 m4 -#define VEC_IMM_LMUL_8 m8 +#define VEC_IMM_LMUL_F8 mf8 +#define VEC_IMM_LMUL_F4 mf4 +#define VEC_IMM_LMUL_F2 mf2 +#define VEC_IMM_LMUL_1 m1 +#define VEC_IMM_LMUL_2 m2 +#define VEC_IMM_LMUL_4 m4 +#define VEC_IMM_LMUL_8 m8 /* TAIL & MASK agnostic bits */ #define VEC_IMM_TAIL_AGNOSTIC ta #define VEC_IMM_MASK_AGNOSTIC ma @@ -47,9 +40,9 @@ /** * configuration setting instruction */ -#define VEC_CONFIG_SETVLI(xVl, xAvl, vtype...) vsetvli xVl, xAvl, ##vtype -#define VEC_CONFIG_SET_VL_VTYPE(xVl, xVtype) vsetvl x0, xVl, xVtype +#define VEC_CONFIG_SETVLI(xVl, xAvl, vtype...) vsetvli xVl, xAvl, ##vtype +#define VEC_CONFIG_SET_VL_VTYPE(xVl, xVtype) vsetvl x0, xVl, xVtype -#endif +#endif /* __ASSEMBLY__ */ #endif /* __VECTOR_ENCODING_H__ */ diff --git a/libcpu/risc-v/common/vector_gcc.S b/libcpu/risc-v/common/vector_gcc.S new file mode 100644 index 00000000000..099dda6a3bf --- /dev/null +++ b/libcpu/risc-v/common/vector_gcc.S @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-10-02 Bernard The first version + * 2018-12-27 Jesven Add SMP schedule + * 2021-02-02 lizhirui Add userspace support + * 2021-12-24 JasonHu Add user setting save/restore + * 2022-10-22 Shell Support kernel mode RVV; + * Rewrite trap handling routine + * 2025-04-20 GuEe-GUI Support SMP + */ + +#include +#include + + .section ".text","ax" + .align 2 +START_POINT(system_vectors) + /* Distingush exception from kernel or user */ + csrrw sp, CSR_SCRATCH, sp + bnez sp, _save_context + + /* + * BE REALLY careful with xscratch, + * if it's wrong, we could looping here forever + * or accessing random memory and seeing things totally + * messy after a long time and don't even know why + */ +_from_kernel: + csrr sp, CSR_SCRATCH + j _save_context + +_save_context: + SAVE_ALL + + /* Clear xscratch to say 'now in kernel mode' */ + csrw CSR_SCRATCH, zero + + LOAD_GLOBAL_POINTER + + /* Now we are ready to enter interrupt / excepiton handler */ +#ifdef RT_USING_SMART +_distinguish_syscall: + csrr t0, CSR_CAUSE + li t1, EXC_SYSCALL + bne t0, t1, _handle_interrupt_and_exception + + call syscall_entry + /* Syscall never return here */ +#endif /* RT_USING_SMART */ + +_handle_interrupt_and_exception: + mv a0, sp + call rt_hw_trap + +_interrupt_exit: +#ifdef RT_USING_SMP + mv a0, sp + call rt_scheduler_do_irq_switch + j rt_hw_resume_kernel +#else + la s0, rt_thread_switch_interrupt_flag + lw s1, 0(s0) + beqz s1, _resume_execution + sw zero, 0(s0) + +_context_switch: + la t0, rt_interrupt_from_thread + REG_L a0, 0(t0) + la t0, rt_interrupt_to_thread + REG_L a1, 0(t0) + csrr t0, CSR_STATUS + andi t0, t0, ~SR_PIE + csrw CSR_STATUS, t0 + jal rt_hw_context_switch +#endif /* RT_USING_SMP */ + +_resume_execution: +#ifdef RT_USING_SMART + REG_L t0, FRAME_OFF_XSTATUS(sp) + andi t0, t0, SR_PP + bnez t0, rt_hw_resume_kernel + call arch_ret_to_user +#endif /* RT_USING_SMART */ + + j rt_hw_resume_kernel +START_POINT_END(system_vectors) + +.globl rt_hw_resume_kernel +rt_hw_resume_kernel: + RESTORE_ALL + csrw CSR_SCRATCH, zero + XRET + + .align 2 + .weak fast_irq_vectors +START_POINT(fast_irq_vectors) + j system_vectors +START_POINT_END(fast_irq_vectors) diff --git a/libcpu/risc-v/common64/README.md b/libcpu/risc-v/common64/README.md deleted file mode 100644 index 5e7ea4bf92e..00000000000 --- a/libcpu/risc-v/common64/README.md +++ /dev/null @@ -1,52 +0,0 @@ -### RT-Thread RV64支持 - -#### 1.概述 - -该目录提供RT-Thread标准版及SMART版本对rv64体系结构支持,其中包括: - -| 文件名 | 文件内容 | 参考标准 | -| :---------------: | :------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| atomic_rv64.c | 原子操作实现接口 | "A" Extension for Atomic Instructions, Version 2.1 | -| context_gcc.S | 线程上下文切换 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| cpuport_gcc.S | 线程统一入口 | | -| cpuport.c | 线程栈初始化 | | -| cpuport.h | 通用寄存器、浮点、向量寄存器个数定义,内存屏障接口 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| interrupt_gcc.S | 异常/中断处理、全局中断使能/关闭 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| io.h | 以字节、字、双字读、写IO地址接口 | | -| encoding.h | CSR寄存器定义 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| vector_encoding.h | vector相关指令定义 | RISC-V "V" Standard Extension for Vector Operations, Version 1.0 | -| ext_context.h | 浮点/向量上下文保存与恢复 | RISC-V "V" Standard Extension for Vector Operations, Version 1.0 "F" Extension for Single-Precision Floating-Point Version 2.2 | -| mmu.c | rv64 sv39 mmu管理接口 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| mmu.h | rv64 sv39 mmu页表相关定义 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| asid.c | rv64 mmu asid支持 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| riscv_mmu.c | 使能/关闭S态访问用户态页表 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| sbi.c | 通过ecall调用SBI相关信息接口 | RISC-V Supervisor Binary Interface Specification Version 1.0 | -| sbi.h | SBI spec相关接口定义 | RISC-V Supervisor Binary Interface Specification Version 1.0 | -| stack.h | 线程栈数据定义 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| stackframe.h | 线程上下文保存/恢复 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| syscall_c.c | 系统调用处理 | | -| tick.c | S态时钟初始化及中断处理 | | -| tlb.h | tlb刷新/无效接口 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | -| trap.c | 异常/中断处理,包括中断分发及用户态异常处理 | The RISC-V Instruction Set Manual Volume II: privileged supervisor-level ISA version 1.12 | - -#### 2.运行模式配置 - -| 选项 | 默认值 | 说明 | -| --------------- | --- | ---------------------------------------------------------------------------------------------------- | -| RISCV_VIRT64_S_MODE | 打开 | 系统启动后是否运行在S态,关闭时系统将运行在M态;目前系统存在bug尚不可直接运行在M态,故此开关必须打开 | -| RT_USING_SMART | 关闭 | 是否开启RTThread SMART版本,开启后系统运行在S+U态,且会开启MMU页表(satp);关闭时系统仅运行在S态,MMU关闭(satp为bare translation) | -| ARCH_USING_ASID | 关闭 | MMU是否支持asid | - -#### 3.移植指南 - -(1)增加新的CPU支持 - -创建`libcpu/risc-v//`新目录,同时在`libcpu/risc-v/SConscript`中增加该CPU。 - -(2)PLIC中断控制器支持 - -`libcpu/risc-v/virt64/plic.[c|h]`提供了符合《RISC-V Platform-Level Interrupt Controller Specification version 1.0.0 》标准的PLIC中断控制器驱动代码,可作为移植参考。 - -(3)串口uart支持 - -目前串口驱动在各bsp目录下,可参考`bsp/qemu-virt64-riscv/driver/drv_uart.[c|h]` \ No newline at end of file diff --git a/libcpu/risc-v/common64/SConscript b/libcpu/risc-v/common64/SConscript deleted file mode 100644 index 08acc79944a..00000000000 --- a/libcpu/risc-v/common64/SConscript +++ /dev/null @@ -1,12 +0,0 @@ -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') -CPPPATH = [cwd] - -if not GetDepend('ARCH_USING_ASID'): - SrcRemove(src, ['asid.c']) - -group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/libcpu/risc-v/common64/asid.c b/libcpu/risc-v/common64/asid.c deleted file mode 100644 index c8ed61eb67c..00000000000 --- a/libcpu/risc-v/common64/asid.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024-07-12 RT-Thread first version. - */ -#define DBG_TAG "hw.asid" -#define DBG_LVL DBG_INFO -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static rt_uint8_t ASID_BITS = 0; -static rt_uint32_t next_asid; -static rt_uint64_t global_asid_generation; -#define ASID_MASK ((1 << ASID_BITS) - 1) -#define ASID_FIRST_GENERATION (1 << ASID_BITS) -#define MAX_ASID ASID_FIRST_GENERATION - -void rt_hw_asid_init(void) -{ - rt_uint64_t satp_reg = read_csr(satp); - satp_reg |= (((rt_uint64_t)0xffff) << PPN_BITS); - write_csr(satp, satp_reg); - __asm__ volatile("sfence.vma x0, x0"); - unsigned short valid_asid_bit = ((read_csr(satp) >> PPN_BITS) & 0xffff); - - // The maximal value of ASIDLEN, is 9 for Sv32 or 16 for Sv39, Sv48, and Sv57 - for (unsigned i = 0; i < 16; i++) - { - if (!(valid_asid_bit & 0x1)) - { - break; - } - - valid_asid_bit >>= 1; - ASID_BITS++; - } - - global_asid_generation = ASID_FIRST_GENERATION; - next_asid = 1; -} - -static rt_uint64_t _asid_acquire(rt_aspace_t aspace) -{ - if ((aspace->asid ^ global_asid_generation) >> ASID_BITS) // not same generation - { - if (next_asid != MAX_ASID) - { - aspace->asid = global_asid_generation | next_asid; - next_asid++; - } - else - { - // scroll to next generation - global_asid_generation += ASID_FIRST_GENERATION; - next_asid = 1; - rt_hw_tlb_invalidate_all_local(); - - aspace->asid = global_asid_generation | next_asid; - next_asid++; - } - } - - return aspace->asid & ASID_MASK; -} - -void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl) -{ - rt_uint64_t asid = _asid_acquire(aspace); - write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | - (asid << PPN_BITS) | - ((rt_ubase_t)pgtbl >> PAGE_OFFSET_BIT)); - asm volatile("sfence.vma x0,%0"::"r"(asid):"memory"); -} - diff --git a/libcpu/risc-v/common64/asm-generic.h b/libcpu/risc-v/common64/asm-generic.h deleted file mode 100644 index 625af2ce1a3..00000000000 --- a/libcpu/risc-v/common64/asm-generic.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2006-2023 RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2023-03-12 WangXiaoyao the first version - */ -#ifndef __ASM_GENERIC_H__ -#define __ASM_GENERIC_H__ - -/* use to mark a start point where every task start from */ -#define START_POINT(funcname) \ - .global funcname; \ - .type funcname, %function; \ - funcname: \ - .cfi_sections .debug_frame, .eh_frame; \ - .cfi_startproc; \ - .cfi_undefined ra - -#define START_POINT_END(name) \ - .cfi_endproc; \ - .size name, .-name; - -#endif /* __ASM_GENERIC_H__ */ diff --git a/libcpu/risc-v/common64/context_gcc.S b/libcpu/risc-v/common64/context_gcc.S deleted file mode 100644 index ed216716b09..00000000000 --- a/libcpu/risc-v/common64/context_gcc.S +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting implementation - * 2018/12/27 Jesven Add SMP support - * 2021/02/02 lizhirui Add userspace support - * 2022/10/22 Shell Support User mode RVV; - * Trimming process switch context - */ - -#include "cpuport.h" -#include "stackframe.h" -#define _REG_IDX(name) RT_HW_SWITCH_CONTEXT_##name -#define REG_IDX(name) _REG_IDX(name) - -.macro SAVE_REG reg, index - STORE \reg, \index*REGBYTES(sp) -.endm - -.macro LOAD_REG reg, index - LOAD \reg, \index*REGBYTES(sp) -.endm - -.macro RESERVE_CONTEXT - addi sp, sp, -(RT_HW_SWITCH_CONTEXT_SIZE * REGBYTES) - SAVE_REG tp, REG_IDX(TP) - SAVE_REG ra, REG_IDX(RA) - SAVE_REG s0, REG_IDX(S0) - SAVE_REG s1, REG_IDX(S1) - SAVE_REG s2, REG_IDX(S2) - SAVE_REG s3, REG_IDX(S3) - SAVE_REG s4, REG_IDX(S4) - SAVE_REG s5, REG_IDX(S5) - SAVE_REG s6, REG_IDX(S6) - SAVE_REG s7, REG_IDX(S7) - SAVE_REG s8, REG_IDX(S8) - SAVE_REG s9, REG_IDX(S9) - SAVE_REG s10, REG_IDX(S10) - SAVE_REG s11, REG_IDX(S11) - csrr s11, sstatus - li s10, (SSTATUS_SPP) - or s11, s11, s10 - SAVE_REG s11, REG_IDX(SSTATUS) -.endm - -.macro RESTORE_CONTEXT - LOAD_REG s11, REG_IDX(SSTATUS) - csrw sstatus, s11 - LOAD_REG s11, REG_IDX(S11) - LOAD_REG s10, REG_IDX(S10) - LOAD_REG s9, REG_IDX(S9) - LOAD_REG s8, REG_IDX(S8) - LOAD_REG s7, REG_IDX(S7) - LOAD_REG s6, REG_IDX(S6) - LOAD_REG s5, REG_IDX(S5) - LOAD_REG s4, REG_IDX(S4) - LOAD_REG s3, REG_IDX(S3) - LOAD_REG s2, REG_IDX(S2) - LOAD_REG s1, REG_IDX(S1) - LOAD_REG s0, REG_IDX(S0) - LOAD_REG ra, REG_IDX(RA) - LOAD_REG tp, REG_IDX(TP) - addi sp, sp, RT_HW_SWITCH_CONTEXT_SIZE * REGBYTES - csrw sepc, ra -.endm - -/* - * void rt_hw_context_switch_to(rt_ubase_t to); - * - * a0 --> to SP pointer - */ -.globl rt_hw_context_switch_to -rt_hw_context_switch_to: - LOAD sp, (a0) - - call rt_thread_self - mv s1, a0 - - #ifdef RT_USING_SMART - call lwp_aspace_switch - #endif - - RESTORE_CONTEXT - sret - -/* - * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); - * - * a0 --> from SP pointer - * a1 --> to SP pointer - * - * It should only be used on local interrupt disable - */ -.globl rt_hw_context_switch -rt_hw_context_switch: - RESERVE_CONTEXT - STORE sp, (a0) - - // restore to thread SP - LOAD sp, (a1) - - // restore Address Space - call rt_thread_self - mv s1, a0 - - #ifdef RT_USING_SMART - call lwp_aspace_switch - #endif - - RESTORE_CONTEXT - sret diff --git a/libcpu/risc-v/common64/cpuport.c b/libcpu/risc-v/common64/cpuport.c deleted file mode 100644 index 76ae7d38271..00000000000 --- a/libcpu/risc-v/common64/cpuport.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting code. - * 2021-02-11 lizhirui add gp support - * 2021-11-19 JasonHu add fpu support - */ - -#include -#include - -#include "cpuport.h" -#include "stack.h" -#include -#include - -#ifdef ARCH_RISCV_FPU - #define K_SSTATUS_DEFAULT_BASE (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM | SSTATUS_FS) -#else - #define K_SSTATUS_DEFAULT_BASE (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM) -#endif - -#ifdef ARCH_RISCV_VECTOR - #define K_SSTATUS_DEFAULT (K_SSTATUS_DEFAULT_BASE | SSTATUS_VS) -#else - #define K_SSTATUS_DEFAULT K_SSTATUS_DEFAULT_BASE -#endif -#ifdef RT_USING_SMART -#include -#endif - -/** - * @brief from thread used interrupt context switch - * - */ -volatile rt_ubase_t rt_interrupt_from_thread = 0; -/** - * @brief to thread used interrupt context switch - * - */ -volatile rt_ubase_t rt_interrupt_to_thread = 0; -/** - * @brief flag to indicate context switch in interrupt or not - * - */ -volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; - -void *_rt_hw_stack_init(rt_ubase_t *sp, rt_ubase_t ra, rt_ubase_t sstatus) -{ - rt_hw_switch_frame_t frame = (rt_hw_switch_frame_t) - ((rt_ubase_t)sp - sizeof(struct rt_hw_switch_frame)); - - rt_memset(frame, 0, sizeof(struct rt_hw_switch_frame)); - - frame->regs[RT_HW_SWITCH_CONTEXT_RA] = ra; - frame->regs[RT_HW_SWITCH_CONTEXT_SSTATUS] = sstatus; - - return (void *)frame; -} - -int rt_hw_cpu_id(void) -{ - return 0; -} - -/** - * This function will initialize thread stack, we assuming - * when scheduler restore this new thread, context will restore - * an entry to user first application - * - * s0-s11, ra, sstatus, a0 - * @param tentry the entry of thread - * @param parameter the parameter of entry - * @param stack_addr the beginning stack address - * @param texit the function will be called when thread exit - * - * @return stack address - */ -rt_uint8_t *rt_hw_stack_init(void *tentry, - void *parameter, - rt_uint8_t *stack_addr, - void *texit) -{ - rt_ubase_t *sp = (rt_ubase_t *)stack_addr; - // we use a strict alignment requirement for Q extension - sp = (rt_ubase_t *)RT_ALIGN_DOWN((rt_ubase_t)sp, 16); - - (*--sp) = (rt_ubase_t)tentry; - (*--sp) = (rt_ubase_t)parameter; - (*--sp) = (rt_ubase_t)texit; - --sp; /* alignment */ - - /* compatible to RESTORE_CONTEXT */ - extern void _rt_thread_entry(void); - return (rt_uint8_t *)_rt_hw_stack_init(sp, (rt_ubase_t)_rt_thread_entry, K_SSTATUS_DEFAULT); -} - -/* - * #ifdef RT_USING_SMP - * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread); - * #else - * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to); - * #endif - */ -#ifndef RT_USING_SMP -void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread) -{ - if (rt_thread_switch_interrupt_flag == 0) - rt_interrupt_from_thread = from; - - rt_interrupt_to_thread = to; - rt_thread_switch_interrupt_flag = 1; - - return; -} -#endif /* end of RT_USING_SMP */ - -/** shutdown CPU */ -void rt_hw_cpu_shutdown(void) -{ - rt_uint32_t level; - rt_kprintf("shutdown...\n"); - - level = rt_hw_interrupt_disable(); - - sbi_shutdown(); - - while (1) - ; -} - -void rt_hw_set_process_id(int pid) -{ - // TODO -} diff --git a/libcpu/risc-v/common64/cpuport.h b/libcpu/risc-v/common64/cpuport.h deleted file mode 100644 index 293f681c971..00000000000 --- a/libcpu/risc-v/common64/cpuport.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018-10-03 Bernard The first version - */ - -#ifndef CPUPORT_H__ -#define CPUPORT_H__ - -#include -#include - -#ifndef __ASSEMBLY__ - -#ifdef RT_USING_SMP -typedef union { - unsigned long slock; - struct __arch_tickets { - unsigned short owner; - unsigned short next; - } tickets; -} rt_hw_spinlock_t; -#endif - -#include - -rt_inline void rt_hw_dsb(void) -{ - __asm__ volatile("fence":::"memory"); -} - -rt_inline void rt_hw_dmb(void) -{ - __asm__ volatile("fence":::"memory"); -} - -rt_inline void rt_hw_isb(void) -{ - __asm__ volatile(OPC_FENCE_I:::"memory"); -} - -int rt_hw_cpu_id(void); - -#endif - -#endif -#ifdef RISCV_U_MODE -#define RISCV_USER_ENTRY 0xFFFFFFE000000000ULL -#endif diff --git a/libcpu/risc-v/common64/cpuport_gcc.S b/libcpu/risc-v/common64/cpuport_gcc.S deleted file mode 100644 index 5361646753f..00000000000 --- a/libcpu/risc-v/common64/cpuport_gcc.S +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-10-19 RT-Thread the first version - */ - -#include "cpuport.h" -#include "stackframe.h" -#include "asm-generic.h" - -START_POINT(_rt_thread_entry) - LOAD ra, REGBYTES(sp) /* thread exit */ - addi sp, sp, 2 * REGBYTES - LOAD a0, (sp) /* parameter */ - LOAD t0, REGBYTES(sp) /* tentry */ - addi sp, sp, 2 * REGBYTES - mv s1, ra - jalr t0 - jalr s1 - j . /* never here */ -START_POINT_END(_rt_thread_entry) diff --git a/libcpu/risc-v/common64/encoding.h b/libcpu/risc-v/common64/encoding.h deleted file mode 100644 index 7e906fedd83..00000000000 --- a/libcpu/risc-v/common64/encoding.h +++ /dev/null @@ -1,1348 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - */ -// See LICENSE for license details. - -#ifndef RISCV_CSR_ENCODING_H -#define RISCV_CSR_ENCODING_H - -#include - -#ifdef ARCH_RISCV_VECTOR -#include "vector_encoding.h" - -#else -#define SSTATUS_VS 0 /* fallback */ -#endif /* ARCH_RISCV_VECTOR */ - -#define MSTATUS_UIE 0x00000001 -#define MSTATUS_SIE 0x00000002 -#define MSTATUS_HIE 0x00000004 -#define MSTATUS_MIE 0x00000008 -#define MSTATUS_UPIE 0x00000010 -#define MSTATUS_SPIE 0x00000020 -#define MSTATUS_HPIE 0x00000040 -#define MSTATUS_MPIE 0x00000080 -#define MSTATUS_SPP 0x00000100 -#define MSTATUS_HPP 0x00000600 -#define MSTATUS_MPP 0x00001800 -#define MSTATUS_FS 0x00006000 -#define MSTATUS_XS 0x00018000 -#define MSTATUS_MPRV 0x00020000 -#define MSTATUS_PUM 0x00040000 -#define MSTATUS_MXR 0x00080000 -#define MSTATUS_VM 0x1F000000 -#define MSTATUS32_SD 0x80000000 -#define MSTATUS64_SD 0x8000000000000000 - -#define SSTATUS_UIE 0x00000001 -#define SSTATUS_SIE 0x00000002 -#define SSTATUS_UPIE 0x00000010 -#define SSTATUS_SPIE 0x00000020 -#define SSTATUS_SPP 0x00000100 -#define SSTATUS_FS 0x00006000 /* Floating-point Status */ -#define SSTATUS_FS_INITIAL 0x00002000 -#define SSTATUS_FS_CLEAN 0x00004000 -#define SSTATUS_FS_DIRTY 0x00006000 -#define SSTATUS_XS 0x00018000 -#define SSTATUS_SUM 0x00040000 -#define SSTATUS32_SD 0x80000000 -#define SSTATUS64_SD 0x8000000000000000 - -#define DCSR_XDEBUGVER (3U<<30) -#define DCSR_NDRESET (1<<29) -#define DCSR_FULLRESET (1<<28) -#define DCSR_EBREAKM (1<<15) -#define DCSR_EBREAKH (1<<14) -#define DCSR_EBREAKS (1<<13) -#define DCSR_EBREAKU (1<<12) -#define DCSR_STOPCYCLE (1<<10) -#define DCSR_STOPTIME (1<<9) -#define DCSR_CAUSE (7<<6) -#define DCSR_DEBUGINT (1<<5) -#define DCSR_HALT (1<<3) -#define DCSR_STEP (1<<2) -#define DCSR_PRV (3<<0) - -#define DCSR_CAUSE_NONE 0 -#define DCSR_CAUSE_SWBP 1 -#define DCSR_CAUSE_HWBP 2 -#define DCSR_CAUSE_DEBUGINT 3 -#define DCSR_CAUSE_STEP 4 -#define DCSR_CAUSE_HALT 5 - -#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) -#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) -#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) - -#define MCONTROL_SELECT (1<<19) -#define MCONTROL_TIMING (1<<18) -#define MCONTROL_ACTION (0x3f<<12) -#define MCONTROL_CHAIN (1<<11) -#define MCONTROL_MATCH (0xf<<7) -#define MCONTROL_M (1<<6) -#define MCONTROL_H (1<<5) -#define MCONTROL_S (1<<4) -#define MCONTROL_U (1<<3) -#define MCONTROL_EXECUTE (1<<2) -#define MCONTROL_STORE (1<<1) -#define MCONTROL_LOAD (1<<0) - -#define MCONTROL_TYPE_NONE 0 -#define MCONTROL_TYPE_MATCH 2 - -#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 -#define MCONTROL_ACTION_DEBUG_MODE 1 -#define MCONTROL_ACTION_TRACE_START 2 -#define MCONTROL_ACTION_TRACE_STOP 3 -#define MCONTROL_ACTION_TRACE_EMIT 4 - -#define MCONTROL_MATCH_EQUAL 0 -#define MCONTROL_MATCH_NAPOT 1 -#define MCONTROL_MATCH_GE 2 -#define MCONTROL_MATCH_LT 3 -#define MCONTROL_MATCH_MASK_LOW 4 -#define MCONTROL_MATCH_MASK_HIGH 5 - -#define MIP_SSIP (1 << IRQ_S_SOFT) -#define MIP_HSIP (1 << IRQ_H_SOFT) -#define MIP_MSIP (1 << IRQ_M_SOFT) -#define MIP_STIP (1 << IRQ_S_TIMER) -#define MIP_HTIP (1 << IRQ_H_TIMER) -#define MIP_MTIP (1 << IRQ_M_TIMER) -#define MIP_SEIP (1 << IRQ_S_EXT) -#define MIP_HEIP (1 << IRQ_H_EXT) -#define MIP_MEIP (1 << IRQ_M_EXT) - -#define SIP_SSIP MIP_SSIP /* software interrupt */ -#define SIP_STIP MIP_STIP /* timer interrupt */ -#define SIP_SEIP MIP_SEIP /* ext interrupt */ - -#define SIE_SSIE (1 << IRQ_S_SOFT) -#define SIE_STIE (1 << IRQ_S_TIMER) -#define SIE_SEIE (1 << IRQ_S_EXT) - -#define RISCV_XLEN 64 - -#define SCAUSE_INTERRUPT (1UL << (RISCV_XLEN - 1)) - -#define SCAUSE_S_SOFTWARE_INTR 1 -#define SCAUSE_S_TIMER_INTR 5 -#define SCAUSE_S_EXTERNAL_INTR 9 - -#define PRV_U 0 -#define PRV_S 1 -#define PRV_H 2 -#define PRV_M 3 - -#define VM_MBARE 0 -#define VM_MBB 1 -#define VM_MBBID 2 -#define VM_SV32 8 -#define VM_SV39 9 -#define VM_SV48 10 - -#define IRQ_S_SOFT 1 -#define IRQ_H_SOFT 2 -#define IRQ_M_SOFT 3 -#define IRQ_S_TIMER 5 -#define IRQ_H_TIMER 6 -#define IRQ_M_TIMER 7 -#define IRQ_S_EXT 9 -#define IRQ_H_EXT 10 -#define IRQ_M_EXT 11 -#define IRQ_COP 12 -#define IRQ_HOST 13 - -#define DEFAULT_RSTVEC 0x00001000 -#define DEFAULT_NMIVEC 0x00001004 -#define DEFAULT_MTVEC 0x00001010 -#define CONFIG_STRING_ADDR 0x0000100C -#define EXT_IO_BASE 0x40000000 -#define DRAM_BASE 0x80000000 - -// page table entry (PTE) fields -#define PTE_V 0x001 // Valid -#define PTE_R 0x002 // Read -#define PTE_W 0x004 // Write -#define PTE_X 0x008 // Execute -#define PTE_U 0x010 // User -#define PTE_G 0x020 // Global -#define PTE_A 0x040 // Accessed -#define PTE_D 0x080 // Dirty -#define PTE_SOFT 0x300 // Reserved for Software - -#define PTE_PPN_SHIFT 10 - -#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) - -#ifdef __riscv - -#ifdef __riscv64 -# define MSTATUS_SD MSTATUS64_SD -# define SSTATUS_SD SSTATUS64_SD -# define RISCV_PGLEVEL_BITS 9 -#else -# define MSTATUS_SD MSTATUS32_SD -# define SSTATUS_SD SSTATUS32_SD -# define RISCV_PGLEVEL_BITS 10 -#endif /* end of __riscv64 */ - -#define RISCV_PGSHIFT 12 -#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) - -#ifndef __ASSEMBLY__ - -#ifdef __GNUC__ - -#define read_csr(reg) ({ unsigned long __tmp; \ - asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ - __tmp; }) - -#define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) - -#define swap_csr(reg, val) ({ unsigned long __tmp; \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ - else \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ - __tmp; }) - -#define set_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) - -#define clear_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) - -#define rdtime() read_csr(time) -#define rdcycle() read_csr(cycle) -#define rdinstret() read_csr(instret) - -#endif /* end of __GNUC__ */ - -#endif /* end of __ASSEMBLY__ */ - -#endif /* end of __riscv */ - -#endif /* end of RISCV_CSR_ENCODING_H */ - -/* Automatically generated by parse-opcodes */ -#ifndef RISCV_ENCODING_H -#define RISCV_ENCODING_H -#define MATCH_BEQ 0x63 -#define MASK_BEQ 0x707f -#define MATCH_BNE 0x1063 -#define MASK_BNE 0x707f -#define MATCH_BLT 0x4063 -#define MASK_BLT 0x707f -#define MATCH_BGE 0x5063 -#define MASK_BGE 0x707f -#define MATCH_BLTU 0x6063 -#define MASK_BLTU 0x707f -#define MATCH_BGEU 0x7063 -#define MASK_BGEU 0x707f -#define MATCH_JALR 0x67 -#define MASK_JALR 0x707f -#define MATCH_JAL 0x6f -#define MASK_JAL 0x7f -#define MATCH_LUI 0x37 -#define MASK_LUI 0x7f -#define MATCH_AUIPC 0x17 -#define MASK_AUIPC 0x7f -#define MATCH_ADDI 0x13 -#define MASK_ADDI 0x707f -#define MATCH_SLLI 0x1013 -#define MASK_SLLI 0xfc00707f -#define MATCH_SLTI 0x2013 -#define MASK_SLTI 0x707f -#define MATCH_SLTIU 0x3013 -#define MASK_SLTIU 0x707f -#define MATCH_XORI 0x4013 -#define MASK_XORI 0x707f -#define MATCH_SRLI 0x5013 -#define MASK_SRLI 0xfc00707f -#define MATCH_SRAI 0x40005013 -#define MASK_SRAI 0xfc00707f -#define MATCH_ORI 0x6013 -#define MASK_ORI 0x707f -#define MATCH_ANDI 0x7013 -#define MASK_ANDI 0x707f -#define MATCH_ADD 0x33 -#define MASK_ADD 0xfe00707f -#define MATCH_SUB 0x40000033 -#define MASK_SUB 0xfe00707f -#define MATCH_SLL 0x1033 -#define MASK_SLL 0xfe00707f -#define MATCH_SLT 0x2033 -#define MASK_SLT 0xfe00707f -#define MATCH_SLTU 0x3033 -#define MASK_SLTU 0xfe00707f -#define MATCH_XOR 0x4033 -#define MASK_XOR 0xfe00707f -#define MATCH_SRL 0x5033 -#define MASK_SRL 0xfe00707f -#define MATCH_SRA 0x40005033 -#define MASK_SRA 0xfe00707f -#define MATCH_OR 0x6033 -#define MASK_OR 0xfe00707f -#define MATCH_AND 0x7033 -#define MASK_AND 0xfe00707f -#define MATCH_ADDIW 0x1b -#define MASK_ADDIW 0x707f -#define MATCH_SLLIW 0x101b -#define MASK_SLLIW 0xfe00707f -#define MATCH_SRLIW 0x501b -#define MASK_SRLIW 0xfe00707f -#define MATCH_SRAIW 0x4000501b -#define MASK_SRAIW 0xfe00707f -#define MATCH_ADDW 0x3b -#define MASK_ADDW 0xfe00707f -#define MATCH_SUBW 0x4000003b -#define MASK_SUBW 0xfe00707f -#define MATCH_SLLW 0x103b -#define MASK_SLLW 0xfe00707f -#define MATCH_SRLW 0x503b -#define MASK_SRLW 0xfe00707f -#define MATCH_SRAW 0x4000503b -#define MASK_SRAW 0xfe00707f -#define MATCH_LB 0x3 -#define MASK_LB 0x707f -#define MATCH_LH 0x1003 -#define MASK_LH 0x707f -#define MATCH_LW 0x2003 -#define MASK_LW 0x707f -#define MATCH_LD 0x3003 -#define MASK_LD 0x707f -#define MATCH_LBU 0x4003 -#define MASK_LBU 0x707f -#define MATCH_LHU 0x5003 -#define MASK_LHU 0x707f -#define MATCH_LWU 0x6003 -#define MASK_LWU 0x707f -#define MATCH_SB 0x23 -#define MASK_SB 0x707f -#define MATCH_SH 0x1023 -#define MASK_SH 0x707f -#define MATCH_SW 0x2023 -#define MASK_SW 0x707f -#define MATCH_SD 0x3023 -#define MASK_SD 0x707f -#define MATCH_FENCE 0xf -#define MASK_FENCE 0x707f -#define MATCH_FENCE_I 0x100f -#define MASK_FENCE_I 0x707f -#define MATCH_MUL 0x2000033 -#define MASK_MUL 0xfe00707f -#define MATCH_MULH 0x2001033 -#define MASK_MULH 0xfe00707f -#define MATCH_MULHSU 0x2002033 -#define MASK_MULHSU 0xfe00707f -#define MATCH_MULHU 0x2003033 -#define MASK_MULHU 0xfe00707f -#define MATCH_DIV 0x2004033 -#define MASK_DIV 0xfe00707f -#define MATCH_DIVU 0x2005033 -#define MASK_DIVU 0xfe00707f -#define MATCH_REM 0x2006033 -#define MASK_REM 0xfe00707f -#define MATCH_REMU 0x2007033 -#define MASK_REMU 0xfe00707f -#define MATCH_MULW 0x200003b -#define MASK_MULW 0xfe00707f -#define MATCH_DIVW 0x200403b -#define MASK_DIVW 0xfe00707f -#define MATCH_DIVUW 0x200503b -#define MASK_DIVUW 0xfe00707f -#define MATCH_REMW 0x200603b -#define MASK_REMW 0xfe00707f -#define MATCH_REMUW 0x200703b -#define MASK_REMUW 0xfe00707f -#define MATCH_AMOADD_W 0x202f -#define MASK_AMOADD_W 0xf800707f -#define MATCH_AMOXOR_W 0x2000202f -#define MASK_AMOXOR_W 0xf800707f -#define MATCH_AMOOR_W 0x4000202f -#define MASK_AMOOR_W 0xf800707f -#define MATCH_AMOAND_W 0x6000202f -#define MASK_AMOAND_W 0xf800707f -#define MATCH_AMOMIN_W 0x8000202f -#define MASK_AMOMIN_W 0xf800707f -#define MATCH_AMOMAX_W 0xa000202f -#define MASK_AMOMAX_W 0xf800707f -#define MATCH_AMOMINU_W 0xc000202f -#define MASK_AMOMINU_W 0xf800707f -#define MATCH_AMOMAXU_W 0xe000202f -#define MASK_AMOMAXU_W 0xf800707f -#define MATCH_AMOSWAP_W 0x800202f -#define MASK_AMOSWAP_W 0xf800707f -#define MATCH_LR_W 0x1000202f -#define MASK_LR_W 0xf9f0707f -#define MATCH_SC_W 0x1800202f -#define MASK_SC_W 0xf800707f -#define MATCH_AMOADD_D 0x302f -#define MASK_AMOADD_D 0xf800707f -#define MATCH_AMOXOR_D 0x2000302f -#define MASK_AMOXOR_D 0xf800707f -#define MATCH_AMOOR_D 0x4000302f -#define MASK_AMOOR_D 0xf800707f -#define MATCH_AMOAND_D 0x6000302f -#define MASK_AMOAND_D 0xf800707f -#define MATCH_AMOMIN_D 0x8000302f -#define MASK_AMOMIN_D 0xf800707f -#define MATCH_AMOMAX_D 0xa000302f -#define MASK_AMOMAX_D 0xf800707f -#define MATCH_AMOMINU_D 0xc000302f -#define MASK_AMOMINU_D 0xf800707f -#define MATCH_AMOMAXU_D 0xe000302f -#define MASK_AMOMAXU_D 0xf800707f -#define MATCH_AMOSWAP_D 0x800302f -#define MASK_AMOSWAP_D 0xf800707f -#define MATCH_LR_D 0x1000302f -#define MASK_LR_D 0xf9f0707f -#define MATCH_SC_D 0x1800302f -#define MASK_SC_D 0xf800707f -#define MATCH_ECALL 0x73 -#define MASK_ECALL 0xffffffff -#define MATCH_EBREAK 0x100073 -#define MASK_EBREAK 0xffffffff -#define MATCH_URET 0x200073 -#define MASK_URET 0xffffffff -#define MATCH_SRET 0x10200073 -#define MASK_SRET 0xffffffff -#define MATCH_HRET 0x20200073 -#define MASK_HRET 0xffffffff -#define MATCH_MRET 0x30200073 -#define MASK_MRET 0xffffffff -#define MATCH_DRET 0x7b200073 -#define MASK_DRET 0xffffffff -#define MATCH_SFENCE_VM 0x10400073 -#define MASK_SFENCE_VM 0xfff07fff -#define MATCH_WFI 0x10500073 -#define MASK_WFI 0xffffffff -#define MATCH_CSRRW 0x1073 -#define MASK_CSRRW 0x707f -#define MATCH_CSRRS 0x2073 -#define MASK_CSRRS 0x707f -#define MATCH_CSRRC 0x3073 -#define MASK_CSRRC 0x707f -#define MATCH_CSRRWI 0x5073 -#define MASK_CSRRWI 0x707f -#define MATCH_CSRRSI 0x6073 -#define MASK_CSRRSI 0x707f -#define MATCH_CSRRCI 0x7073 -#define MASK_CSRRCI 0x707f -#define MATCH_FADD_S 0x53 -#define MASK_FADD_S 0xfe00007f -#define MATCH_FSUB_S 0x8000053 -#define MASK_FSUB_S 0xfe00007f -#define MATCH_FMUL_S 0x10000053 -#define MASK_FMUL_S 0xfe00007f -#define MATCH_FDIV_S 0x18000053 -#define MASK_FDIV_S 0xfe00007f -#define MATCH_FSGNJ_S 0x20000053 -#define MASK_FSGNJ_S 0xfe00707f -#define MATCH_FSGNJN_S 0x20001053 -#define MASK_FSGNJN_S 0xfe00707f -#define MATCH_FSGNJX_S 0x20002053 -#define MASK_FSGNJX_S 0xfe00707f -#define MATCH_FMIN_S 0x28000053 -#define MASK_FMIN_S 0xfe00707f -#define MATCH_FMAX_S 0x28001053 -#define MASK_FMAX_S 0xfe00707f -#define MATCH_FSQRT_S 0x58000053 -#define MASK_FSQRT_S 0xfff0007f -#define MATCH_FADD_D 0x2000053 -#define MASK_FADD_D 0xfe00007f -#define MATCH_FSUB_D 0xa000053 -#define MASK_FSUB_D 0xfe00007f -#define MATCH_FMUL_D 0x12000053 -#define MASK_FMUL_D 0xfe00007f -#define MATCH_FDIV_D 0x1a000053 -#define MASK_FDIV_D 0xfe00007f -#define MATCH_FSGNJ_D 0x22000053 -#define MASK_FSGNJ_D 0xfe00707f -#define MATCH_FSGNJN_D 0x22001053 -#define MASK_FSGNJN_D 0xfe00707f -#define MATCH_FSGNJX_D 0x22002053 -#define MASK_FSGNJX_D 0xfe00707f -#define MATCH_FMIN_D 0x2a000053 -#define MASK_FMIN_D 0xfe00707f -#define MATCH_FMAX_D 0x2a001053 -#define MASK_FMAX_D 0xfe00707f -#define MATCH_FCVT_S_D 0x40100053 -#define MASK_FCVT_S_D 0xfff0007f -#define MATCH_FCVT_D_S 0x42000053 -#define MASK_FCVT_D_S 0xfff0007f -#define MATCH_FSQRT_D 0x5a000053 -#define MASK_FSQRT_D 0xfff0007f -#define MATCH_FLE_S 0xa0000053 -#define MASK_FLE_S 0xfe00707f -#define MATCH_FLT_S 0xa0001053 -#define MASK_FLT_S 0xfe00707f -#define MATCH_FEQ_S 0xa0002053 -#define MASK_FEQ_S 0xfe00707f -#define MATCH_FLE_D 0xa2000053 -#define MASK_FLE_D 0xfe00707f -#define MATCH_FLT_D 0xa2001053 -#define MASK_FLT_D 0xfe00707f -#define MATCH_FEQ_D 0xa2002053 -#define MASK_FEQ_D 0xfe00707f -#define MATCH_FCVT_W_S 0xc0000053 -#define MASK_FCVT_W_S 0xfff0007f -#define MATCH_FCVT_WU_S 0xc0100053 -#define MASK_FCVT_WU_S 0xfff0007f -#define MATCH_FCVT_L_S 0xc0200053 -#define MASK_FCVT_L_S 0xfff0007f -#define MATCH_FCVT_LU_S 0xc0300053 -#define MASK_FCVT_LU_S 0xfff0007f -#define MATCH_FMV_X_S 0xe0000053 -#define MASK_FMV_X_S 0xfff0707f -#define MATCH_FCLASS_S 0xe0001053 -#define MASK_FCLASS_S 0xfff0707f -#define MATCH_FCVT_W_D 0xc2000053 -#define MASK_FCVT_W_D 0xfff0007f -#define MATCH_FCVT_WU_D 0xc2100053 -#define MASK_FCVT_WU_D 0xfff0007f -#define MATCH_FCVT_L_D 0xc2200053 -#define MASK_FCVT_L_D 0xfff0007f -#define MATCH_FCVT_LU_D 0xc2300053 -#define MASK_FCVT_LU_D 0xfff0007f -#define MATCH_FMV_X_D 0xe2000053 -#define MASK_FMV_X_D 0xfff0707f -#define MATCH_FCLASS_D 0xe2001053 -#define MASK_FCLASS_D 0xfff0707f -#define MATCH_FCVT_S_W 0xd0000053 -#define MASK_FCVT_S_W 0xfff0007f -#define MATCH_FCVT_S_WU 0xd0100053 -#define MASK_FCVT_S_WU 0xfff0007f -#define MATCH_FCVT_S_L 0xd0200053 -#define MASK_FCVT_S_L 0xfff0007f -#define MATCH_FCVT_S_LU 0xd0300053 -#define MASK_FCVT_S_LU 0xfff0007f -#define MATCH_FMV_S_X 0xf0000053 -#define MASK_FMV_S_X 0xfff0707f -#define MATCH_FCVT_D_W 0xd2000053 -#define MASK_FCVT_D_W 0xfff0007f -#define MATCH_FCVT_D_WU 0xd2100053 -#define MASK_FCVT_D_WU 0xfff0007f -#define MATCH_FCVT_D_L 0xd2200053 -#define MASK_FCVT_D_L 0xfff0007f -#define MATCH_FCVT_D_LU 0xd2300053 -#define MASK_FCVT_D_LU 0xfff0007f -#define MATCH_FMV_D_X 0xf2000053 -#define MASK_FMV_D_X 0xfff0707f -#define MATCH_FLW 0x2007 -#define MASK_FLW 0x707f -#define MATCH_FLD 0x3007 -#define MASK_FLD 0x707f -#define MATCH_FSW 0x2027 -#define MASK_FSW 0x707f -#define MATCH_FSD 0x3027 -#define MASK_FSD 0x707f -#define MATCH_FMADD_S 0x43 -#define MASK_FMADD_S 0x600007f -#define MATCH_FMSUB_S 0x47 -#define MASK_FMSUB_S 0x600007f -#define MATCH_FNMSUB_S 0x4b -#define MASK_FNMSUB_S 0x600007f -#define MATCH_FNMADD_S 0x4f -#define MASK_FNMADD_S 0x600007f -#define MATCH_FMADD_D 0x2000043 -#define MASK_FMADD_D 0x600007f -#define MATCH_FMSUB_D 0x2000047 -#define MASK_FMSUB_D 0x600007f -#define MATCH_FNMSUB_D 0x200004b -#define MASK_FNMSUB_D 0x600007f -#define MATCH_FNMADD_D 0x200004f -#define MASK_FNMADD_D 0x600007f -#define MATCH_C_NOP 0x1 -#define MASK_C_NOP 0xffff -#define MATCH_C_ADDI16SP 0x6101 -#define MASK_C_ADDI16SP 0xef83 -#define MATCH_C_JR 0x8002 -#define MASK_C_JR 0xf07f -#define MATCH_C_JALR 0x9002 -#define MASK_C_JALR 0xf07f -#define MATCH_C_EBREAK 0x9002 -#define MASK_C_EBREAK 0xffff -#define MATCH_C_LD 0x6000 -#define MASK_C_LD 0xe003 -#define MATCH_C_SD 0xe000 -#define MASK_C_SD 0xe003 -#define MATCH_C_ADDIW 0x2001 -#define MASK_C_ADDIW 0xe003 -#define MATCH_C_LDSP 0x6002 -#define MASK_C_LDSP 0xe003 -#define MATCH_C_SDSP 0xe002 -#define MASK_C_SDSP 0xe003 -#define MATCH_C_ADDI4SPN 0x0 -#define MASK_C_ADDI4SPN 0xe003 -#define MATCH_C_FLD 0x2000 -#define MASK_C_FLD 0xe003 -#define MATCH_C_LW 0x4000 -#define MASK_C_LW 0xe003 -#define MATCH_C_FLW 0x6000 -#define MASK_C_FLW 0xe003 -#define MATCH_C_FSD 0xa000 -#define MASK_C_FSD 0xe003 -#define MATCH_C_SW 0xc000 -#define MASK_C_SW 0xe003 -#define MATCH_C_FSW 0xe000 -#define MASK_C_FSW 0xe003 -#define MATCH_C_ADDI 0x1 -#define MASK_C_ADDI 0xe003 -#define MATCH_C_JAL 0x2001 -#define MASK_C_JAL 0xe003 -#define MATCH_C_LI 0x4001 -#define MASK_C_LI 0xe003 -#define MATCH_C_LUI 0x6001 -#define MASK_C_LUI 0xe003 -#define MATCH_C_SRLI 0x8001 -#define MASK_C_SRLI 0xec03 -#define MATCH_C_SRAI 0x8401 -#define MASK_C_SRAI 0xec03 -#define MATCH_C_ANDI 0x8801 -#define MASK_C_ANDI 0xec03 -#define MATCH_C_SUB 0x8c01 -#define MASK_C_SUB 0xfc63 -#define MATCH_C_XOR 0x8c21 -#define MASK_C_XOR 0xfc63 -#define MATCH_C_OR 0x8c41 -#define MASK_C_OR 0xfc63 -#define MATCH_C_AND 0x8c61 -#define MASK_C_AND 0xfc63 -#define MATCH_C_SUBW 0x9c01 -#define MASK_C_SUBW 0xfc63 -#define MATCH_C_ADDW 0x9c21 -#define MASK_C_ADDW 0xfc63 -#define MATCH_C_J 0xa001 -#define MASK_C_J 0xe003 -#define MATCH_C_BEQZ 0xc001 -#define MASK_C_BEQZ 0xe003 -#define MATCH_C_BNEZ 0xe001 -#define MASK_C_BNEZ 0xe003 -#define MATCH_C_SLLI 0x2 -#define MASK_C_SLLI 0xe003 -#define MATCH_C_FLDSP 0x2002 -#define MASK_C_FLDSP 0xe003 -#define MATCH_C_LWSP 0x4002 -#define MASK_C_LWSP 0xe003 -#define MATCH_C_FLWSP 0x6002 -#define MASK_C_FLWSP 0xe003 -#define MATCH_C_MV 0x8002 -#define MASK_C_MV 0xf003 -#define MATCH_C_ADD 0x9002 -#define MASK_C_ADD 0xf003 -#define MATCH_C_FSDSP 0xa002 -#define MASK_C_FSDSP 0xe003 -#define MATCH_C_SWSP 0xc002 -#define MASK_C_SWSP 0xe003 -#define MATCH_C_FSWSP 0xe002 -#define MASK_C_FSWSP 0xe003 -#define MATCH_CUSTOM0 0xb -#define MASK_CUSTOM0 0x707f -#define MATCH_CUSTOM0_RS1 0x200b -#define MASK_CUSTOM0_RS1 0x707f -#define MATCH_CUSTOM0_RS1_RS2 0x300b -#define MASK_CUSTOM0_RS1_RS2 0x707f -#define MATCH_CUSTOM0_RD 0x400b -#define MASK_CUSTOM0_RD 0x707f -#define MATCH_CUSTOM0_RD_RS1 0x600b -#define MASK_CUSTOM0_RD_RS1 0x707f -#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b -#define MASK_CUSTOM0_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM1 0x2b -#define MASK_CUSTOM1 0x707f -#define MATCH_CUSTOM1_RS1 0x202b -#define MASK_CUSTOM1_RS1 0x707f -#define MATCH_CUSTOM1_RS1_RS2 0x302b -#define MASK_CUSTOM1_RS1_RS2 0x707f -#define MATCH_CUSTOM1_RD 0x402b -#define MASK_CUSTOM1_RD 0x707f -#define MATCH_CUSTOM1_RD_RS1 0x602b -#define MASK_CUSTOM1_RD_RS1 0x707f -#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b -#define MASK_CUSTOM1_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM2 0x5b -#define MASK_CUSTOM2 0x707f -#define MATCH_CUSTOM2_RS1 0x205b -#define MASK_CUSTOM2_RS1 0x707f -#define MATCH_CUSTOM2_RS1_RS2 0x305b -#define MASK_CUSTOM2_RS1_RS2 0x707f -#define MATCH_CUSTOM2_RD 0x405b -#define MASK_CUSTOM2_RD 0x707f -#define MATCH_CUSTOM2_RD_RS1 0x605b -#define MASK_CUSTOM2_RD_RS1 0x707f -#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b -#define MASK_CUSTOM2_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM3 0x7b -#define MASK_CUSTOM3 0x707f -#define MATCH_CUSTOM3_RS1 0x207b -#define MASK_CUSTOM3_RS1 0x707f -#define MATCH_CUSTOM3_RS1_RS2 0x307b -#define MASK_CUSTOM3_RS1_RS2 0x707f -#define MATCH_CUSTOM3_RD 0x407b -#define MASK_CUSTOM3_RD 0x707f -#define MATCH_CUSTOM3_RD_RS1 0x607b -#define MASK_CUSTOM3_RD_RS1 0x707f -#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b -#define MASK_CUSTOM3_RD_RS1_RS2 0x707f -#define CSR_FFLAGS 0x1 -#define CSR_FRM 0x2 -#define CSR_FCSR 0x3 -#define CSR_CYCLE 0xc00 -#define CSR_TIME 0xc01 -#define CSR_INSTRET 0xc02 -#define CSR_HPMCOUNTER3 0xc03 -#define CSR_HPMCOUNTER4 0xc04 -#define CSR_HPMCOUNTER5 0xc05 -#define CSR_HPMCOUNTER6 0xc06 -#define CSR_HPMCOUNTER7 0xc07 -#define CSR_HPMCOUNTER8 0xc08 -#define CSR_HPMCOUNTER9 0xc09 -#define CSR_HPMCOUNTER10 0xc0a -#define CSR_HPMCOUNTER11 0xc0b -#define CSR_HPMCOUNTER12 0xc0c -#define CSR_HPMCOUNTER13 0xc0d -#define CSR_HPMCOUNTER14 0xc0e -#define CSR_HPMCOUNTER15 0xc0f -#define CSR_HPMCOUNTER16 0xc10 -#define CSR_HPMCOUNTER17 0xc11 -#define CSR_HPMCOUNTER18 0xc12 -#define CSR_HPMCOUNTER19 0xc13 -#define CSR_HPMCOUNTER20 0xc14 -#define CSR_HPMCOUNTER21 0xc15 -#define CSR_HPMCOUNTER22 0xc16 -#define CSR_HPMCOUNTER23 0xc17 -#define CSR_HPMCOUNTER24 0xc18 -#define CSR_HPMCOUNTER25 0xc19 -#define CSR_HPMCOUNTER26 0xc1a -#define CSR_HPMCOUNTER27 0xc1b -#define CSR_HPMCOUNTER28 0xc1c -#define CSR_HPMCOUNTER29 0xc1d -#define CSR_HPMCOUNTER30 0xc1e -#define CSR_HPMCOUNTER31 0xc1f -#define CSR_SSTATUS 0x100 -#define CSR_SIE 0x104 -#define CSR_STVEC 0x105 -#define CSR_SSCRATCH 0x140 -#define CSR_SEPC 0x141 -#define CSR_SCAUSE 0x142 -#define CSR_SBADADDR 0x143 -#define CSR_SIP 0x144 -#define CSR_SPTBR 0x180 -#define CSR_MSTATUS 0x300 -#define CSR_MISA 0x301 -#define CSR_MEDELEG 0x302 -#define CSR_MIDELEG 0x303 -#define CSR_MIE 0x304 -#define CSR_MTVEC 0x305 -#define CSR_MSCRATCH 0x340 -#define CSR_MEPC 0x341 -#define CSR_MCAUSE 0x342 -#define CSR_MBADADDR 0x343 -#define CSR_MIP 0x344 -#define CSR_TSELECT 0x7a0 -#define CSR_TDATA1 0x7a1 -#define CSR_TDATA2 0x7a2 -#define CSR_TDATA3 0x7a3 -#define CSR_DCSR 0x7b0 -#define CSR_DPC 0x7b1 -#define CSR_DSCRATCH 0x7b2 -#define CSR_MCYCLE 0xb00 -#define CSR_MINSTRET 0xb02 -#define CSR_MHPMCOUNTER3 0xb03 -#define CSR_MHPMCOUNTER4 0xb04 -#define CSR_MHPMCOUNTER5 0xb05 -#define CSR_MHPMCOUNTER6 0xb06 -#define CSR_MHPMCOUNTER7 0xb07 -#define CSR_MHPMCOUNTER8 0xb08 -#define CSR_MHPMCOUNTER9 0xb09 -#define CSR_MHPMCOUNTER10 0xb0a -#define CSR_MHPMCOUNTER11 0xb0b -#define CSR_MHPMCOUNTER12 0xb0c -#define CSR_MHPMCOUNTER13 0xb0d -#define CSR_MHPMCOUNTER14 0xb0e -#define CSR_MHPMCOUNTER15 0xb0f -#define CSR_MHPMCOUNTER16 0xb10 -#define CSR_MHPMCOUNTER17 0xb11 -#define CSR_MHPMCOUNTER18 0xb12 -#define CSR_MHPMCOUNTER19 0xb13 -#define CSR_MHPMCOUNTER20 0xb14 -#define CSR_MHPMCOUNTER21 0xb15 -#define CSR_MHPMCOUNTER22 0xb16 -#define CSR_MHPMCOUNTER23 0xb17 -#define CSR_MHPMCOUNTER24 0xb18 -#define CSR_MHPMCOUNTER25 0xb19 -#define CSR_MHPMCOUNTER26 0xb1a -#define CSR_MHPMCOUNTER27 0xb1b -#define CSR_MHPMCOUNTER28 0xb1c -#define CSR_MHPMCOUNTER29 0xb1d -#define CSR_MHPMCOUNTER30 0xb1e -#define CSR_MHPMCOUNTER31 0xb1f -#define CSR_MUCOUNTEREN 0x320 -#define CSR_MSCOUNTEREN 0x321 -#define CSR_MHPMEVENT3 0x323 -#define CSR_MHPMEVENT4 0x324 -#define CSR_MHPMEVENT5 0x325 -#define CSR_MHPMEVENT6 0x326 -#define CSR_MHPMEVENT7 0x327 -#define CSR_MHPMEVENT8 0x328 -#define CSR_MHPMEVENT9 0x329 -#define CSR_MHPMEVENT10 0x32a -#define CSR_MHPMEVENT11 0x32b -#define CSR_MHPMEVENT12 0x32c -#define CSR_MHPMEVENT13 0x32d -#define CSR_MHPMEVENT14 0x32e -#define CSR_MHPMEVENT15 0x32f -#define CSR_MHPMEVENT16 0x330 -#define CSR_MHPMEVENT17 0x331 -#define CSR_MHPMEVENT18 0x332 -#define CSR_MHPMEVENT19 0x333 -#define CSR_MHPMEVENT20 0x334 -#define CSR_MHPMEVENT21 0x335 -#define CSR_MHPMEVENT22 0x336 -#define CSR_MHPMEVENT23 0x337 -#define CSR_MHPMEVENT24 0x338 -#define CSR_MHPMEVENT25 0x339 -#define CSR_MHPMEVENT26 0x33a -#define CSR_MHPMEVENT27 0x33b -#define CSR_MHPMEVENT28 0x33c -#define CSR_MHPMEVENT29 0x33d -#define CSR_MHPMEVENT30 0x33e -#define CSR_MHPMEVENT31 0x33f -#define CSR_MVENDORID 0xf11 -#define CSR_MARCHID 0xf12 -#define CSR_MIMPID 0xf13 -#define CSR_MHARTID 0xf14 -#define CSR_CYCLEH 0xc80 -#define CSR_TIMEH 0xc81 -#define CSR_INSTRETH 0xc82 -#define CSR_HPMCOUNTER3H 0xc83 -#define CSR_HPMCOUNTER4H 0xc84 -#define CSR_HPMCOUNTER5H 0xc85 -#define CSR_HPMCOUNTER6H 0xc86 -#define CSR_HPMCOUNTER7H 0xc87 -#define CSR_HPMCOUNTER8H 0xc88 -#define CSR_HPMCOUNTER9H 0xc89 -#define CSR_HPMCOUNTER10H 0xc8a -#define CSR_HPMCOUNTER11H 0xc8b -#define CSR_HPMCOUNTER12H 0xc8c -#define CSR_HPMCOUNTER13H 0xc8d -#define CSR_HPMCOUNTER14H 0xc8e -#define CSR_HPMCOUNTER15H 0xc8f -#define CSR_HPMCOUNTER16H 0xc90 -#define CSR_HPMCOUNTER17H 0xc91 -#define CSR_HPMCOUNTER18H 0xc92 -#define CSR_HPMCOUNTER19H 0xc93 -#define CSR_HPMCOUNTER20H 0xc94 -#define CSR_HPMCOUNTER21H 0xc95 -#define CSR_HPMCOUNTER22H 0xc96 -#define CSR_HPMCOUNTER23H 0xc97 -#define CSR_HPMCOUNTER24H 0xc98 -#define CSR_HPMCOUNTER25H 0xc99 -#define CSR_HPMCOUNTER26H 0xc9a -#define CSR_HPMCOUNTER27H 0xc9b -#define CSR_HPMCOUNTER28H 0xc9c -#define CSR_HPMCOUNTER29H 0xc9d -#define CSR_HPMCOUNTER30H 0xc9e -#define CSR_HPMCOUNTER31H 0xc9f -#define CSR_MCYCLEH 0xb80 -#define CSR_MINSTRETH 0xb82 -#define CSR_MHPMCOUNTER3H 0xb83 -#define CSR_MHPMCOUNTER4H 0xb84 -#define CSR_MHPMCOUNTER5H 0xb85 -#define CSR_MHPMCOUNTER6H 0xb86 -#define CSR_MHPMCOUNTER7H 0xb87 -#define CSR_MHPMCOUNTER8H 0xb88 -#define CSR_MHPMCOUNTER9H 0xb89 -#define CSR_MHPMCOUNTER10H 0xb8a -#define CSR_MHPMCOUNTER11H 0xb8b -#define CSR_MHPMCOUNTER12H 0xb8c -#define CSR_MHPMCOUNTER13H 0xb8d -#define CSR_MHPMCOUNTER14H 0xb8e -#define CSR_MHPMCOUNTER15H 0xb8f -#define CSR_MHPMCOUNTER16H 0xb90 -#define CSR_MHPMCOUNTER17H 0xb91 -#define CSR_MHPMCOUNTER18H 0xb92 -#define CSR_MHPMCOUNTER19H 0xb93 -#define CSR_MHPMCOUNTER20H 0xb94 -#define CSR_MHPMCOUNTER21H 0xb95 -#define CSR_MHPMCOUNTER22H 0xb96 -#define CSR_MHPMCOUNTER23H 0xb97 -#define CSR_MHPMCOUNTER24H 0xb98 -#define CSR_MHPMCOUNTER25H 0xb99 -#define CSR_MHPMCOUNTER26H 0xb9a -#define CSR_MHPMCOUNTER27H 0xb9b -#define CSR_MHPMCOUNTER28H 0xb9c -#define CSR_MHPMCOUNTER29H 0xb9d -#define CSR_MHPMCOUNTER30H 0xb9e -#define CSR_MHPMCOUNTER31H 0xb9f -#define CAUSE_MISALIGNED_FETCH 0x0 -#define CAUSE_FAULT_FETCH 0x1 -#define CAUSE_ILLEGAL_INSTRUCTION 0x2 -#define CAUSE_BREAKPOINT 0x3 -#define CAUSE_MISALIGNED_LOAD 0x4 -#define CAUSE_FAULT_LOAD 0x5 -#define CAUSE_MISALIGNED_STORE 0x6 -#define CAUSE_FAULT_STORE 0x7 -#define CAUSE_USER_ECALL 0x8 -#define CAUSE_SUPERVISOR_ECALL 0x9 -#define CAUSE_HYPERVISOR_ECALL 0xa -#define CAUSE_MACHINE_ECALL 0xb -#endif -#ifdef DECLARE_INSN -DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) -DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) -DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) -DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) -DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) -DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) -DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) -DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) -DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) -DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) -DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) -DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) -DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) -DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) -DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) -DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) -DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) -DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) -DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) -DECLARE_INSN(add, MATCH_ADD, MASK_ADD) -DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) -DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) -DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) -DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) -DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) -DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) -DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) -DECLARE_INSN(or, MATCH_OR, MASK_OR) -DECLARE_INSN(and, MATCH_AND, MASK_AND) -DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) -DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) -DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) -DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) -DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) -DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) -DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) -DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) -DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) -DECLARE_INSN(lb, MATCH_LB, MASK_LB) -DECLARE_INSN(lh, MATCH_LH, MASK_LH) -DECLARE_INSN(lw, MATCH_LW, MASK_LW) -DECLARE_INSN(ld, MATCH_LD, MASK_LD) -DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) -DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) -DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) -DECLARE_INSN(sb, MATCH_SB, MASK_SB) -DECLARE_INSN(sh, MATCH_SH, MASK_SH) -DECLARE_INSN(sw, MATCH_SW, MASK_SW) -DECLARE_INSN(sd, MATCH_SD, MASK_SD) -DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) -DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) -DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) -DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) -DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) -DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) -DECLARE_INSN(div, MATCH_DIV, MASK_DIV) -DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) -DECLARE_INSN(rem, MATCH_REM, MASK_REM) -DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) -DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) -DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) -DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) -DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) -DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) -DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) -DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) -DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) -DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) -DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) -DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) -DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) -DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) -DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) -DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) -DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) -DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) -DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) -DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) -DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) -DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) -DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) -DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) -DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) -DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) -DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) -DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) -DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) -DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) -DECLARE_INSN(uret, MATCH_URET, MASK_URET) -DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) -DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) -DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) -DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) -DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) -DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) -DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) -DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) -DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) -DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) -DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) -DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) -DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) -DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) -DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) -DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) -DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) -DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) -DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) -DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) -DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) -DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) -DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) -DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) -DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) -DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) -DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) -DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) -DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) -DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) -DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) -DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) -DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) -DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) -DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) -DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) -DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) -DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) -DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) -DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) -DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) -DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) -DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) -DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) -DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) -DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) -DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) -DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) -DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) -DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) -DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) -DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) -DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) -DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) -DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) -DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) -DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) -DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) -DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) -DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) -DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) -DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) -DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) -DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) -DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) -DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) -DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) -DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) -DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) -DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) -DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) -DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) -DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) -DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) -DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) -DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) -DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) -DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) -DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) -DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) -DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) -DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) -DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) -DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) -DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) -DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) -DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) -DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) -DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) -DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) -DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) -DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) -DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) -DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) -DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) -DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) -DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) -DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) -DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) -DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) -DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) -DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) -DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) -DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) -DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) -DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) -DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) -DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) -DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) -DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) -DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) -DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) -DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) -DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) -DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) -DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) -DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) -DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) -DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) -DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) -DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) -DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) -DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) -DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) -DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) -DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) -DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) -DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) -DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) -DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) -DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) -DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) -DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) -DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) -DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) -DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) -DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) -DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) -DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) -DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) -#endif -#ifdef DECLARE_CSR -DECLARE_CSR(fflags, CSR_FFLAGS) -DECLARE_CSR(frm, CSR_FRM) -DECLARE_CSR(fcsr, CSR_FCSR) -DECLARE_CSR(cycle, CSR_CYCLE) -DECLARE_CSR(time, CSR_TIME) -DECLARE_CSR(instret, CSR_INSTRET) -DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) -DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) -DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) -DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) -DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) -DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) -DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) -DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) -DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) -DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) -DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) -DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) -DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) -DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) -DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) -DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) -DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) -DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) -DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) -DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) -DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) -DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) -DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) -DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) -DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) -DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) -DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) -DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) -DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) -DECLARE_CSR(sstatus, CSR_SSTATUS) -DECLARE_CSR(sie, CSR_SIE) -DECLARE_CSR(stvec, CSR_STVEC) -DECLARE_CSR(sscratch, CSR_SSCRATCH) -DECLARE_CSR(sepc, CSR_SEPC) -DECLARE_CSR(scause, CSR_SCAUSE) -DECLARE_CSR(sbadaddr, CSR_SBADADDR) -DECLARE_CSR(sip, CSR_SIP) -DECLARE_CSR(sptbr, CSR_SPTBR) -DECLARE_CSR(mstatus, CSR_MSTATUS) -DECLARE_CSR(misa, CSR_MISA) -DECLARE_CSR(medeleg, CSR_MEDELEG) -DECLARE_CSR(mideleg, CSR_MIDELEG) -DECLARE_CSR(mie, CSR_MIE) -DECLARE_CSR(mtvec, CSR_MTVEC) -DECLARE_CSR(mscratch, CSR_MSCRATCH) -DECLARE_CSR(mepc, CSR_MEPC) -DECLARE_CSR(mcause, CSR_MCAUSE) -DECLARE_CSR(mbadaddr, CSR_MBADADDR) -DECLARE_CSR(mip, CSR_MIP) -DECLARE_CSR(tselect, CSR_TSELECT) -DECLARE_CSR(tdata1, CSR_TDATA1) -DECLARE_CSR(tdata2, CSR_TDATA2) -DECLARE_CSR(tdata3, CSR_TDATA3) -DECLARE_CSR(dcsr, CSR_DCSR) -DECLARE_CSR(dpc, CSR_DPC) -DECLARE_CSR(dscratch, CSR_DSCRATCH) -DECLARE_CSR(mcycle, CSR_MCYCLE) -DECLARE_CSR(minstret, CSR_MINSTRET) -DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) -DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) -DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) -DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) -DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) -DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) -DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) -DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) -DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) -DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) -DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) -DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) -DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) -DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) -DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) -DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) -DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) -DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) -DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) -DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) -DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) -DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) -DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) -DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) -DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) -DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) -DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) -DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) -DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) -DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) -DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) -DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) -DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) -DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) -DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) -DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) -DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) -DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) -DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) -DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) -DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) -DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) -DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) -DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) -DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) -DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) -DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) -DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) -DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) -DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) -DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) -DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) -DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) -DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) -DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) -DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) -DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) -DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) -DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) -DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) -DECLARE_CSR(mvendorid, CSR_MVENDORID) -DECLARE_CSR(marchid, CSR_MARCHID) -DECLARE_CSR(mimpid, CSR_MIMPID) -DECLARE_CSR(mhartid, CSR_MHARTID) -DECLARE_CSR(cycleh, CSR_CYCLEH) -DECLARE_CSR(timeh, CSR_TIMEH) -DECLARE_CSR(instreth, CSR_INSTRETH) -DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) -DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) -DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) -DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) -DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) -DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) -DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) -DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) -DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) -DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) -DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) -DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) -DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) -DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) -DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) -DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) -DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) -DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) -DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) -DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) -DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) -DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) -DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) -DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) -DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) -DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) -DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) -DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) -DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) -DECLARE_CSR(mcycleh, CSR_MCYCLEH) -DECLARE_CSR(minstreth, CSR_MINSTRETH) -DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) -DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) -DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) -DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) -DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) -DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) -DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) -DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) -DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) -DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) -DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) -DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) -DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) -DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) -DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) -DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) -DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) -DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) -DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) -DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) -DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) -DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) -DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) -DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) -DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) -DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) -DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) -DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) -DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) -#endif -#ifdef DECLARE_CAUSE -DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) -DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) -DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) -DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) -DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) -DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) -DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) -DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) -DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) -DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) -DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) -DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) -#endif diff --git a/libcpu/risc-v/common64/ext_context.h b/libcpu/risc-v/common64/ext_context.h deleted file mode 100644 index f7eb9035765..00000000000 --- a/libcpu/risc-v/common64/ext_context.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-10-10 RT-Thread the first version - */ -#ifndef __EXT_CONTEXT_H__ -#define __EXT_CONTEXT_H__ - -#include - -#ifdef ARCH_RISCV_FPU -/* 32 fpu register */ -#define CTX_FPU_REG_NR 32 -#else -#define CTX_FPU_REG_NR 0 -#endif /* ARCH_RISCV_FPU */ - -#ifdef __ASSEMBLY__ - -/** - * ================================== - * RISC-V D ISA (Floating) - * ================================== - */ - -#ifdef ARCH_RISCV_FPU -#define FPU_CTX_F0_OFF (REGBYTES * 0) /* offsetof(fpu_context_t, fpustatus.f[0]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F1_OFF (REGBYTES * 1) /* offsetof(fpu_context_t, fpustatus.f[1]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F2_OFF (REGBYTES * 2) /* offsetof(fpu_context_t, fpustatus.f[2]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F3_OFF (REGBYTES * 3) /* offsetof(fpu_context_t, fpustatus.f[3]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F4_OFF (REGBYTES * 4) /* offsetof(fpu_context_t, fpustatus.f[4]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F5_OFF (REGBYTES * 5) /* offsetof(fpu_context_t, fpustatus.f[5]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F6_OFF (REGBYTES * 6) /* offsetof(fpu_context_t, fpustatus.f[6]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F7_OFF (REGBYTES * 7) /* offsetof(fpu_context_t, fpustatus.f[7]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F8_OFF (REGBYTES * 8) /* offsetof(fpu_context_t, fpustatus.f[8]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F9_OFF (REGBYTES * 9) /* offsetof(fpu_context_t, fpustatus.f[9]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F10_OFF (REGBYTES * 10) /* offsetof(fpu_context_t, fpustatus.f[10]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F11_OFF (REGBYTES * 11) /* offsetof(fpu_context_t, fpustatus.f[11]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F12_OFF (REGBYTES * 12) /* offsetof(fpu_context_t, fpustatus.f[12]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F13_OFF (REGBYTES * 13) /* offsetof(fpu_context_t, fpustatus.f[13]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F14_OFF (REGBYTES * 14) /* offsetof(fpu_context_t, fpustatus.f[14]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F15_OFF (REGBYTES * 15) /* offsetof(fpu_context_t, fpustatus.f[15]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F16_OFF (REGBYTES * 16) /* offsetof(fpu_context_t, fpustatus.f[16]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F17_OFF (REGBYTES * 17) /* offsetof(fpu_context_t, fpustatus.f[17]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F18_OFF (REGBYTES * 18) /* offsetof(fpu_context_t, fpustatus.f[18]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F19_OFF (REGBYTES * 19) /* offsetof(fpu_context_t, fpustatus.f[19]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F20_OFF (REGBYTES * 20) /* offsetof(fpu_context_t, fpustatus.f[20]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F21_OFF (REGBYTES * 21) /* offsetof(fpu_context_t, fpustatus.f[21]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F22_OFF (REGBYTES * 22) /* offsetof(fpu_context_t, fpustatus.f[22]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F23_OFF (REGBYTES * 23) /* offsetof(fpu_context_t, fpustatus.f[23]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F24_OFF (REGBYTES * 24) /* offsetof(fpu_context_t, fpustatus.f[24]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F25_OFF (REGBYTES * 25) /* offsetof(fpu_context_t, fpustatus.f[25]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F26_OFF (REGBYTES * 26) /* offsetof(fpu_context_t, fpustatus.f[26]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F27_OFF (REGBYTES * 27) /* offsetof(fpu_context_t, fpustatus.f[27]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F28_OFF (REGBYTES * 28) /* offsetof(fpu_context_t, fpustatus.f[28]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F29_OFF (REGBYTES * 29) /* offsetof(fpu_context_t, fpustatus.f[29]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F30_OFF (REGBYTES * 30) /* offsetof(fpu_context_t, fpustatus.f[30]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F31_OFF (REGBYTES * 31) /* offsetof(fpu_context_t, fpustatus.f[31]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#endif /* ARCH_RISCV_FPU */ - -#endif /* __ASSEMBLY__ */ - -#ifdef ARCH_RISCV_VECTOR -#include "rvv_context.h" -#else /* !ARCH_RISCV_VECTOR */ -#define CTX_VECTOR_REG_NR 0 -#endif /* ARCH_RISCV_VECTOR */ - -#endif /* __EXT_CONTEXT_H__ */ diff --git a/libcpu/risc-v/common64/interrupt_gcc.S b/libcpu/risc-v/common64/interrupt_gcc.S deleted file mode 100644 index 015900a16dd..00000000000 --- a/libcpu/risc-v/common64/interrupt_gcc.S +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/02 Bernard The first version - * 2018/12/27 Jesven Add SMP schedule - * 2021/02/02 lizhirui Add userspace support - * 2021/12/24 JasonHu Add user setting save/restore - * 2022/10/22 Shell Support kernel mode RVV; - * Rewrite trap handling routine - */ - -#include "cpuport.h" -#include "encoding.h" -#include "stackframe.h" - - .align 2 - .global trap_entry - .global debug_check_sp -trap_entry: - // distingush exception from kernel or user - csrrw sp, sscratch, sp - bnez sp, _save_context - - // BE REALLY careful with sscratch, - // if it's wrong, we could looping here forever - // or accessing random memory and seeing things totally - // messy after a long time and don't even know why -_from_kernel: - csrr sp, sscratch - j _save_context - -_save_context: - SAVE_ALL - // clear sscratch to say 'now in kernel mode' - csrw sscratch, zero - - RESTORE_SYS_GP - - // now we are ready to enter interrupt / excepiton handler -_distinguish_syscall: - csrr t0, scause -#ifdef RT_USING_SMART - // TODO swap 8 with config macro name - li t1, 8 - bne t0, t1, _handle_interrupt_and_exception - call syscall_entry - // syscall never return here -#endif - -_handle_interrupt_and_exception: - mv a0, t0 - csrrc a1, stval, zero - csrr a2, sepc - // sp as exception frame pointer - mv a3, sp - call handle_trap - -_interrupt_exit: - la s0, rt_thread_switch_interrupt_flag - lw s2, 0(s0) - beqz s2, _resume_execution - sw zero, 0(s0) - -_context_switch: - la t0, rt_interrupt_from_thread - LOAD a0, 0(t0) - la t0, rt_interrupt_to_thread - LOAD a1, 0(t0) - csrr t0, sstatus - andi t0, t0, ~SSTATUS_SPIE - csrw sstatus, t0 - jal rt_hw_context_switch - -_resume_execution: -#ifdef RT_USING_SMART - LOAD t0, FRAME_OFF_SSTATUS(sp) - andi t0, t0, SSTATUS_SPP - bnez t0, _resume_kernel - call arch_ret_to_user -#endif - -_resume_kernel: - RESTORE_ALL - csrw sscratch, zero - sret - -.global rt_hw_interrupt_enable -rt_hw_interrupt_enable: - csrs sstatus, a0 /* restore to old csr */ - jr ra - -.global rt_hw_interrupt_disable -rt_hw_interrupt_disable: - csrrci a0, sstatus, 2 /* clear SIE */ - jr ra diff --git a/libcpu/risc-v/common64/io.h b/libcpu/risc-v/common64/io.h deleted file mode 100644 index 97dca5af971..00000000000 --- a/libcpu/risc-v/common64/io.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019-2020, Xim - * - * SPDX-License-Identifier: Apache-2.0 - * - */ -#ifndef ARCH_IO_H -#define ARCH_IO_H -#include -#define RISCV_FENCE(p, s) \ - __asm__ __volatile__ ("fence " #p "," #s : : : "memory") - -/* These barriers need to enforce ordering on both devices or memory. */ -#define mb() RISCV_FENCE(iorw,iorw) -#define rmb() RISCV_FENCE(ir,ir) -#define wmb() RISCV_FENCE(ow,ow) - -#define __arch_getl(a) (*(unsigned int *)(a)) -#define __arch_putl(v, a) (*(unsigned int *)(a) = (v)) - -#define dmb() mb() -#define __iormb() rmb() -#define __iowmb() wmb() - -static inline void writel(uint32_t val, volatile void *addr) -{ - __iowmb(); - __arch_putl(val, addr); -} - -static inline uint32_t readl(const volatile void *addr) -{ - uint32_t val; - - val = __arch_getl(addr); - __iormb(); - return val; -} - -static inline void write_reg( - uint32_t val, volatile void *addr, unsigned offset) -{ - writel(val, (void *)((rt_size_t)addr + offset)); -} - -static inline uint32_t read_reg( - const volatile void *addr, unsigned offset) -{ - return readl((void *)((rt_size_t)addr + offset)); -} - -#endif // ARCH_IO_H diff --git a/libcpu/risc-v/common64/mmu.c b/libcpu/risc-v/common64/mmu.c deleted file mode 100644 index 6cab811eca7..00000000000 --- a/libcpu/risc-v/common64/mmu.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (c) 2006-2025 RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2022-12-13 WangXiaoyao Port to new mm - * 2023-10-12 Shell Add permission control API - */ - -#include -#include -#include - -#define DBG_TAG "hw.mmu" -#define DBG_LVL DBG_INFO -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef RT_USING_SMART -#include -#include -#include -#endif - -#ifndef RT_USING_SMART -#define USER_VADDR_START 0 -#endif - -static size_t _unmap_area(struct rt_aspace *aspace, void *v_addr); - -static void *current_mmu_table = RT_NULL; - -volatile __attribute__((aligned(4 * 1024))) -rt_ubase_t MMUTable[__SIZE(VPN2_BIT)]; - -/** - * @brief Switch the current address space to the specified one. - * - * This function is responsible for switching the address space by updating the page table - * and related hardware state. The behavior depends on whether the architecture supports - * Address Space Identifiers (ASIDs), devided by macro definition of ARCH_USING_ASID. - * - * @param aspace Pointer to the address space structure containing the new page table. - * - * @note If ASID is supported (`ARCH_USING_ASID` is defined), the function will call - * `rt_hw_asid_switch_pgtbl` to switch the page table and update the ASID. - * Otherwise, it will directly write the `satp` CSR to switch the page table - * and invalidate the TLB. - */ -#ifdef ARCH_USING_ASID -void rt_hw_aspace_switch(rt_aspace_t aspace) -{ - uintptr_t page_table = (uintptr_t)rt_kmem_v2p(aspace->page_table); - current_mmu_table = aspace->page_table; - - rt_hw_asid_switch_pgtbl(aspace, page_table); -} - -#else /* !ARCH_USING_ASID */ -void rt_hw_aspace_switch(rt_aspace_t aspace) -{ - uintptr_t page_table = (uintptr_t)rt_kmem_v2p(aspace->page_table); - current_mmu_table = aspace->page_table; - - write_csr(satp, (((size_t)SATP_MODE) << SATP_MODE_OFFSET) | - ((rt_ubase_t)page_table >> PAGE_OFFSET_BIT)); - rt_hw_tlb_invalidate_all_local(); -} - -void rt_hw_asid_init(void) -{ -} -#endif /* ARCH_USING_ASID */ - -/* get current page table. */ -void *rt_hw_mmu_tbl_get() -{ - return current_mmu_table; -} - -/* Map a single virtual address page to a physical address page in the page table. */ -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; - - l1_off = GET_L1((size_t)va); - l2_off = GET_L2((size_t)va); - l3_off = GET_L3((size_t)va); - - mmu_l1 = ((rt_ubase_t *)aspace->page_table) + l1_off; - - if (PTE_USED(*mmu_l1)) - { - mmu_l2 = (rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*mmu_l1), PV_OFFSET); - } - else - { - mmu_l2 = (rt_ubase_t *)rt_pages_alloc(0); - - if (mmu_l2) - { - 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)); - } - else - { - return -1; - } - } - - 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; - } - } - - 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))); - return 0; -} - -/** - * @brief Maps a virtual address space to a physical address space. - * - * This function maps a specified range of virtual addresses to a range of physical addresses - * and sets the attributes of the page table entries (PTEs). If an error occurs during the - * mapping process, the function will automatically roll back any partially completed mappings. - * - * @param aspace Pointer to the address space structure containing the page table information. - * @param v_addr The starting virtual address to be mapped. - * @param p_addr The starting physical address to be mapped. - * @param size The size of the memory to be mapped (in bytes). - * @param attr The attributes of the page table entries (e.g., read/write permissions, cache policies). - * - * @return On success, returns the starting virtual address `v_addr`; - * On failure, returns `NULL`. - * - * @note This function will not override existing page table entries. - * @warning The caller must ensure that `v_addr` and `p_addr` are page-aligned, - * and `size` is a multiple of the page size. - * - */ -void *rt_hw_mmu_map(struct rt_aspace *aspace, void *v_addr, void *p_addr, - size_t size, size_t attr) -{ - int ret = -1; - void *unmap_va = v_addr; - size_t npages = size >> ARCH_PAGE_SHIFT; - - /* TODO trying with HUGEPAGE here */ - while (npages--) - { - MM_PGTBL_LOCK(aspace); - ret = _map_one_page(aspace, v_addr, p_addr, attr); - MM_PGTBL_UNLOCK(aspace); - if (ret != 0) - { - /* error, undo map */ - while (unmap_va != v_addr) - { - MM_PGTBL_LOCK(aspace); - _unmap_area(aspace, unmap_va); - MM_PGTBL_UNLOCK(aspace); - unmap_va += ARCH_PAGE_SIZE; - } - break; - } - v_addr += ARCH_PAGE_SIZE; - p_addr += ARCH_PAGE_SIZE; - } - - if (ret == 0) - { - return unmap_va; - } - - return NULL; -} - -/* unmap page table entry */ -static void _unmap_pte(rt_ubase_t *pentry, rt_ubase_t *lvl_entry[], int level) -{ - int loop_flag = 1; - while (loop_flag) - { - loop_flag = 0; - *pentry = 0; - rt_hw_cpu_dcache_clean(pentry, sizeof(*pentry)); - - /* we don't handle level 0, which is maintained by caller */ - if (level > 0) - { - void *page = (void *)((rt_ubase_t)pentry & ~ARCH_PAGE_MASK); - - /* decrease reference from child page to parent */ - rt_pages_free(page, 0); - - int free = rt_page_ref_get(page, 0); - if (free == 1) - { - rt_pages_free(page, 0); - pentry = lvl_entry[--level]; - loop_flag = 1; - } - } - } -} - -/* 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) -{ - 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 *pentry; - lvl_entry[i] = ((rt_ubase_t *)aspace->page_table + lvl_off[i]); - pentry = lvl_entry[i]; - - /* check if lvl_entry[0] is valid. if no, return 0 directly. */ - if (!PTE_USED(*pentry)) - { - return 0; - } - - /* find leaf page table entry */ - while (PTE_USED(*pentry) && !PAGE_IS_LEAF(*pentry)) - { - i += 1; - - if (i >= 3) - { - unmapped = 0; - break; - } - - lvl_entry[i] = ((rt_ubase_t *)PPN_TO_VPN(GET_PADDR(*pentry), PV_OFFSET) + - lvl_off[i]); - pentry = lvl_entry[i]; - unmapped >>= ARCH_INDEX_WIDTH; - } - - /* clear PTE & setup its */ - if (PTE_USED(*pentry)) - { - _unmap_pte(pentry, lvl_entry, i); - } - else - { - unmapped = 0; /* invalid pte, return 0. */ - } - - return unmapped; -} - -/** - * @brief Unmaps a range of virtual memory addresses from the specified address space. - * - * This function is responsible for unmapping a contiguous region of virtual memory - * from the given address space. It handles multiple pages and ensures thread safety - * by locking the page table during the unmapping operation. - * - * @param aspace Pointer to the address space structure from which the memory will be unmapped. - * @param v_addr Starting virtual address to unmap. Must be page-aligned. - * @param size Size of the memory region to unmap. Must be page-aligned. - * - * @note The caller must ensure that both `v_addr` and `size` are page-aligned. - * - * @details The function operates in a loop, unmapping memory in chunks. It uses the - * `_unmap_area` function to perform the actual unmapping, which is called within a - * locked section to ensure thread safety. The loop continues until the entire region - * is unmapped. - * - * @see _unmap_area - * @note unmap is different from map that it can handle multiple pages - */ -void rt_hw_mmu_unmap(struct rt_aspace *aspace, void *v_addr, size_t size) -{ - /* caller guarantee that v_addr & size are page aligned */ - if (!aspace->page_table) - { - return; - } - size_t unmapped = 0; - - while (size > 0) - { - MM_PGTBL_LOCK(aspace); - unmapped = _unmap_area(aspace, v_addr); - MM_PGTBL_UNLOCK(aspace); - - /* when unmapped == 0, region not exist in pgtbl */ - if (!unmapped || unmapped > size) break; - - size -= unmapped; - v_addr += unmapped; - } -} - -#ifdef RT_USING_SMART -static inline void _init_region(void *vaddr, size_t size) -{ - rt_ioremap_start = vaddr; - rt_ioremap_size = size; - rt_mpr_start = rt_ioremap_start - rt_mpr_size; - LOG_D("rt_ioremap_start: %p, rt_mpr_start: %p", rt_ioremap_start, - rt_mpr_start); -} -#else -static inline void _init_region(void *vaddr, size_t size) -{ - rt_mpr_start = vaddr - rt_mpr_size; -} -#endif - -#if defined(RT_USING_SMART) && defined(ARCH_REMAP_KERNEL) -#define KERN_SPACE_START ((void *)KERNEL_VADDR_START) -#define KERN_SPACE_SIZE (0xfffffffffffff000UL - KERNEL_VADDR_START + 0x1000) -#else -#define KERN_SPACE_START ((void *)0x1000) -#define KERN_SPACE_SIZE ((size_t)USER_VADDR_START - 0x1000) -#endif - -/** - * @brief Initialize the MMU (Memory Management Unit) mapping. - * - * 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. - * 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 - * using _init_region. - * - * @param aspace Pointer to the address space. Must not be NULL. - * @param v_address The starting virtual address. - * @param size The size of the virtual address space. - * @param vtable Pointer to the page table. Must not be NULL. - * @param pv_off The page table offset. - * - * @return Returns 0 if the initialization is successful. Returns -1 if any input parameter is invalid - * or the page table initialization check fails. - */ -int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, - rt_ubase_t *vtable, rt_ubase_t pv_off) -{ - size_t l1_off, va_s, va_e; - - if ((!aspace) || (!vtable)) - { - return -1; - } - - va_s = (rt_ubase_t)v_address; - va_e = ((rt_ubase_t)v_address) + size - 1; - - if (va_e < va_s) - { - return -1; - } - - /* convert address to PPN2 index */ - va_s = GET_L1(va_s); - va_e = GET_L1(va_e); - - if (va_s == 0) - { - return -1; - } - - /* vtable initialization check */ - for (l1_off = va_s; l1_off <= va_e; l1_off++) - { - size_t v = vtable[l1_off]; - - if (v) - { - return -1; - } - } - - rt_aspace_init(&rt_kernel_space, KERN_SPACE_START, KERN_SPACE_SIZE, vtable); - - _init_region(v_address, size); - return 0; -} - -const static int max_level = - (ARCH_VADDR_WIDTH - ARCH_PAGE_SHIFT) / ARCH_INDEX_WIDTH; - -static inline uintptr_t _get_level_size(int level) -{ - return 1ul << (ARCH_PAGE_SHIFT + (max_level - level) * ARCH_INDEX_WIDTH); -} - -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); - - if (!aspace) - { - LOG_W("%s: no aspace", __func__); - return RT_NULL; - } - - mmu_l1 = ((rt_ubase_t *)aspace->page_table) + l1_off; - - if (PTE_USED(*mmu_l1)) - { - 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); - - if (PTE_USED(*(mmu_l2 + l2_off))) - { - if (*(mmu_l2 + l2_off) & PTE_XWR_MASK) - { - *level = 2; - return mmu_l2 + l2_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; - } - } - } - - return RT_NULL; -} - -/** - * @brief Translate a virtual address to a physical address. - * - * This function translates a given virtual address (`vaddr`) to its corresponding - * physical address (`paddr`) using the page table in the specified address space (`aspace`). - * - * @param aspace Pointer to the address space structure containing the page table. - * @param vaddr The virtual address to be translated. - * - * @return The translated physical address. If the translation fails, `ARCH_MAP_FAILED` is returned. - * - * @note The function queries the page table entry (PTE) for the virtual address using `_query`. - * If a valid PTE is found, the physical address is extracted and combined with the offset - * from the virtual address. If no valid PTE is found, a debug log is recorded, and - * `ARCH_MAP_FAILED` is returned. - */ -void *rt_hw_mmu_v2p(struct rt_aspace *aspace, void *vaddr) -{ - int level; - rt_ubase_t *pte = _query(aspace, vaddr, &level); - uintptr_t paddr; - - if (pte) - { - paddr = GET_PADDR(*pte); - paddr |= ((intptr_t)vaddr & (_get_level_size(level) - 1)); - } - else - { - LOG_D("%s: failed at %p", __func__, vaddr); - paddr = (uintptr_t)ARCH_MAP_FAILED; - } - return (void *)paddr; -} - -static int _noncache(rt_base_t *pte) -{ - return 0; -} - -static int _cache(rt_base_t *pte) -{ - return 0; -} - -static int (*control_handler[MMU_CNTL_DUMMY_END])(rt_base_t *pte)= -{ - [MMU_CNTL_CACHE] = _cache, - [MMU_CNTL_NONCACHE] = _noncache, -}; - -/** - * @brief Control the page table entries (PTEs) for a specified virtual address range. - * - * This function applies a control command (e.g., cache control) to the page table entries - * (PTEs) corresponding to the specified virtual address range (`vaddr` to `vaddr + size`). - * - * @param aspace Pointer to the address space structure containing the page table. - * @param vaddr The starting virtual address of the range. - * @param size The size of the virtual address range. - * @param cmd The control command to apply (e.g., `MMU_CNTL_CACHE`, `MMU_CNTL_NONCACHE`.etc.). - * - * @return `RT_EOK` on success, or an error code (`-RT_EINVAL` or `-RT_ENOSYS`) on failure. - * - * @note The function uses the `control_handler` array to map the command to a handler function. - * It iterates over the virtual address range, queries the PTEs, and applies the handler - * to each valid PTE. If the command is invalid, `-RT_ENOSYS` is returned. - */ -int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, - enum rt_mmu_cntl cmd) -{ - int level; - int err = -RT_EINVAL; - void *vend = vaddr + size; - - int (*handler)(rt_base_t *pte); - if (cmd >= 0 && cmd < MMU_CNTL_DUMMY_END) - { - handler = control_handler[cmd]; - - while (vaddr < vend) - { - rt_base_t *pte = _query(aspace, vaddr, &level); - void *range_end = vaddr + _get_level_size(level); - RT_ASSERT(range_end <= vend); - - if (pte) - { - err = handler(pte); - RT_ASSERT(err == RT_EOK); - } - vaddr = range_end; - } - } - else - { - err = -RT_ENOSYS; - } - - return err; -} - -/** - * @brief setup Page Table for kernel space. It's a fixed map - * and all mappings cannot be changed after initialization. - * - * Memory region in struct mem_desc must be page aligned, - * otherwise is a failure and no report will be - * returned. - * - * @param aspace Pointer to the address space structure. - * @param mdesc Pointer to the array of memory descriptors. - * @param desc_nr Number of memory descriptors in the array. - */ -void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr) -{ - void *err; - for (size_t i = 0; i < desc_nr; i++) - { - size_t attr; - switch (mdesc->attr) - { - case NORMAL_MEM: - attr = MMU_MAP_K_RWCB; - break; - case NORMAL_NOCACHE_MEM: - attr = MMU_MAP_K_RWCB; - break; - case DEVICE_MEM: - attr = MMU_MAP_K_DEVICE; - break; - default: - attr = MMU_MAP_K_DEVICE; - } - - struct rt_mm_va_hint hint = { - .flags = MMF_MAP_FIXED, - .limit_start = aspace->start, - .limit_range_size = aspace->size, - .map_size = mdesc->vaddr_end - mdesc->vaddr_start + 1, - .prefer = (void *)mdesc->vaddr_start}; - - if (mdesc->paddr_start == (rt_uintptr_t)ARCH_MAP_FAILED) - mdesc->paddr_start = mdesc->vaddr_start + PV_OFFSET; - - rt_aspace_map_phy_static(aspace, &mdesc->varea, &hint, attr, - mdesc->paddr_start >> MM_PAGE_SHIFT, &err); - mdesc++; - } - - rt_hw_asid_init(); - - rt_hw_aspace_switch(&rt_kernel_space); - rt_page_cleanup(); -} - -#define SATP_BASE ((rt_ubase_t)SATP_MODE << SATP_MODE_OFFSET) - -extern unsigned int __bss_end; - -/** - * @brief Early memory setup function for hardware initialization. - * - * This function performs early memory setup tasks, including: - * - Calculating the physical-to-virtual (PV) offset. - * - Setting up initial page tables for identity mapping and text region relocation. - * - Applying new memory mappings by updating the SATP register. - * - * @note This function is typically called during the early stages of system initialization (startup_gcc.S), - * before the memory management system is fully operational. - * Here the identity mapping is implemented by a 1-stage page table, whose page size is 1GB. - */ -void rt_hw_mem_setup_early(void) -{ - rt_ubase_t pv_off; - rt_ubase_t ps = 0x0; - rt_ubase_t vs = 0x0; - rt_ubase_t *early_pgtbl = (rt_ubase_t *)(((size_t)&__bss_end + 4095) & ~0xfff); - - /* calculate pv_offset */ - void *symb_pc; - void *symb_linker; - __asm__ volatile("la %0, _start\n" : "=r"(symb_pc)); - __asm__ volatile("la %0, _start_link_addr\n" : "=r"(symb_linker)); - symb_linker = *(void **)symb_linker; - pv_off = symb_pc - symb_linker; - rt_kmem_pvoff_set(pv_off); - - if (pv_off) - { - if (pv_off & ((1ul << (ARCH_INDEX_WIDTH * 2 + ARCH_PAGE_SHIFT)) - 1)) - { - LOG_E("%s: not aligned virtual address. pv_offset %p", __func__, - pv_off); - RT_ASSERT(0); - } - - /** - * identical mapping, - * PC are still at lower region before relocating to high memory - */ - for (size_t i = 0; i < __SIZE(PPN0_BIT); i++) - { - early_pgtbl[i] = COMBINEPTE(ps, MMU_MAP_EARLY); - ps += L1_PAGE_SIZE; - } - - /* relocate text region */ - __asm__ volatile("la %0, _start\n" : "=r"(ps)); - ps &= ~(L1_PAGE_SIZE - 1); - vs = ps - pv_off; - - /* relocate region */ - rt_ubase_t vs_idx = GET_L1(vs); - rt_ubase_t ve_idx = GET_L1(vs + 0x80000000); - for (size_t i = vs_idx; i < ve_idx; i++) - { - early_pgtbl[i] = COMBINEPTE(ps, MMU_MAP_EARLY); - ps += L1_PAGE_SIZE; - } - - /* apply new mapping */ - asm volatile("sfence.vma x0, x0"); - write_csr(satp, SATP_BASE | ((size_t)early_pgtbl >> PAGE_OFFSET_BIT)); - asm volatile("sfence.vma x0, x0"); - } - /* return to lower text section */ -} - -/** - * @brief Creates and initializes a new MMU page table. - * - * This function allocates a new MMU page table, copies the kernel space - * page table into it, and flushes the data cache to ensure consistency. - * - * @return - * - A pointer to the newly allocated MMU page table on success. - * - RT_NULL if the allocation fails. - */ -void *rt_hw_mmu_pgtbl_create(void) -{ - rt_ubase_t *mmu_table; - mmu_table = (rt_ubase_t *)rt_pages_alloc_ext(0, PAGE_ANY_AVAILABLE); - if (!mmu_table) - { - return RT_NULL; - } - rt_memcpy(mmu_table, rt_kernel_space.page_table, ARCH_PAGE_SIZE); - rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, ARCH_PAGE_SIZE); - - return mmu_table; -} - -/** - * @brief Deletes an MMU page table. - * - * This function frees the memory allocated for the given MMU page table. - * - * @param pgtbl Pointer to the MMU page table to be deleted. - */ -void rt_hw_mmu_pgtbl_delete(void *pgtbl) -{ - rt_pages_free(pgtbl, 0); -} \ No newline at end of file diff --git a/libcpu/risc-v/common64/mmu.h b/libcpu/risc-v/common64/mmu.h deleted file mode 100644 index cb9ae45fa4a..00000000000 --- a/libcpu/risc-v/common64/mmu.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2023-10-12 Shell Add permission control API - */ - -#ifndef __MMU_H__ -#define __MMU_H__ - -#include "riscv.h" -#include "riscv_mmu.h" -#include -#include - -/* RAM, Flash, or ROM */ -#define NORMAL_MEM 0 -/* normal nocache memory mapping type */ -#define NORMAL_NOCACHE_MEM 1 -/* MMIO region */ -#define DEVICE_MEM 2 - -typedef size_t rt_pte_t; - -struct mem_desc -{ - rt_size_t vaddr_start; - rt_size_t vaddr_end; - rt_ubase_t paddr_start; - rt_size_t attr; - struct rt_varea varea; -}; - -#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) \ - (__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) \ - ((((paddr) >> PAGE_OFFSET_BIT) << PTE_PPN_SHIFT) | (attr)) - -#define MMU_MAP_ERROR_VANOTALIGN -1 -#define MMU_MAP_ERROR_PANOTALIGN -2 -#define MMU_MAP_ERROR_NOPAGE -3 -#define MMU_MAP_ERROR_CONFLICT -4 - -void *rt_hw_mmu_tbl_get(void); -int rt_hw_mmu_map_init(rt_aspace_t aspace, void *v_address, rt_ubase_t size, - rt_ubase_t *vtable, rt_ubase_t pv_off); -void rt_hw_mmu_setup(rt_aspace_t aspace, struct mem_desc *mdesc, int desc_nr); -void *rt_hw_mmu_map(rt_aspace_t aspace, void *v_addr, void *p_addr, size_t size, - size_t attr); -void rt_hw_mmu_unmap(rt_aspace_t aspace, void *v_addr, size_t size); -void rt_hw_aspace_switch(rt_aspace_t aspace); -void *rt_hw_mmu_v2p(rt_aspace_t aspace, void *vaddr); - -int rt_hw_mmu_control(struct rt_aspace *aspace, void *vaddr, size_t size, - enum rt_mmu_cntl cmd); - -void *rt_hw_mmu_pgtbl_create(void); -void rt_hw_mmu_pgtbl_delete(void *pgtbl); - -#endif diff --git a/libcpu/risc-v/common64/riscv.h b/libcpu/risc-v/common64/riscv.h deleted file mode 100644 index 4adaaf10341..00000000000 --- a/libcpu/risc-v/common64/riscv.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2024-08-28 RT-Thread Fit into rv64ilp32 ABI - */ - -#ifndef __RISCV_H__ -#define __RISCV_H__ - -#include - -/* using unsigned long long for the case of rv64ilp32 */ -#define __SIZE(bit) (1ULL << (bit)) -#define __MASK(bit) (__SIZE(bit) - 1ULL) - -#define __UMASK(bit) (~(__MASK(bit))) -#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue)) -#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue))) -#define __CHECKUPBOUND(value,bit_count) (!(((rt_ubase_t)value) & (~__MASK(bit_count)))) -#define __CHECKALIGN(value,start_bit) (!(((rt_ubase_t)value) & (__MASK(start_bit)))) - -#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length)) - -#define __ALIGNUP(value,bit) (((value) + __MASK(bit)) & __UMASK(bit)) -#define __ALIGNDOWN(value,bit) ((value) & __UMASK(bit)) - -#endif diff --git a/libcpu/risc-v/common64/riscv_io.h b/libcpu/risc-v/common64/riscv_io.h deleted file mode 100644 index f5582fbbf80..00000000000 --- a/libcpu/risc-v/common64/riscv_io.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 2019 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - */ - -#ifndef __RISCV_IO_H__ -#define __RISCV_IO_H__ - -static inline uint32_t __raw_hartid(void) -{ - extern int boot_hartid; - return boot_hartid; -} - -static inline void __raw_writeb(rt_uint8_t val, volatile void *addr) -{ - asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr)); -} - -static inline void __raw_writew(rt_uint16_t val, volatile void *addr) -{ - asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr)); -} - -static inline void __raw_writel(rt_uint32_t val, volatile void *addr) -{ - asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr)); -} - -#if __riscv_xlen != 32 -static inline void __raw_writeq(rt_uint64_t val, volatile void *addr) -{ - asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr)); -} -#endif - -static inline rt_uint8_t __raw_readb(const volatile void *addr) -{ - rt_uint8_t val; - - asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; -} - -static inline rt_uint16_t __raw_readw(const volatile void *addr) -{ - rt_uint16_t val; - - asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; -} - -static inline rt_uint32_t __raw_readl(const volatile void *addr) -{ - rt_uint32_t val; - - asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; -} - -#if __riscv_xlen != 32 -static inline rt_uint64_t __raw_readq(const volatile void *addr) -{ - rt_uint64_t val; - - asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr)); - return val; -} -#endif - -/* FIXME: These are now the same as asm-generic */ - -/* clang-format off */ - -#define __io_rbr() do {} while (0) -#define __io_rar() do {} while (0) -#define __io_rbw() do {} while (0) -#define __io_raw() do {} while (0) - -#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; }) -#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; }) -#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; }) - -#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); }) -#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); }) -#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); }) - -#if __riscv_xlen != 32 -#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; }) -#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); }) -#endif - -#define __io_br() do {} while (0) -#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory"); -#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory"); -#define __io_aw() do {} while (0) - -#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; }) -#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; }) -#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; }) - -#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); }) -#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); }) -#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); }) - -#if __riscv_xlen != 32 -#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; }) -#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); }) -#endif - -#endif diff --git a/libcpu/risc-v/common64/riscv_mmu.c b/libcpu/risc-v/common64/riscv_mmu.c deleted file mode 100644 index 9dec1aed718..00000000000 --- a/libcpu/risc-v/common64/riscv_mmu.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - */ - -#include -#include - -#include -#include -#include -#include - -#include "riscv_mmu.h" - -void mmu_enable_user_page_access(void) -{ - set_csr(sstatus, SSTATUS_SUM); -} - -void mmu_disable_user_page_access(void) -{ - clear_csr(sstatus, SSTATUS_SUM); -} diff --git a/libcpu/risc-v/common64/stack.h b/libcpu/risc-v/common64/stack.h deleted file mode 100644 index 4302b26e1f5..00000000000 --- a/libcpu/risc-v/common64/stack.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2021-11-18 JasonHu add fpu member - * 2022-10-22 Shell Support kernel mode RVV - */ - -#ifndef __STACK_H__ -#define __STACK_H__ - -#include "stackframe.h" - -#include - -typedef struct rt_hw_switch_frame -{ - uint64_t regs[RT_HW_SWITCH_CONTEXT_SIZE]; -} *rt_hw_switch_frame_t; - - -struct rt_hw_stack_frame -{ - rt_ubase_t epc; /* epc - epc - program counter */ - rt_ubase_t ra; /* x1 - ra - return address for jumps */ - rt_ubase_t sstatus; /* - supervisor status register */ - rt_ubase_t gp; /* x3 - gp - global pointer */ - rt_ubase_t tp; /* x4 - tp - thread pointer */ - rt_ubase_t t0; /* x5 - t0 - temporary register 0 */ - rt_ubase_t t1; /* x6 - t1 - temporary register 1 */ - rt_ubase_t t2; /* x7 - t2 - temporary register 2 */ - rt_ubase_t s0_fp; /* x8 - s0/fp - saved register 0 or frame pointer */ - rt_ubase_t s1; /* x9 - s1 - saved register 1 */ - rt_ubase_t a0; /* x10 - a0 - return value or function argument 0 */ - rt_ubase_t a1; /* x11 - a1 - return value or function argument 1 */ - rt_ubase_t a2; /* x12 - a2 - function argument 2 */ - rt_ubase_t a3; /* x13 - a3 - function argument 3 */ - rt_ubase_t a4; /* x14 - a4 - function argument 4 */ - rt_ubase_t a5; /* x15 - a5 - function argument 5 */ - rt_ubase_t a6; /* x16 - a6 - function argument 6 */ - rt_ubase_t a7; /* x17 - s7 - function argument 7 */ - rt_ubase_t s2; /* x18 - s2 - saved register 2 */ - rt_ubase_t s3; /* x19 - s3 - saved register 3 */ - rt_ubase_t s4; /* x20 - s4 - saved register 4 */ - rt_ubase_t s5; /* x21 - s5 - saved register 5 */ - rt_ubase_t s6; /* x22 - s6 - saved register 6 */ - rt_ubase_t s7; /* x23 - s7 - saved register 7 */ - rt_ubase_t s8; /* x24 - s8 - saved register 8 */ - rt_ubase_t s9; /* x25 - s9 - saved register 9 */ - rt_ubase_t s10; /* x26 - s10 - saved register 10 */ - rt_ubase_t s11; /* x27 - s11 - saved register 11 */ - rt_ubase_t t3; /* x28 - t3 - temporary register 3 */ - rt_ubase_t t4; /* x29 - t4 - temporary register 4 */ - rt_ubase_t t5; /* x30 - t5 - temporary register 5 */ - rt_ubase_t t6; /* x31 - t6 - temporary register 6 */ - rt_ubase_t user_sp_exc_stack; /* sscratch - user mode sp/exception stack */ - rt_ubase_t __padding; /* align to 16bytes */ -#ifdef ARCH_RISCV_FPU - rt_ubase_t f[CTX_FPU_REG_NR]; /* f0~f31 */ -#endif /* ARCH_RISCV_FPU */ -#ifdef ARCH_RISCV_VECTOR - rt_ubase_t v[CTX_VECTOR_REG_NR]; -#endif /* ARCH_RISCV_VECTOR */ -}; - -#endif diff --git a/libcpu/risc-v/common64/stackframe.h b/libcpu/risc-v/common64/stackframe.h deleted file mode 100644 index f6311a76fe1..00000000000 --- a/libcpu/risc-v/common64/stackframe.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-02-02 lizhirui first version - * 2021-02-11 lizhirui fixed gp save/store bug - * 2021-11-18 JasonHu add fpu registers save/restore - * 2022-10-22 Shell Support kernel mode RVV - */ - -#ifndef __STACKFRAME_H__ -#define __STACKFRAME_H__ - -#include -#include "encoding.h" - -/* bytes of register width */ -#ifdef ARCH_CPU_64BIT -#define STORE sd -#define LOAD ld -#define FSTORE fsd -#define FLOAD fld -#define REGBYTES 8 -#else -// error here, not portable -#error "Not supported XLEN" -#endif - -#include "ext_context.h" - -/* 33 general register + 1 padding */ -#define CTX_GENERAL_REG_NR 34 - -/* all context registers */ -#define CTX_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR + CTX_VECTOR_REG_NR) - -#define BYTES(idx) ((idx) * REGBYTES) -#define FRAME_OFF_SSTATUS BYTES(2) -#define FRAME_OFF_SP BYTES(32) -#define FRAME_OFF_GP BYTES(3) - -/* switch frame */ -#define RT_HW_SWITCH_CONTEXT_SSTATUS 0 -#define RT_HW_SWITCH_CONTEXT_S11 1 -#define RT_HW_SWITCH_CONTEXT_S10 2 -#define RT_HW_SWITCH_CONTEXT_S9 3 -#define RT_HW_SWITCH_CONTEXT_S8 4 -#define RT_HW_SWITCH_CONTEXT_S7 5 -#define RT_HW_SWITCH_CONTEXT_S6 6 -#define RT_HW_SWITCH_CONTEXT_S5 7 -#define RT_HW_SWITCH_CONTEXT_S4 8 -#define RT_HW_SWITCH_CONTEXT_S3 9 -#define RT_HW_SWITCH_CONTEXT_S2 10 -#define RT_HW_SWITCH_CONTEXT_S1 11 -#define RT_HW_SWITCH_CONTEXT_S0 12 -#define RT_HW_SWITCH_CONTEXT_RA 13 -#define RT_HW_SWITCH_CONTEXT_TP 14 -#define RT_HW_SWITCH_CONTEXT_ALIGNMENT 15 // Padding for alignment -#define RT_HW_SWITCH_CONTEXT_SIZE 16 // Total size of the structure - -#ifdef __ASSEMBLY__ - -.macro SAVE_ALL - -#ifdef ARCH_RISCV_FPU - /* reserve float registers */ - addi sp, sp, -CTX_FPU_REG_NR * REGBYTES -#endif /* ARCH_RISCV_FPU */ -#ifdef ARCH_RISCV_VECTOR - /* reserve float registers */ - addi sp, sp, -CTX_VECTOR_REG_NR * REGBYTES -#endif /* ARCH_RISCV_VECTOR */ - - /* save general registers */ - addi sp, sp, -CTX_GENERAL_REG_NR * REGBYTES - STORE x1, 1 * REGBYTES(sp) - - csrr x1, sstatus - STORE x1, FRAME_OFF_SSTATUS(sp) - - csrr x1, sepc - STORE x1, 0 * REGBYTES(sp) - - STORE x3, 3 * REGBYTES(sp) - STORE x4, 4 * REGBYTES(sp) /* save tp */ - STORE x5, 5 * REGBYTES(sp) - STORE x6, 6 * REGBYTES(sp) - STORE x7, 7 * REGBYTES(sp) - STORE x8, 8 * REGBYTES(sp) - STORE x9, 9 * REGBYTES(sp) - STORE x10, 10 * REGBYTES(sp) - STORE x11, 11 * REGBYTES(sp) - STORE x12, 12 * REGBYTES(sp) - STORE x13, 13 * REGBYTES(sp) - STORE x14, 14 * REGBYTES(sp) - STORE x15, 15 * REGBYTES(sp) - STORE x16, 16 * REGBYTES(sp) - STORE x17, 17 * REGBYTES(sp) - STORE x18, 18 * REGBYTES(sp) - STORE x19, 19 * REGBYTES(sp) - STORE x20, 20 * REGBYTES(sp) - STORE x21, 21 * REGBYTES(sp) - STORE x22, 22 * REGBYTES(sp) - STORE x23, 23 * REGBYTES(sp) - STORE x24, 24 * REGBYTES(sp) - STORE x25, 25 * REGBYTES(sp) - STORE x26, 26 * REGBYTES(sp) - STORE x27, 27 * REGBYTES(sp) - STORE x28, 28 * REGBYTES(sp) - STORE x29, 29 * REGBYTES(sp) - STORE x30, 30 * REGBYTES(sp) - STORE x31, 31 * REGBYTES(sp) - csrr t0, sscratch - STORE t0, 32 * REGBYTES(sp) - -#ifdef ARCH_RISCV_FPU - /* backup sp and adjust sp to save float registers */ - mv t1, sp - addi t1, t1, CTX_GENERAL_REG_NR * REGBYTES - - li t0, SSTATUS_FS - csrs sstatus, t0 - FSTORE f0, FPU_CTX_F0_OFF(t1) - FSTORE f1, FPU_CTX_F1_OFF(t1) - FSTORE f2, FPU_CTX_F2_OFF(t1) - FSTORE f3, FPU_CTX_F3_OFF(t1) - FSTORE f4, FPU_CTX_F4_OFF(t1) - FSTORE f5, FPU_CTX_F5_OFF(t1) - FSTORE f6, FPU_CTX_F6_OFF(t1) - FSTORE f7, FPU_CTX_F7_OFF(t1) - FSTORE f8, FPU_CTX_F8_OFF(t1) - FSTORE f9, FPU_CTX_F9_OFF(t1) - FSTORE f10, FPU_CTX_F10_OFF(t1) - FSTORE f11, FPU_CTX_F11_OFF(t1) - FSTORE f12, FPU_CTX_F12_OFF(t1) - FSTORE f13, FPU_CTX_F13_OFF(t1) - FSTORE f14, FPU_CTX_F14_OFF(t1) - FSTORE f15, FPU_CTX_F15_OFF(t1) - FSTORE f16, FPU_CTX_F16_OFF(t1) - FSTORE f17, FPU_CTX_F17_OFF(t1) - FSTORE f18, FPU_CTX_F18_OFF(t1) - FSTORE f19, FPU_CTX_F19_OFF(t1) - FSTORE f20, FPU_CTX_F20_OFF(t1) - FSTORE f21, FPU_CTX_F21_OFF(t1) - FSTORE f22, FPU_CTX_F22_OFF(t1) - FSTORE f23, FPU_CTX_F23_OFF(t1) - FSTORE f24, FPU_CTX_F24_OFF(t1) - FSTORE f25, FPU_CTX_F25_OFF(t1) - FSTORE f26, FPU_CTX_F26_OFF(t1) - FSTORE f27, FPU_CTX_F27_OFF(t1) - FSTORE f28, FPU_CTX_F28_OFF(t1) - FSTORE f29, FPU_CTX_F29_OFF(t1) - FSTORE f30, FPU_CTX_F30_OFF(t1) - FSTORE f31, FPU_CTX_F31_OFF(t1) - - /* clr FS domain */ - csrc sstatus, t0 - - /* clean status would clr sr_sd; */ - li t0, SSTATUS_FS_CLEAN - csrs sstatus, t0 - -#endif /* ARCH_RISCV_FPU */ - -#ifdef ARCH_RISCV_VECTOR - csrr t0, sstatus - andi t0, t0, SSTATUS_VS - beqz t0, 0f - - /* push vector frame */ - addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * REGBYTES - - SAVE_VECTOR t1 -0: -#endif /* ARCH_RISCV_VECTOR */ -.endm - -/** - * @brief Restore All General Registers, for interrupt handling - * - */ -.macro RESTORE_ALL - -#ifdef ARCH_RISCV_VECTOR - // skip on close - ld t0, 2 * REGBYTES(sp) - // cannot use vector on initial - andi t0, t0, SSTATUS_VS_CLEAN - beqz t0, 0f - - /* push vector frame */ - addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * REGBYTES - - RESTORE_VECTOR t1 -0: -#endif /* ARCH_RISCV_VECTOR */ - -#ifdef ARCH_RISCV_FPU - /* restore float register */ - addi t2, sp, CTX_GENERAL_REG_NR * REGBYTES - - li t0, SSTATUS_FS - csrs sstatus, t0 - FLOAD f0, FPU_CTX_F0_OFF(t2) - FLOAD f1, FPU_CTX_F1_OFF(t2) - FLOAD f2, FPU_CTX_F2_OFF(t2) - FLOAD f3, FPU_CTX_F3_OFF(t2) - FLOAD f4, FPU_CTX_F4_OFF(t2) - FLOAD f5, FPU_CTX_F5_OFF(t2) - FLOAD f6, FPU_CTX_F6_OFF(t2) - FLOAD f7, FPU_CTX_F7_OFF(t2) - FLOAD f8, FPU_CTX_F8_OFF(t2) - FLOAD f9, FPU_CTX_F9_OFF(t2) - FLOAD f10, FPU_CTX_F10_OFF(t2) - FLOAD f11, FPU_CTX_F11_OFF(t2) - FLOAD f12, FPU_CTX_F12_OFF(t2) - FLOAD f13, FPU_CTX_F13_OFF(t2) - FLOAD f14, FPU_CTX_F14_OFF(t2) - FLOAD f15, FPU_CTX_F15_OFF(t2) - FLOAD f16, FPU_CTX_F16_OFF(t2) - FLOAD f17, FPU_CTX_F17_OFF(t2) - FLOAD f18, FPU_CTX_F18_OFF(t2) - FLOAD f19, FPU_CTX_F19_OFF(t2) - FLOAD f20, FPU_CTX_F20_OFF(t2) - FLOAD f21, FPU_CTX_F21_OFF(t2) - FLOAD f22, FPU_CTX_F22_OFF(t2) - FLOAD f23, FPU_CTX_F23_OFF(t2) - FLOAD f24, FPU_CTX_F24_OFF(t2) - FLOAD f25, FPU_CTX_F25_OFF(t2) - FLOAD f26, FPU_CTX_F26_OFF(t2) - FLOAD f27, FPU_CTX_F27_OFF(t2) - FLOAD f28, FPU_CTX_F28_OFF(t2) - FLOAD f29, FPU_CTX_F29_OFF(t2) - FLOAD f30, FPU_CTX_F30_OFF(t2) - FLOAD f31, FPU_CTX_F31_OFF(t2) - - /* clr FS domain */ - csrc sstatus, t0 - - /* clean status would clr sr_sd; */ - li t0, SSTATUS_FS_CLEAN - csrs sstatus, t0 - -#endif /* ARCH_RISCV_FPU */ - - /* restore general register */ - addi t0, sp, CTX_REG_NR * REGBYTES - csrw sscratch, t0 - - /* resw ra to sepc */ - LOAD x1, 0 * REGBYTES(sp) - csrw sepc, x1 - - LOAD x1, 2 * REGBYTES(sp) - csrw sstatus, x1 - - LOAD x1, 1 * REGBYTES(sp) - - LOAD x3, 3 * REGBYTES(sp) - LOAD x4, 4 * REGBYTES(sp) /* restore tp */ - LOAD x5, 5 * REGBYTES(sp) - LOAD x6, 6 * REGBYTES(sp) - LOAD x7, 7 * REGBYTES(sp) - LOAD x8, 8 * REGBYTES(sp) - LOAD x9, 9 * REGBYTES(sp) - LOAD x10, 10 * REGBYTES(sp) - LOAD x11, 11 * REGBYTES(sp) - LOAD x12, 12 * REGBYTES(sp) - LOAD x13, 13 * REGBYTES(sp) - LOAD x14, 14 * REGBYTES(sp) - LOAD x15, 15 * REGBYTES(sp) - LOAD x16, 16 * REGBYTES(sp) - LOAD x17, 17 * REGBYTES(sp) - LOAD x18, 18 * REGBYTES(sp) - LOAD x19, 19 * REGBYTES(sp) - LOAD x20, 20 * REGBYTES(sp) - LOAD x21, 21 * REGBYTES(sp) - LOAD x22, 22 * REGBYTES(sp) - LOAD x23, 23 * REGBYTES(sp) - LOAD x24, 24 * REGBYTES(sp) - LOAD x25, 25 * REGBYTES(sp) - LOAD x26, 26 * REGBYTES(sp) - LOAD x27, 27 * REGBYTES(sp) - LOAD x28, 28 * REGBYTES(sp) - LOAD x29, 29 * REGBYTES(sp) - LOAD x30, 30 * REGBYTES(sp) - LOAD x31, 31 * REGBYTES(sp) - - /* restore user sp */ - LOAD sp, 32 * REGBYTES(sp) -.endm - -.macro RESTORE_SYS_GP - .option push - .option norelax - la gp, __global_pointer$ - .option pop -.endm - -.macro OPEN_INTERRUPT - csrsi sstatus, 2 -.endm - -.macro CLOSE_INTERRUPT - csrci sstatus, 2 -.endm - -#endif /* __ASSEMBLY__ */ - -#endif /* __STACKFRAME_H__ */ diff --git a/libcpu/risc-v/common64/startup_gcc.S b/libcpu/risc-v/common64/startup_gcc.S deleted file mode 100644 index 184b48a1aeb..00000000000 --- a/libcpu/risc-v/common64/startup_gcc.S +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2006-2018, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/01 Bernard The first version - * 2018/12/27 Jesven Add SMP support - * 2020/6/12 Xim Port to QEMU and remove SMP support - * 2024-06-30 Shell Support of kernel remapping - */ - -#include -#include - - .data - .global boot_hartid /* global varible rt_boot_hartid in .data section */ -boot_hartid: - .word 0xdeadbeef - - .global _start - .section ".start", "ax" -_start: - j 1f - .word 0xdeadbeef - .align 3 - .global g_wake_up - g_wake_up: - .dword 1 - .dword 0 -1: - /* save hartid */ - la t0, boot_hartid /* global varible rt_boot_hartid */ - mv t1, a0 /* get hartid in S-mode frome a0 register */ - sw t1, (t0) /* store t1 register low 4 bits in memory address which is stored in t0 */ - - /* clear Interrupt Registers */ - csrw sie, 0 - csrw sip, 0 - /* set Trap Vector Base Address Register */ - la t0, trap_entry - csrw stvec, t0 - - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10,0 - li x11,0 - li x12,0 - li x13,0 - li x14,0 - li x15,0 - li x16,0 - li x17,0 - li x18,0 - li x19,0 - li x20,0 - li x21,0 - li x22,0 - li x23,0 - li x24,0 - li x25,0 - li x26,0 - li x27,0 - li x28,0 - li x29,0 - li x30,0 - li x31,0 - - /* set to disable FPU */ - li t0, SSTATUS_FS + SSTATUS_VS - csrc sstatus, t0 - li t0, SSTATUS_SUM - csrs sstatus, t0 - -.option push -.option norelax - la gp, __global_pointer$ -.option pop - - /* removed SMP support here */ - la sp, __stack_start__ - li t0, __STACKSIZE__ - add sp, sp, t0 - - /** - * sscratch is always zero on kernel mode - */ - csrw sscratch, zero - call init_bss -#ifdef ARCH_MM_MMU - call rt_hw_mem_setup_early - call rt_kmem_pvoff - /* a0 := pvoff */ - beq a0, zero, 1f - - /* relocate pc */ - la x1, _after_pc_relocation - sub x1, x1, a0 - ret -_after_pc_relocation: - /* relocate gp */ - sub gp, gp, a0 - - /* relocate context: sp */ - la sp, __stack_start__ - li t0, __STACKSIZE__ - add sp, sp, t0 - - /* reset s0-fp */ - mv s0, zero - - /* relocate stvec */ - la t0, trap_entry - csrw stvec, t0 -1: -#endif - call sbi_init - call primary_cpu_entry - -_never_return_here: - j . - -.global _start_link_addr -_start_link_addr: - .dword __text_start diff --git a/libcpu/risc-v/common64/tick.c b/libcpu/risc-v/common64/tick.c deleted file mode 100644 index 8e8ff86a748..00000000000 --- a/libcpu/risc-v/common64/tick.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting code. - * 2024/07/08 Shell Using CPUTIME as tick - */ - -#include -#include - -#include -#include -#include "sbi.h" - -#ifdef RT_USING_KTIME -#include -#endif - -static volatile unsigned long tick_cycles = 0; - -int tick_isr(void) -{ - rt_tick_increase(); - sbi_set_timer(clock_cpu_gettime() + tick_cycles); - return 0; -} - -/* BSP should config clockbase frequency */ -RT_STATIC_ASSERT(defined_clockbase_freq, CPUTIME_TIMER_FREQ != 0); - -/* Sets and enable the timer interrupt */ -int rt_hw_tick_init(void) -{ - /* calculate the tick cycles */ - tick_cycles = CPUTIME_TIMER_FREQ / RT_TICK_PER_SECOND; - - /* Clear the Supervisor-Timer bit in SIE */ - clear_csr(sie, SIP_STIP); - - /* Init riscv timer */ - riscv_cputime_init(); - - /* Set timer */ - sbi_set_timer(clock_cpu_gettime() + tick_cycles); - -#ifdef RT_USING_KTIME - rt_ktime_cputimer_init(); -#endif - /* Enable the Supervisor-Timer bit in SIE */ - set_csr(sie, SIP_STIP); - - return 0; -} - -/** - * This function will delay for some us. - * - * @param us the delay time of us - */ -void rt_hw_us_delay(rt_uint32_t us) -{ - unsigned long start_time; - unsigned long end_time; - unsigned long run_time; - - start_time = clock_cpu_gettime(); - end_time = start_time + us * (CPUTIME_TIMER_FREQ / 1000000); - do - { - run_time = clock_cpu_gettime(); - } while(run_time < end_time); -} diff --git a/libcpu/risc-v/common64/tick.h b/libcpu/risc-v/common64/tick.h deleted file mode 100644 index 6d0e8a90b68..00000000000 --- a/libcpu/risc-v/common64/tick.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/28 Bernard The unify RISC-V porting code. - */ - -#ifndef TICK_H__ -#define TICK_H__ - -int tick_isr(void); -int rt_hw_tick_init(void); - -#endif diff --git a/libcpu/risc-v/common64/tlb.h b/libcpu/risc-v/common64/tlb.h deleted file mode 100644 index 5697ca61f69..00000000000 --- a/libcpu/risc-v/common64/tlb.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-28 WangXiaoyao the first version - */ -#ifndef __TLB_H__ -#define __TLB_H__ - -#include -#include - -#include -#include -#include "sbi.h" -#include "riscv_mmu.h" - -#define HANDLE_FAULT(ret) \ - if (__builtin_expect((ret) != SBI_SUCCESS, 0)) \ - LOG_W("%s failed", __FUNCTION__); - -static inline void rt_hw_tlb_invalidate_all(void) -{ - uintptr_t mask = -1ul; - HANDLE_FAULT(sbi_remote_sfence_vma(&mask, -1ul, 0, mask)); -} - -static inline void rt_hw_tlb_invalidate_all_local(void) -{ - __asm__ volatile("sfence.vma" ::: "memory"); -} - -static inline void rt_hw_tlb_invalidate_aspace(rt_aspace_t aspace) -{ - // TODO ASID - rt_hw_tlb_invalidate_all_local(); -} - -static inline void rt_hw_tlb_invalidate_page(rt_aspace_t aspace, void *start) -{ - __asm__ volatile("sfence.vma %0, zero" ::"r"(start) : "memory"); -} - -static inline void rt_hw_tlb_invalidate_range(rt_aspace_t aspace, void *start, - size_t size, size_t stride) -{ - // huge page is taking as normal page - if (size <= ARCH_PAGE_SIZE) - { - rt_hw_tlb_invalidate_page(aspace, start); - } - else - { - rt_hw_tlb_invalidate_aspace(aspace); - } -} - -#endif /* __TLB_H__ */ diff --git a/libcpu/risc-v/common64/trap.c b/libcpu/risc-v/common64/trap.c deleted file mode 100644 index 1b79b73950c..00000000000 --- a/libcpu/risc-v/common64/trap.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-12-08 RT-Thread first version - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef RT_USING_SMART -#include -#endif - -#define DBG_TAG "libcpu.trap" -#define DBG_LVL DBG_INFO -#include - -void dump_regs(struct rt_hw_stack_frame *regs) -{ - rt_kprintf("--------------Dump Registers-----------------\n"); - - rt_kprintf("Function Registers:\n"); - rt_kprintf("\tra(x1) = %p\tuser_sp = %p\n", regs->ra, - regs->user_sp_exc_stack); - rt_kprintf("\tgp(x3) = %p\ttp(x4) = %p\n", regs->gp, regs->tp); - rt_kprintf("Temporary Registers:\n"); - rt_kprintf("\tt0(x5) = %p\tt1(x6) = %p\n", regs->t0, regs->t1); - rt_kprintf("\tt2(x7) = %p\n", regs->t2); - rt_kprintf("\tt3(x28) = %p\tt4(x29) = %p\n", regs->t3, regs->t4); - rt_kprintf("\tt5(x30) = %p\tt6(x31) = %p\n", regs->t5, regs->t6); - rt_kprintf("Saved Registers:\n"); - rt_kprintf("\ts0/fp(x8) = %p\ts1(x9) = %p\n", regs->s0_fp, regs->s1); - rt_kprintf("\ts2(x18) = %p\ts3(x19) = %p\n", regs->s2, regs->s3); - rt_kprintf("\ts4(x20) = %p\ts5(x21) = %p\n", regs->s4, regs->s5); - rt_kprintf("\ts6(x22) = %p\ts7(x23) = %p\n", regs->s6, regs->s7); - rt_kprintf("\ts8(x24) = %p\ts9(x25) = %p\n", regs->s8, regs->s9); - rt_kprintf("\ts10(x26) = %p\ts11(x27) = %p\n", regs->s10, regs->s11); - rt_kprintf("Function Arguments Registers:\n"); - rt_kprintf("\ta0(x10) = %p\ta1(x11) = %p\n", regs->a0, regs->a1); - rt_kprintf("\ta2(x12) = %p\ta3(x13) = %p\n", regs->a2, regs->a3); - rt_kprintf("\ta4(x14) = %p\ta5(x15) = %p\n", regs->a4, regs->a5); - rt_kprintf("\ta6(x16) = %p\ta7(x17) = %p\n", regs->a6, regs->a7); - rt_kprintf("sstatus = %p\n", regs->sstatus); - rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) - ? "Supervisor Interrupt Enabled" - : "Supervisor Interrupt Disabled"); - rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) - ? "Last Time Supervisor Interrupt Enabled" - : "Last Time Supervisor Interrupt Disabled"); - rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) - ? "Last Privilege is Supervisor Mode" - : "Last Privilege is User Mode"); - rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) - ? "Permit to Access User Page" - : "Not Permit to Access User Page"); - rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) - ? "Permit to Read Executable-only Page" - : "Not Permit to Read Executable-only Page"); - rt_ubase_t satp_v = read_csr(satp); - rt_kprintf("satp = %p\n", satp_v); - rt_kprintf("\tCurrent Page Table(Physical) = %p\n", - __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT); - rt_kprintf("\tCurrent ASID = %p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) - << PAGE_OFFSET_BIT); - const char *mode_str = "Unknown Address Translation/Protection Mode"; - - switch (__MASKVALUE(satp_v >> 60, __MASK(4))) - { - case 0: - mode_str = "No Address Translation/Protection Mode"; - break; - - case 8: - mode_str = "Page-based 39-bit Virtual Addressing Mode"; - break; - - case 9: - mode_str = "Page-based 48-bit Virtual Addressing Mode"; - break; - } - - rt_kprintf("\tMode = %s\n", mode_str); - rt_kprintf("-----------------Dump OK---------------------\n"); -} - -static const char *Exception_Name[] = {"Instruction Address Misaligned", - "Instruction Access Fault", - "Illegal Instruction", - "Breakpoint", - "Load Address Misaligned", - "Load Access Fault", - "Store/AMO Address Misaligned", - "Store/AMO Access Fault", - "Environment call from U-mode", - "Environment call from S-mode", - "Reserved-10", - "Reserved-11", - "Instruction Page Fault", - "Load Page Fault", - "Reserved-14", - "Store/AMO Page Fault"}; - -static const char *Interrupt_Name[] = { - "User Software Interrupt", - "Supervisor Software Interrupt", - "Reversed-2", - "Reversed-3", - "User Timer Interrupt", - "Supervisor Timer Interrupt", - "Reversed-6", - "Reversed-7", - "User External Interrupt", - "Supervisor External Interrupt", - "Reserved-10", - "Reserved-11", -}; - -#ifndef RT_USING_SMP -static volatile int nested = 0; -#define ENTER_TRAP nested += 1 -#define EXIT_TRAP nested -= 1 -#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \ - if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe) -#endif /* RT_USING_SMP */ - -static const char *get_exception_msg(int id) -{ - const char *msg; - if (id < sizeof(Exception_Name) / sizeof(const char *)) - { - msg = Exception_Name[id]; - } - else - { - msg = "Unknown Exception"; - } - return msg; -} - -#ifdef RT_USING_SMART -#include "lwp.h" -void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, - struct rt_hw_stack_frame *sp) -{ - rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL)); - struct rt_lwp *lwp; - - /* user page fault */ - enum rt_mm_fault_op fault_op; - enum rt_mm_fault_type fault_type; - switch (id) - { - case EP_LOAD_PAGE_FAULT: - fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_GENERIC_MMU; - break; - case EP_LOAD_ACCESS_FAULT: - fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - case EP_LOAD_ADDRESS_MISALIGNED: - fault_op = MM_FAULT_OP_READ; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - case EP_STORE_PAGE_FAULT: - fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_GENERIC_MMU; - break; - case EP_STORE_ACCESS_FAULT: - fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - case EP_STORE_ADDRESS_MISALIGNED: - fault_op = MM_FAULT_OP_WRITE; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - case EP_INSTRUCTION_PAGE_FAULT: - fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_GENERIC_MMU; - break; - case EP_INSTRUCTION_ACCESS_FAULT: - fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - case EP_INSTRUCTION_ADDRESS_MISALIGNED: - fault_op = MM_FAULT_OP_EXECUTE; - fault_type = MM_FAULT_TYPE_BUS_ERROR; - break; - default: - fault_op = 0; - } - - if (fault_op) - { - rt_base_t saved_stat; - lwp = lwp_self(); - struct rt_aspace_fault_msg msg = { - .fault_op = fault_op, - .fault_type = fault_type, - .fault_vaddr = (void *)stval, - }; - - __asm__ volatile("csrrsi %0, sstatus, 2" : "=r"(saved_stat)); - if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg)) - { - __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat)); - return; - } - __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat)); - } - LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id)); - LOG_E("scause:%p,stval:%p,sepc:%p\n", scause, stval, sepc); - dump_regs(sp); - - rt_thread_t cur_thr = rt_thread_self(); - struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc}; - rt_kprintf("fp = %p\n", frame.fp); - lwp_backtrace_frame(cur_thr, &frame); - - LOG_E("User Fault, killing thread: %s", cur_thr->parent.name); - - EXIT_TRAP; - sys_exit_group(-1); -} -#endif - -#ifdef ARCH_RISCV_VECTOR -static void vector_enable(struct rt_hw_stack_frame *sp) -{ - sp->sstatus |= SSTATUS_VS_INITIAL; -} - -/** - * detect V/D support, and do not distinguish V/D instruction - */ -static int illegal_inst_recoverable(rt_ubase_t stval, - struct rt_hw_stack_frame *sp) -{ - // first 7 bits is opcode - int opcode = stval & 0x7f; - int csr = (stval & 0xFFF00000) >> 20; - // ref riscv-v-spec-1.0, [Vector Instruction Formats] - int width = ((stval & 0x7000) >> 12) - 1; - int flag = 0; - - switch (opcode) - { - case 0x57: // V - case 0x27: // scalar FLOAT - case 0x07: - case 0x73: // CSR - flag = 1; - break; - } - - if (flag) - { - vector_enable(sp); - } - - return flag; -} -#endif - -static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval, - rt_ubase_t epc, - struct rt_hw_stack_frame *eframe) -{ - LOG_E("\n-------- [SEVER ERROR] --------"); - LOG_E("Nested trap detected"); - LOG_E("scause:%p,stval:%p,sepc:%p\n", cause, tval, epc); - dump_regs(eframe); - rt_hw_cpu_shutdown(); -} - -#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP) -#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT) - -/* Trap entry */ -void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, - struct rt_hw_stack_frame *sp) -{ - ENTER_TRAP; - rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL)); - const char *msg; - - /* supervisor external interrupt */ - if ((SCAUSE_INTERRUPT & scause) && - SCAUSE_S_EXTERNAL_INTR == (scause & 0xff)) - { - rt_interrupt_enter(); - plic_handle_irq(); - rt_interrupt_leave(); - } - else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause) - { - /* supervisor timer */ - rt_interrupt_enter(); - tick_isr(); - rt_interrupt_leave(); - } - else - { - if (SCAUSE_INTERRUPT & scause) - { - if (id < sizeof(Interrupt_Name) / sizeof(const char *)) - { - msg = Interrupt_Name[id]; - } - else - { - msg = "Unknown Interrupt"; - } - - LOG_E("Unhandled Interrupt %ld:%s\n", id, msg); - } - else - { -#ifdef ARCH_RISCV_VECTOR - if (scause == 0x2) - { - if (!(sp->sstatus & SSTATUS_VS) && - illegal_inst_recoverable(stval, sp)) - goto _exit; - } -#endif /* ARCH_RISCV_VECTOR */ -#ifdef RT_USING_SMART - if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE)) - { - handle_user(scause, stval, sepc, sp); - // if handle_user() return here, jump to u mode then - goto _exit; - } -#endif - - // handle kernel exception: - rt_kprintf("Unhandled Exception %ld:%s\n", id, - get_exception_msg(id)); - } - - // trap cannot nested when handling another trap / interrupt - CHECK_NESTED_PANIC(scause, stval, sepc, sp); - - rt_kprintf("scause:%p,stval:%p,sepc:%p\n", scause, stval, sepc); - dump_regs(sp); - - rt_thread_t cur_thr = rt_thread_self(); - rt_kprintf("--------------Thread list--------------\n"); - rt_kprintf("current thread: %s\n", cur_thr->parent.name); - - rt_kprintf("--------------Backtrace--------------\n"); - struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc}; - -#ifdef RT_USING_SMART - if (!(sp->sstatus & 0x100)) - { - lwp_backtrace_frame(cur_thr, &frame); - } - else -#endif - { - rt_backtrace_frame(cur_thr, &frame); - } - - while (1) - ; - } -_exit: - EXIT_TRAP; - return; -} diff --git a/libcpu/risc-v/link.lds.S b/libcpu/risc-v/link.lds.S new file mode 100644 index 00000000000..d0d3281d667 --- /dev/null +++ b/libcpu/risc-v/link.lds.S @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Date Author Notes + * 2020-12-12 bernard first version + */ + +#define __ASSEMBLY__ + +#include "rtconfig.h" + +#ifndef __riscv_xlen +#ifdef ARCH_CPU_64BIT +#define __riscv_xlen 64 +#else +#define __riscv_xlen 32 +#endif +#endif + +#include "page_def.h" + +OUTPUT_ARCH(riscv) + +#ifndef ARCH_TEXT_OFFSET +#if __riscv_xlen == 64 +#define ARCH_TEXT_OFFSET 0x200000 +#elif __riscv_xlen == 32 +#define ARCH_TEXT_OFFSET 0x400000 +#else +#error "Unexpected __riscv_xlen" +#endif +#endif + +#ifndef ARCH_RAM_OFFSET +#define ARCH_RAM_OFFSET 0 +#endif + +PHDRS +{ + text PT_LOAD FLAGS(5); /* PF_R(4) | PF_X(1) = 0x5 (RX) */ + data PT_LOAD FLAGS(6); /* PF_R(4) | PF_W(2) = 0x6 (RW) */ +} + +SECTIONS +{ + _text_offset = ARCH_TEXT_OFFSET; + +#ifdef RT_USING_SMART + . = KERNEL_VADDR_START + _text_offset; +#else + . = ARCH_RAM_OFFSET + _text_offset; +#endif + + .text : + { + PROVIDE(__text_start = .); + + KEEP(*(.text.start)) /* The start point */ + *(.text) /* Remaining code */ + *(.text.*) /* Remaining code */ + + *(.rodata) /* Read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for utest */ + . = ALIGN(RISCV_SZPTR); + PROVIDE(__rt_utest_tc_tab_start = .); + KEEP(*(UtestTcTab)) + PROVIDE(__rt_utest_tc_tab_end = .); + + /* section information for finsh shell */ + . = ALIGN(RISCV_SZPTR); + PROVIDE(__fsymtab_start = .); + KEEP(*(FSymTab)) + PROVIDE(__fsymtab_end = .); + . = ALIGN(RISCV_SZPTR); + PROVIDE(__vsymtab_start = .); + KEEP(*(VSymTab)) + PROVIDE(__vsymtab_end = .); + . = ALIGN(RISCV_SZPTR); + + /* section information for modules */ + . = ALIGN(RISCV_SZPTR); + PROVIDE(__rtmsymtab_start = .); + KEEP(*(RTMSymTab)) + PROVIDE(__rtmsymtab_end = .); + + /* section information for initialization */ + . = ALIGN(RISCV_SZPTR); + PROVIDE(__rt_init_start = .); + KEEP(*(SORT(.rti_fn*))) + PROVIDE(__rt_init_end = .); + + /* section information for rt_ofw. */ + . = ALIGN(RISCV_SZPTR); + PROVIDE(__rt_ofw_data_start = .); + KEEP(*(SORT(.rt_ofw_data.*))) + PROVIDE(__rt_ofw_data_end = .); + . = ALIGN(RISCV_SZPTR); + + /* section information for usb usbh_class_info */ + . = ALIGN(RISCV_SZPTR); + __usbh_class_info_start__ = .; + KEEP(*(.usbh_class_info)) + . = ALIGN(RISCV_SZPTR); + __usbh_class_info_end__ = .; + + PROVIDE(__text_end = .); + } :text + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + + . = ALIGN(RISCV_SZPTR); + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(ARCH_PAGE_SIZE); + PROVIDE(__global_pointer$ = . + 0x800); + + *(.sdata) + *(.sdata.*) + + *(.rel.local) + } :data + + . = ALIGN(RISCV_SZPTR); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE(__dtors_end__ = .); + } + + .bss : + { + /* + * We need some free space to page, move .bss.noclean.* + * to optimize size. + */ + PROVIDE(__bss_noclean_start = .); + *(.bss.noclean.*) + PROVIDE(__bss_noclean_end = .); + . = ALIGN(RISCV_SZPTR); + PROVIDE(__bss_start = .); + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.dynbss) + *(COMMON) + . = ALIGN(RISCV_SZPTR); + PROVIDE(__bss_end = .); + } + + .percpu (NOLOAD) : + { + #if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) + /* Align for MMU early map */ + . = ALIGN(SUPPER_PAGE_SIZE); + #endif /* RT_USING_SMP && ARCH_MM_MMU */ + PROVIDE(__percpu_start = .); + *(.percpu) + #if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) + . = ALIGN(ARCH_PAGE_SIZE); + #endif /* RT_USING_SMP && ARCH_MM_MMU */ + PROVIDE(__percpu_end = .); + + /* Clone the area */ + . = __percpu_end + (__percpu_end - __percpu_start) * (RT_CPUS_NR - 1); + #if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) + /* Align for MMU early map */ + . = ALIGN(SUPPER_PAGE_SIZE); + #endif /* RT_USING_SMP && ARCH_MM_MMU */ + PROVIDE(__percpu_real_end = .); + + #if defined(RT_USING_SMP) && defined(ARCH_MM_MMU) + ASSERT(((__percpu_real_end - __percpu_start) / ARCH_PAGE_SIZE) <= (ARCH_PAGE_SIZE / RISCV_SZPTR), "Not enough L0 pages to map per-CPU"); + #endif /* RT_USING_SMP && ARCH_MM_MMU */ + } + + /* + * We should make the bootloader know the size of memory we need, + * so we MUST calc the image's size with section '.percpu'. + */ + _end = .; + + /* Stabs debugging sections. */ + .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. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .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) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + __data_size = SIZEOF(.data); + __bss_size = SIZEOF(.bss); +} diff --git a/libcpu/risc-v/rv64/SConscript b/libcpu/risc-v/rv64/SConscript deleted file mode 100755 index 05c70ba1b96..00000000000 --- a/libcpu/risc-v/rv64/SConscript +++ /dev/null @@ -1,12 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') -CPPPATH = [cwd] -ASFLAGS = ' -I ' + cwd - -group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH, ASFLAGS = ASFLAGS) - -Return('group') diff --git a/libcpu/risc-v/rv64/cpuport.c b/libcpu/risc-v/rv64/cpuport.c deleted file mode 100644 index cb222821b9d..00000000000 --- a/libcpu/risc-v/rv64/cpuport.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024-04-26 Shell lockless rt_completion - */ - -#include - -#undef rt_hw_isb -rt_weak void rt_hw_isb(void) -{ - return ; -} diff --git a/libcpu/risc-v/rv64/encoding.h b/libcpu/risc-v/rv64/encoding.h deleted file mode 100644 index 25f1b771db1..00000000000 --- a/libcpu/risc-v/rv64/encoding.h +++ /dev/null @@ -1,1331 +0,0 @@ -// See LICENSE for license details. - -#ifndef RISCV_CSR_ENCODING_H -#define RISCV_CSR_ENCODING_H - -#define MSTATUS_UIE 0x00000001 -#define MSTATUS_SIE 0x00000002 -#define MSTATUS_HIE 0x00000004 -#define MSTATUS_MIE 0x00000008 -#define MSTATUS_UPIE 0x00000010 -#define MSTATUS_SPIE 0x00000020 -#define MSTATUS_HPIE 0x00000040 -#define MSTATUS_MPIE 0x00000080 -#define MSTATUS_SPP 0x00000100 -#define MSTATUS_HPP 0x00000600 -#define MSTATUS_MPP 0x00001800 -#define MSTATUS_FS 0x00006000 -#define MSTATUS_XS 0x00018000 -#define MSTATUS_MPRV 0x00020000 -#define MSTATUS_PUM 0x00040000 -#define MSTATUS_MXR 0x00080000 -#define MSTATUS_VM 0x1F000000 -#define MSTATUS32_SD 0x80000000 -#define MSTATUS64_SD 0x8000000000000000 - -#define SSTATUS_UIE 0x00000001 -#define SSTATUS_SIE 0x00000002 -#define SSTATUS_UPIE 0x00000010 -#define SSTATUS_SPIE 0x00000020 -#define SSTATUS_SPP 0x00000100 -#define SSTATUS_FS 0x00006000 /* Floating-point Status */ -#define SSTATUS_FS_INITIAL 0x00002000 -#define SSTATUS_FS_CLEAN 0x00004000 -#define SSTATUS_FS_DIRTY 0x00006000 -#define SSTATUS_XS 0x00018000 -#define SSTATUS_SUM 0x00040000 -#define SSTATUS32_SD 0x80000000 -#define SSTATUS64_SD 0x8000000000000000 - -#define DCSR_XDEBUGVER (3U<<30) -#define DCSR_NDRESET (1<<29) -#define DCSR_FULLRESET (1<<28) -#define DCSR_EBREAKM (1<<15) -#define DCSR_EBREAKH (1<<14) -#define DCSR_EBREAKS (1<<13) -#define DCSR_EBREAKU (1<<12) -#define DCSR_STOPCYCLE (1<<10) -#define DCSR_STOPTIME (1<<9) -#define DCSR_CAUSE (7<<6) -#define DCSR_DEBUGINT (1<<5) -#define DCSR_HALT (1<<3) -#define DCSR_STEP (1<<2) -#define DCSR_PRV (3<<0) - -#define DCSR_CAUSE_NONE 0 -#define DCSR_CAUSE_SWBP 1 -#define DCSR_CAUSE_HWBP 2 -#define DCSR_CAUSE_DEBUGINT 3 -#define DCSR_CAUSE_STEP 4 -#define DCSR_CAUSE_HALT 5 - -#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) -#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) -#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) - -#define MCONTROL_SELECT (1<<19) -#define MCONTROL_TIMING (1<<18) -#define MCONTROL_ACTION (0x3f<<12) -#define MCONTROL_CHAIN (1<<11) -#define MCONTROL_MATCH (0xf<<7) -#define MCONTROL_M (1<<6) -#define MCONTROL_H (1<<5) -#define MCONTROL_S (1<<4) -#define MCONTROL_U (1<<3) -#define MCONTROL_EXECUTE (1<<2) -#define MCONTROL_STORE (1<<1) -#define MCONTROL_LOAD (1<<0) - -#define MCONTROL_TYPE_NONE 0 -#define MCONTROL_TYPE_MATCH 2 - -#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 -#define MCONTROL_ACTION_DEBUG_MODE 1 -#define MCONTROL_ACTION_TRACE_START 2 -#define MCONTROL_ACTION_TRACE_STOP 3 -#define MCONTROL_ACTION_TRACE_EMIT 4 - -#define MCONTROL_MATCH_EQUAL 0 -#define MCONTROL_MATCH_NAPOT 1 -#define MCONTROL_MATCH_GE 2 -#define MCONTROL_MATCH_LT 3 -#define MCONTROL_MATCH_MASK_LOW 4 -#define MCONTROL_MATCH_MASK_HIGH 5 - -#define MIP_SSIP (1 << IRQ_S_SOFT) -#define MIP_HSIP (1 << IRQ_H_SOFT) -#define MIP_MSIP (1 << IRQ_M_SOFT) -#define MIP_STIP (1 << IRQ_S_TIMER) -#define MIP_HTIP (1 << IRQ_H_TIMER) -#define MIP_MTIP (1 << IRQ_M_TIMER) -#define MIP_SEIP (1 << IRQ_S_EXT) -#define MIP_HEIP (1 << IRQ_H_EXT) -#define MIP_MEIP (1 << IRQ_M_EXT) - -#define SIP_SSIP MIP_SSIP /* software interrupt */ -#define SIP_STIP MIP_STIP /* timer interrupt */ -#define SIP_SEIP MIP_SEIP /* ext interrupt */ - -#define SIE_SSIE (1 << IRQ_S_SOFT) -#define SIE_STIE (1 << IRQ_S_TIMER) -#define SIE_SEIE (1 << IRQ_S_EXT) - -#define RISCV_XLEN 64 - -#define SCAUSE_INTERRUPT (1UL << (RISCV_XLEN - 1)) - -#define SCAUSE_S_SOFTWARE_INTR 1 -#define SCAUSE_S_TIMER_INTR 5 -#define SCAUSE_S_EXTERNAL_INTR 9 - -#define PRV_U 0 -#define PRV_S 1 -#define PRV_H 2 -#define PRV_M 3 - -#define VM_MBARE 0 -#define VM_MBB 1 -#define VM_MBBID 2 -#define VM_SV32 8 -#define VM_SV39 9 -#define VM_SV48 10 - -#define IRQ_S_SOFT 1 -#define IRQ_H_SOFT 2 -#define IRQ_M_SOFT 3 -#define IRQ_S_TIMER 5 -#define IRQ_H_TIMER 6 -#define IRQ_M_TIMER 7 -#define IRQ_S_EXT 9 -#define IRQ_H_EXT 10 -#define IRQ_M_EXT 11 -#define IRQ_COP 12 -#define IRQ_HOST 13 - -#define DEFAULT_RSTVEC 0x00001000 -#define DEFAULT_NMIVEC 0x00001004 -#define DEFAULT_MTVEC 0x00001010 -#define CONFIG_STRING_ADDR 0x0000100C -#define EXT_IO_BASE 0x40000000 -#define DRAM_BASE 0x80000000 - -// page table entry (PTE) fields -#define PTE_V 0x001 // Valid -#define PTE_R 0x002 // Read -#define PTE_W 0x004 // Write -#define PTE_X 0x008 // Execute -#define PTE_U 0x010 // User -#define PTE_G 0x020 // Global -#define PTE_A 0x040 // Accessed -#define PTE_D 0x080 // Dirty -#define PTE_SOFT 0x300 // Reserved for Software - -#define PTE_PPN_SHIFT 10 - -#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) - -#ifdef __riscv - -#ifdef __riscv64 -# define MSTATUS_SD MSTATUS64_SD -# define SSTATUS_SD SSTATUS64_SD -# define RISCV_PGLEVEL_BITS 9 -#else -# define MSTATUS_SD MSTATUS32_SD -# define SSTATUS_SD SSTATUS32_SD -# define RISCV_PGLEVEL_BITS 10 -#endif /* end of __riscv64 */ - -#define RISCV_PGSHIFT 12 -#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) - -#ifndef __ASSEMBLY__ - -#ifdef __GNUC__ - -#define read_csr(reg) ({ unsigned long __tmp; \ - asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ - __tmp; }) - -#define write_csr(reg, val) ({ \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ - else \ - asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) - -#define swap_csr(reg, val) ({ unsigned long __tmp; \ - if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ - else \ - asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ - __tmp; }) - -#define set_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) - -#define clear_csr(reg, bit) ({ unsigned long __tmp; \ - if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ - else \ - asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ - __tmp; }) - -#define rdtime() read_csr(time) -#define rdcycle() read_csr(cycle) -#define rdinstret() read_csr(instret) - -#endif /* end of __GNUC__ */ - -#endif /* end of __ASSEMBLY__ */ - -#endif /* end of __riscv */ - -#endif /* end of RISCV_CSR_ENCODING_H */ - -/* Automatically generated by parse-opcodes */ -#ifndef RISCV_ENCODING_H -#define RISCV_ENCODING_H -#define MATCH_BEQ 0x63 -#define MASK_BEQ 0x707f -#define MATCH_BNE 0x1063 -#define MASK_BNE 0x707f -#define MATCH_BLT 0x4063 -#define MASK_BLT 0x707f -#define MATCH_BGE 0x5063 -#define MASK_BGE 0x707f -#define MATCH_BLTU 0x6063 -#define MASK_BLTU 0x707f -#define MATCH_BGEU 0x7063 -#define MASK_BGEU 0x707f -#define MATCH_JALR 0x67 -#define MASK_JALR 0x707f -#define MATCH_JAL 0x6f -#define MASK_JAL 0x7f -#define MATCH_LUI 0x37 -#define MASK_LUI 0x7f -#define MATCH_AUIPC 0x17 -#define MASK_AUIPC 0x7f -#define MATCH_ADDI 0x13 -#define MASK_ADDI 0x707f -#define MATCH_SLLI 0x1013 -#define MASK_SLLI 0xfc00707f -#define MATCH_SLTI 0x2013 -#define MASK_SLTI 0x707f -#define MATCH_SLTIU 0x3013 -#define MASK_SLTIU 0x707f -#define MATCH_XORI 0x4013 -#define MASK_XORI 0x707f -#define MATCH_SRLI 0x5013 -#define MASK_SRLI 0xfc00707f -#define MATCH_SRAI 0x40005013 -#define MASK_SRAI 0xfc00707f -#define MATCH_ORI 0x6013 -#define MASK_ORI 0x707f -#define MATCH_ANDI 0x7013 -#define MASK_ANDI 0x707f -#define MATCH_ADD 0x33 -#define MASK_ADD 0xfe00707f -#define MATCH_SUB 0x40000033 -#define MASK_SUB 0xfe00707f -#define MATCH_SLL 0x1033 -#define MASK_SLL 0xfe00707f -#define MATCH_SLT 0x2033 -#define MASK_SLT 0xfe00707f -#define MATCH_SLTU 0x3033 -#define MASK_SLTU 0xfe00707f -#define MATCH_XOR 0x4033 -#define MASK_XOR 0xfe00707f -#define MATCH_SRL 0x5033 -#define MASK_SRL 0xfe00707f -#define MATCH_SRA 0x40005033 -#define MASK_SRA 0xfe00707f -#define MATCH_OR 0x6033 -#define MASK_OR 0xfe00707f -#define MATCH_AND 0x7033 -#define MASK_AND 0xfe00707f -#define MATCH_ADDIW 0x1b -#define MASK_ADDIW 0x707f -#define MATCH_SLLIW 0x101b -#define MASK_SLLIW 0xfe00707f -#define MATCH_SRLIW 0x501b -#define MASK_SRLIW 0xfe00707f -#define MATCH_SRAIW 0x4000501b -#define MASK_SRAIW 0xfe00707f -#define MATCH_ADDW 0x3b -#define MASK_ADDW 0xfe00707f -#define MATCH_SUBW 0x4000003b -#define MASK_SUBW 0xfe00707f -#define MATCH_SLLW 0x103b -#define MASK_SLLW 0xfe00707f -#define MATCH_SRLW 0x503b -#define MASK_SRLW 0xfe00707f -#define MATCH_SRAW 0x4000503b -#define MASK_SRAW 0xfe00707f -#define MATCH_LB 0x3 -#define MASK_LB 0x707f -#define MATCH_LH 0x1003 -#define MASK_LH 0x707f -#define MATCH_LW 0x2003 -#define MASK_LW 0x707f -#define MATCH_LD 0x3003 -#define MASK_LD 0x707f -#define MATCH_LBU 0x4003 -#define MASK_LBU 0x707f -#define MATCH_LHU 0x5003 -#define MASK_LHU 0x707f -#define MATCH_LWU 0x6003 -#define MASK_LWU 0x707f -#define MATCH_SB 0x23 -#define MASK_SB 0x707f -#define MATCH_SH 0x1023 -#define MASK_SH 0x707f -#define MATCH_SW 0x2023 -#define MASK_SW 0x707f -#define MATCH_SD 0x3023 -#define MASK_SD 0x707f -#define MATCH_FENCE 0xf -#define MASK_FENCE 0x707f -#define MATCH_FENCE_I 0x100f -#define MASK_FENCE_I 0x707f -#define MATCH_MUL 0x2000033 -#define MASK_MUL 0xfe00707f -#define MATCH_MULH 0x2001033 -#define MASK_MULH 0xfe00707f -#define MATCH_MULHSU 0x2002033 -#define MASK_MULHSU 0xfe00707f -#define MATCH_MULHU 0x2003033 -#define MASK_MULHU 0xfe00707f -#define MATCH_DIV 0x2004033 -#define MASK_DIV 0xfe00707f -#define MATCH_DIVU 0x2005033 -#define MASK_DIVU 0xfe00707f -#define MATCH_REM 0x2006033 -#define MASK_REM 0xfe00707f -#define MATCH_REMU 0x2007033 -#define MASK_REMU 0xfe00707f -#define MATCH_MULW 0x200003b -#define MASK_MULW 0xfe00707f -#define MATCH_DIVW 0x200403b -#define MASK_DIVW 0xfe00707f -#define MATCH_DIVUW 0x200503b -#define MASK_DIVUW 0xfe00707f -#define MATCH_REMW 0x200603b -#define MASK_REMW 0xfe00707f -#define MATCH_REMUW 0x200703b -#define MASK_REMUW 0xfe00707f -#define MATCH_AMOADD_W 0x202f -#define MASK_AMOADD_W 0xf800707f -#define MATCH_AMOXOR_W 0x2000202f -#define MASK_AMOXOR_W 0xf800707f -#define MATCH_AMOOR_W 0x4000202f -#define MASK_AMOOR_W 0xf800707f -#define MATCH_AMOAND_W 0x6000202f -#define MASK_AMOAND_W 0xf800707f -#define MATCH_AMOMIN_W 0x8000202f -#define MASK_AMOMIN_W 0xf800707f -#define MATCH_AMOMAX_W 0xa000202f -#define MASK_AMOMAX_W 0xf800707f -#define MATCH_AMOMINU_W 0xc000202f -#define MASK_AMOMINU_W 0xf800707f -#define MATCH_AMOMAXU_W 0xe000202f -#define MASK_AMOMAXU_W 0xf800707f -#define MATCH_AMOSWAP_W 0x800202f -#define MASK_AMOSWAP_W 0xf800707f -#define MATCH_LR_W 0x1000202f -#define MASK_LR_W 0xf9f0707f -#define MATCH_SC_W 0x1800202f -#define MASK_SC_W 0xf800707f -#define MATCH_AMOADD_D 0x302f -#define MASK_AMOADD_D 0xf800707f -#define MATCH_AMOXOR_D 0x2000302f -#define MASK_AMOXOR_D 0xf800707f -#define MATCH_AMOOR_D 0x4000302f -#define MASK_AMOOR_D 0xf800707f -#define MATCH_AMOAND_D 0x6000302f -#define MASK_AMOAND_D 0xf800707f -#define MATCH_AMOMIN_D 0x8000302f -#define MASK_AMOMIN_D 0xf800707f -#define MATCH_AMOMAX_D 0xa000302f -#define MASK_AMOMAX_D 0xf800707f -#define MATCH_AMOMINU_D 0xc000302f -#define MASK_AMOMINU_D 0xf800707f -#define MATCH_AMOMAXU_D 0xe000302f -#define MASK_AMOMAXU_D 0xf800707f -#define MATCH_AMOSWAP_D 0x800302f -#define MASK_AMOSWAP_D 0xf800707f -#define MATCH_LR_D 0x1000302f -#define MASK_LR_D 0xf9f0707f -#define MATCH_SC_D 0x1800302f -#define MASK_SC_D 0xf800707f -#define MATCH_ECALL 0x73 -#define MASK_ECALL 0xffffffff -#define MATCH_EBREAK 0x100073 -#define MASK_EBREAK 0xffffffff -#define MATCH_URET 0x200073 -#define MASK_URET 0xffffffff -#define MATCH_SRET 0x10200073 -#define MASK_SRET 0xffffffff -#define MATCH_HRET 0x20200073 -#define MASK_HRET 0xffffffff -#define MATCH_MRET 0x30200073 -#define MASK_MRET 0xffffffff -#define MATCH_DRET 0x7b200073 -#define MASK_DRET 0xffffffff -#define MATCH_SFENCE_VM 0x10400073 -#define MASK_SFENCE_VM 0xfff07fff -#define MATCH_WFI 0x10500073 -#define MASK_WFI 0xffffffff -#define MATCH_CSRRW 0x1073 -#define MASK_CSRRW 0x707f -#define MATCH_CSRRS 0x2073 -#define MASK_CSRRS 0x707f -#define MATCH_CSRRC 0x3073 -#define MASK_CSRRC 0x707f -#define MATCH_CSRRWI 0x5073 -#define MASK_CSRRWI 0x707f -#define MATCH_CSRRSI 0x6073 -#define MASK_CSRRSI 0x707f -#define MATCH_CSRRCI 0x7073 -#define MASK_CSRRCI 0x707f -#define MATCH_FADD_S 0x53 -#define MASK_FADD_S 0xfe00007f -#define MATCH_FSUB_S 0x8000053 -#define MASK_FSUB_S 0xfe00007f -#define MATCH_FMUL_S 0x10000053 -#define MASK_FMUL_S 0xfe00007f -#define MATCH_FDIV_S 0x18000053 -#define MASK_FDIV_S 0xfe00007f -#define MATCH_FSGNJ_S 0x20000053 -#define MASK_FSGNJ_S 0xfe00707f -#define MATCH_FSGNJN_S 0x20001053 -#define MASK_FSGNJN_S 0xfe00707f -#define MATCH_FSGNJX_S 0x20002053 -#define MASK_FSGNJX_S 0xfe00707f -#define MATCH_FMIN_S 0x28000053 -#define MASK_FMIN_S 0xfe00707f -#define MATCH_FMAX_S 0x28001053 -#define MASK_FMAX_S 0xfe00707f -#define MATCH_FSQRT_S 0x58000053 -#define MASK_FSQRT_S 0xfff0007f -#define MATCH_FADD_D 0x2000053 -#define MASK_FADD_D 0xfe00007f -#define MATCH_FSUB_D 0xa000053 -#define MASK_FSUB_D 0xfe00007f -#define MATCH_FMUL_D 0x12000053 -#define MASK_FMUL_D 0xfe00007f -#define MATCH_FDIV_D 0x1a000053 -#define MASK_FDIV_D 0xfe00007f -#define MATCH_FSGNJ_D 0x22000053 -#define MASK_FSGNJ_D 0xfe00707f -#define MATCH_FSGNJN_D 0x22001053 -#define MASK_FSGNJN_D 0xfe00707f -#define MATCH_FSGNJX_D 0x22002053 -#define MASK_FSGNJX_D 0xfe00707f -#define MATCH_FMIN_D 0x2a000053 -#define MASK_FMIN_D 0xfe00707f -#define MATCH_FMAX_D 0x2a001053 -#define MASK_FMAX_D 0xfe00707f -#define MATCH_FCVT_S_D 0x40100053 -#define MASK_FCVT_S_D 0xfff0007f -#define MATCH_FCVT_D_S 0x42000053 -#define MASK_FCVT_D_S 0xfff0007f -#define MATCH_FSQRT_D 0x5a000053 -#define MASK_FSQRT_D 0xfff0007f -#define MATCH_FLE_S 0xa0000053 -#define MASK_FLE_S 0xfe00707f -#define MATCH_FLT_S 0xa0001053 -#define MASK_FLT_S 0xfe00707f -#define MATCH_FEQ_S 0xa0002053 -#define MASK_FEQ_S 0xfe00707f -#define MATCH_FLE_D 0xa2000053 -#define MASK_FLE_D 0xfe00707f -#define MATCH_FLT_D 0xa2001053 -#define MASK_FLT_D 0xfe00707f -#define MATCH_FEQ_D 0xa2002053 -#define MASK_FEQ_D 0xfe00707f -#define MATCH_FCVT_W_S 0xc0000053 -#define MASK_FCVT_W_S 0xfff0007f -#define MATCH_FCVT_WU_S 0xc0100053 -#define MASK_FCVT_WU_S 0xfff0007f -#define MATCH_FCVT_L_S 0xc0200053 -#define MASK_FCVT_L_S 0xfff0007f -#define MATCH_FCVT_LU_S 0xc0300053 -#define MASK_FCVT_LU_S 0xfff0007f -#define MATCH_FMV_X_S 0xe0000053 -#define MASK_FMV_X_S 0xfff0707f -#define MATCH_FCLASS_S 0xe0001053 -#define MASK_FCLASS_S 0xfff0707f -#define MATCH_FCVT_W_D 0xc2000053 -#define MASK_FCVT_W_D 0xfff0007f -#define MATCH_FCVT_WU_D 0xc2100053 -#define MASK_FCVT_WU_D 0xfff0007f -#define MATCH_FCVT_L_D 0xc2200053 -#define MASK_FCVT_L_D 0xfff0007f -#define MATCH_FCVT_LU_D 0xc2300053 -#define MASK_FCVT_LU_D 0xfff0007f -#define MATCH_FMV_X_D 0xe2000053 -#define MASK_FMV_X_D 0xfff0707f -#define MATCH_FCLASS_D 0xe2001053 -#define MASK_FCLASS_D 0xfff0707f -#define MATCH_FCVT_S_W 0xd0000053 -#define MASK_FCVT_S_W 0xfff0007f -#define MATCH_FCVT_S_WU 0xd0100053 -#define MASK_FCVT_S_WU 0xfff0007f -#define MATCH_FCVT_S_L 0xd0200053 -#define MASK_FCVT_S_L 0xfff0007f -#define MATCH_FCVT_S_LU 0xd0300053 -#define MASK_FCVT_S_LU 0xfff0007f -#define MATCH_FMV_S_X 0xf0000053 -#define MASK_FMV_S_X 0xfff0707f -#define MATCH_FCVT_D_W 0xd2000053 -#define MASK_FCVT_D_W 0xfff0007f -#define MATCH_FCVT_D_WU 0xd2100053 -#define MASK_FCVT_D_WU 0xfff0007f -#define MATCH_FCVT_D_L 0xd2200053 -#define MASK_FCVT_D_L 0xfff0007f -#define MATCH_FCVT_D_LU 0xd2300053 -#define MASK_FCVT_D_LU 0xfff0007f -#define MATCH_FMV_D_X 0xf2000053 -#define MASK_FMV_D_X 0xfff0707f -#define MATCH_FLW 0x2007 -#define MASK_FLW 0x707f -#define MATCH_FLD 0x3007 -#define MASK_FLD 0x707f -#define MATCH_FSW 0x2027 -#define MASK_FSW 0x707f -#define MATCH_FSD 0x3027 -#define MASK_FSD 0x707f -#define MATCH_FMADD_S 0x43 -#define MASK_FMADD_S 0x600007f -#define MATCH_FMSUB_S 0x47 -#define MASK_FMSUB_S 0x600007f -#define MATCH_FNMSUB_S 0x4b -#define MASK_FNMSUB_S 0x600007f -#define MATCH_FNMADD_S 0x4f -#define MASK_FNMADD_S 0x600007f -#define MATCH_FMADD_D 0x2000043 -#define MASK_FMADD_D 0x600007f -#define MATCH_FMSUB_D 0x2000047 -#define MASK_FMSUB_D 0x600007f -#define MATCH_FNMSUB_D 0x200004b -#define MASK_FNMSUB_D 0x600007f -#define MATCH_FNMADD_D 0x200004f -#define MASK_FNMADD_D 0x600007f -#define MATCH_C_NOP 0x1 -#define MASK_C_NOP 0xffff -#define MATCH_C_ADDI16SP 0x6101 -#define MASK_C_ADDI16SP 0xef83 -#define MATCH_C_JR 0x8002 -#define MASK_C_JR 0xf07f -#define MATCH_C_JALR 0x9002 -#define MASK_C_JALR 0xf07f -#define MATCH_C_EBREAK 0x9002 -#define MASK_C_EBREAK 0xffff -#define MATCH_C_LD 0x6000 -#define MASK_C_LD 0xe003 -#define MATCH_C_SD 0xe000 -#define MASK_C_SD 0xe003 -#define MATCH_C_ADDIW 0x2001 -#define MASK_C_ADDIW 0xe003 -#define MATCH_C_LDSP 0x6002 -#define MASK_C_LDSP 0xe003 -#define MATCH_C_SDSP 0xe002 -#define MASK_C_SDSP 0xe003 -#define MATCH_C_ADDI4SPN 0x0 -#define MASK_C_ADDI4SPN 0xe003 -#define MATCH_C_FLD 0x2000 -#define MASK_C_FLD 0xe003 -#define MATCH_C_LW 0x4000 -#define MASK_C_LW 0xe003 -#define MATCH_C_FLW 0x6000 -#define MASK_C_FLW 0xe003 -#define MATCH_C_FSD 0xa000 -#define MASK_C_FSD 0xe003 -#define MATCH_C_SW 0xc000 -#define MASK_C_SW 0xe003 -#define MATCH_C_FSW 0xe000 -#define MASK_C_FSW 0xe003 -#define MATCH_C_ADDI 0x1 -#define MASK_C_ADDI 0xe003 -#define MATCH_C_JAL 0x2001 -#define MASK_C_JAL 0xe003 -#define MATCH_C_LI 0x4001 -#define MASK_C_LI 0xe003 -#define MATCH_C_LUI 0x6001 -#define MASK_C_LUI 0xe003 -#define MATCH_C_SRLI 0x8001 -#define MASK_C_SRLI 0xec03 -#define MATCH_C_SRAI 0x8401 -#define MASK_C_SRAI 0xec03 -#define MATCH_C_ANDI 0x8801 -#define MASK_C_ANDI 0xec03 -#define MATCH_C_SUB 0x8c01 -#define MASK_C_SUB 0xfc63 -#define MATCH_C_XOR 0x8c21 -#define MASK_C_XOR 0xfc63 -#define MATCH_C_OR 0x8c41 -#define MASK_C_OR 0xfc63 -#define MATCH_C_AND 0x8c61 -#define MASK_C_AND 0xfc63 -#define MATCH_C_SUBW 0x9c01 -#define MASK_C_SUBW 0xfc63 -#define MATCH_C_ADDW 0x9c21 -#define MASK_C_ADDW 0xfc63 -#define MATCH_C_J 0xa001 -#define MASK_C_J 0xe003 -#define MATCH_C_BEQZ 0xc001 -#define MASK_C_BEQZ 0xe003 -#define MATCH_C_BNEZ 0xe001 -#define MASK_C_BNEZ 0xe003 -#define MATCH_C_SLLI 0x2 -#define MASK_C_SLLI 0xe003 -#define MATCH_C_FLDSP 0x2002 -#define MASK_C_FLDSP 0xe003 -#define MATCH_C_LWSP 0x4002 -#define MASK_C_LWSP 0xe003 -#define MATCH_C_FLWSP 0x6002 -#define MASK_C_FLWSP 0xe003 -#define MATCH_C_MV 0x8002 -#define MASK_C_MV 0xf003 -#define MATCH_C_ADD 0x9002 -#define MASK_C_ADD 0xf003 -#define MATCH_C_FSDSP 0xa002 -#define MASK_C_FSDSP 0xe003 -#define MATCH_C_SWSP 0xc002 -#define MASK_C_SWSP 0xe003 -#define MATCH_C_FSWSP 0xe002 -#define MASK_C_FSWSP 0xe003 -#define MATCH_CUSTOM0 0xb -#define MASK_CUSTOM0 0x707f -#define MATCH_CUSTOM0_RS1 0x200b -#define MASK_CUSTOM0_RS1 0x707f -#define MATCH_CUSTOM0_RS1_RS2 0x300b -#define MASK_CUSTOM0_RS1_RS2 0x707f -#define MATCH_CUSTOM0_RD 0x400b -#define MASK_CUSTOM0_RD 0x707f -#define MATCH_CUSTOM0_RD_RS1 0x600b -#define MASK_CUSTOM0_RD_RS1 0x707f -#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b -#define MASK_CUSTOM0_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM1 0x2b -#define MASK_CUSTOM1 0x707f -#define MATCH_CUSTOM1_RS1 0x202b -#define MASK_CUSTOM1_RS1 0x707f -#define MATCH_CUSTOM1_RS1_RS2 0x302b -#define MASK_CUSTOM1_RS1_RS2 0x707f -#define MATCH_CUSTOM1_RD 0x402b -#define MASK_CUSTOM1_RD 0x707f -#define MATCH_CUSTOM1_RD_RS1 0x602b -#define MASK_CUSTOM1_RD_RS1 0x707f -#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b -#define MASK_CUSTOM1_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM2 0x5b -#define MASK_CUSTOM2 0x707f -#define MATCH_CUSTOM2_RS1 0x205b -#define MASK_CUSTOM2_RS1 0x707f -#define MATCH_CUSTOM2_RS1_RS2 0x305b -#define MASK_CUSTOM2_RS1_RS2 0x707f -#define MATCH_CUSTOM2_RD 0x405b -#define MASK_CUSTOM2_RD 0x707f -#define MATCH_CUSTOM2_RD_RS1 0x605b -#define MASK_CUSTOM2_RD_RS1 0x707f -#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b -#define MASK_CUSTOM2_RD_RS1_RS2 0x707f -#define MATCH_CUSTOM3 0x7b -#define MASK_CUSTOM3 0x707f -#define MATCH_CUSTOM3_RS1 0x207b -#define MASK_CUSTOM3_RS1 0x707f -#define MATCH_CUSTOM3_RS1_RS2 0x307b -#define MASK_CUSTOM3_RS1_RS2 0x707f -#define MATCH_CUSTOM3_RD 0x407b -#define MASK_CUSTOM3_RD 0x707f -#define MATCH_CUSTOM3_RD_RS1 0x607b -#define MASK_CUSTOM3_RD_RS1 0x707f -#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b -#define MASK_CUSTOM3_RD_RS1_RS2 0x707f -#define CSR_FFLAGS 0x1 -#define CSR_FRM 0x2 -#define CSR_FCSR 0x3 -#define CSR_CYCLE 0xc00 -#define CSR_TIME 0xc01 -#define CSR_INSTRET 0xc02 -#define CSR_HPMCOUNTER3 0xc03 -#define CSR_HPMCOUNTER4 0xc04 -#define CSR_HPMCOUNTER5 0xc05 -#define CSR_HPMCOUNTER6 0xc06 -#define CSR_HPMCOUNTER7 0xc07 -#define CSR_HPMCOUNTER8 0xc08 -#define CSR_HPMCOUNTER9 0xc09 -#define CSR_HPMCOUNTER10 0xc0a -#define CSR_HPMCOUNTER11 0xc0b -#define CSR_HPMCOUNTER12 0xc0c -#define CSR_HPMCOUNTER13 0xc0d -#define CSR_HPMCOUNTER14 0xc0e -#define CSR_HPMCOUNTER15 0xc0f -#define CSR_HPMCOUNTER16 0xc10 -#define CSR_HPMCOUNTER17 0xc11 -#define CSR_HPMCOUNTER18 0xc12 -#define CSR_HPMCOUNTER19 0xc13 -#define CSR_HPMCOUNTER20 0xc14 -#define CSR_HPMCOUNTER21 0xc15 -#define CSR_HPMCOUNTER22 0xc16 -#define CSR_HPMCOUNTER23 0xc17 -#define CSR_HPMCOUNTER24 0xc18 -#define CSR_HPMCOUNTER25 0xc19 -#define CSR_HPMCOUNTER26 0xc1a -#define CSR_HPMCOUNTER27 0xc1b -#define CSR_HPMCOUNTER28 0xc1c -#define CSR_HPMCOUNTER29 0xc1d -#define CSR_HPMCOUNTER30 0xc1e -#define CSR_HPMCOUNTER31 0xc1f -#define CSR_SSTATUS 0x100 -#define CSR_SIE 0x104 -#define CSR_STVEC 0x105 -#define CSR_SSCRATCH 0x140 -#define CSR_SEPC 0x141 -#define CSR_SCAUSE 0x142 -#define CSR_SBADADDR 0x143 -#define CSR_SIP 0x144 -#define CSR_SPTBR 0x180 -#define CSR_MSTATUS 0x300 -#define CSR_MISA 0x301 -#define CSR_MEDELEG 0x302 -#define CSR_MIDELEG 0x303 -#define CSR_MIE 0x304 -#define CSR_MTVEC 0x305 -#define CSR_MSCRATCH 0x340 -#define CSR_MEPC 0x341 -#define CSR_MCAUSE 0x342 -#define CSR_MBADADDR 0x343 -#define CSR_MIP 0x344 -#define CSR_TSELECT 0x7a0 -#define CSR_TDATA1 0x7a1 -#define CSR_TDATA2 0x7a2 -#define CSR_TDATA3 0x7a3 -#define CSR_DCSR 0x7b0 -#define CSR_DPC 0x7b1 -#define CSR_DSCRATCH 0x7b2 -#define CSR_MCYCLE 0xb00 -#define CSR_MINSTRET 0xb02 -#define CSR_MHPMCOUNTER3 0xb03 -#define CSR_MHPMCOUNTER4 0xb04 -#define CSR_MHPMCOUNTER5 0xb05 -#define CSR_MHPMCOUNTER6 0xb06 -#define CSR_MHPMCOUNTER7 0xb07 -#define CSR_MHPMCOUNTER8 0xb08 -#define CSR_MHPMCOUNTER9 0xb09 -#define CSR_MHPMCOUNTER10 0xb0a -#define CSR_MHPMCOUNTER11 0xb0b -#define CSR_MHPMCOUNTER12 0xb0c -#define CSR_MHPMCOUNTER13 0xb0d -#define CSR_MHPMCOUNTER14 0xb0e -#define CSR_MHPMCOUNTER15 0xb0f -#define CSR_MHPMCOUNTER16 0xb10 -#define CSR_MHPMCOUNTER17 0xb11 -#define CSR_MHPMCOUNTER18 0xb12 -#define CSR_MHPMCOUNTER19 0xb13 -#define CSR_MHPMCOUNTER20 0xb14 -#define CSR_MHPMCOUNTER21 0xb15 -#define CSR_MHPMCOUNTER22 0xb16 -#define CSR_MHPMCOUNTER23 0xb17 -#define CSR_MHPMCOUNTER24 0xb18 -#define CSR_MHPMCOUNTER25 0xb19 -#define CSR_MHPMCOUNTER26 0xb1a -#define CSR_MHPMCOUNTER27 0xb1b -#define CSR_MHPMCOUNTER28 0xb1c -#define CSR_MHPMCOUNTER29 0xb1d -#define CSR_MHPMCOUNTER30 0xb1e -#define CSR_MHPMCOUNTER31 0xb1f -#define CSR_MUCOUNTEREN 0x320 -#define CSR_MSCOUNTEREN 0x321 -#define CSR_MHPMEVENT3 0x323 -#define CSR_MHPMEVENT4 0x324 -#define CSR_MHPMEVENT5 0x325 -#define CSR_MHPMEVENT6 0x326 -#define CSR_MHPMEVENT7 0x327 -#define CSR_MHPMEVENT8 0x328 -#define CSR_MHPMEVENT9 0x329 -#define CSR_MHPMEVENT10 0x32a -#define CSR_MHPMEVENT11 0x32b -#define CSR_MHPMEVENT12 0x32c -#define CSR_MHPMEVENT13 0x32d -#define CSR_MHPMEVENT14 0x32e -#define CSR_MHPMEVENT15 0x32f -#define CSR_MHPMEVENT16 0x330 -#define CSR_MHPMEVENT17 0x331 -#define CSR_MHPMEVENT18 0x332 -#define CSR_MHPMEVENT19 0x333 -#define CSR_MHPMEVENT20 0x334 -#define CSR_MHPMEVENT21 0x335 -#define CSR_MHPMEVENT22 0x336 -#define CSR_MHPMEVENT23 0x337 -#define CSR_MHPMEVENT24 0x338 -#define CSR_MHPMEVENT25 0x339 -#define CSR_MHPMEVENT26 0x33a -#define CSR_MHPMEVENT27 0x33b -#define CSR_MHPMEVENT28 0x33c -#define CSR_MHPMEVENT29 0x33d -#define CSR_MHPMEVENT30 0x33e -#define CSR_MHPMEVENT31 0x33f -#define CSR_MVENDORID 0xf11 -#define CSR_MARCHID 0xf12 -#define CSR_MIMPID 0xf13 -#define CSR_MHARTID 0xf14 -#define CSR_CYCLEH 0xc80 -#define CSR_TIMEH 0xc81 -#define CSR_INSTRETH 0xc82 -#define CSR_HPMCOUNTER3H 0xc83 -#define CSR_HPMCOUNTER4H 0xc84 -#define CSR_HPMCOUNTER5H 0xc85 -#define CSR_HPMCOUNTER6H 0xc86 -#define CSR_HPMCOUNTER7H 0xc87 -#define CSR_HPMCOUNTER8H 0xc88 -#define CSR_HPMCOUNTER9H 0xc89 -#define CSR_HPMCOUNTER10H 0xc8a -#define CSR_HPMCOUNTER11H 0xc8b -#define CSR_HPMCOUNTER12H 0xc8c -#define CSR_HPMCOUNTER13H 0xc8d -#define CSR_HPMCOUNTER14H 0xc8e -#define CSR_HPMCOUNTER15H 0xc8f -#define CSR_HPMCOUNTER16H 0xc90 -#define CSR_HPMCOUNTER17H 0xc91 -#define CSR_HPMCOUNTER18H 0xc92 -#define CSR_HPMCOUNTER19H 0xc93 -#define CSR_HPMCOUNTER20H 0xc94 -#define CSR_HPMCOUNTER21H 0xc95 -#define CSR_HPMCOUNTER22H 0xc96 -#define CSR_HPMCOUNTER23H 0xc97 -#define CSR_HPMCOUNTER24H 0xc98 -#define CSR_HPMCOUNTER25H 0xc99 -#define CSR_HPMCOUNTER26H 0xc9a -#define CSR_HPMCOUNTER27H 0xc9b -#define CSR_HPMCOUNTER28H 0xc9c -#define CSR_HPMCOUNTER29H 0xc9d -#define CSR_HPMCOUNTER30H 0xc9e -#define CSR_HPMCOUNTER31H 0xc9f -#define CSR_MCYCLEH 0xb80 -#define CSR_MINSTRETH 0xb82 -#define CSR_MHPMCOUNTER3H 0xb83 -#define CSR_MHPMCOUNTER4H 0xb84 -#define CSR_MHPMCOUNTER5H 0xb85 -#define CSR_MHPMCOUNTER6H 0xb86 -#define CSR_MHPMCOUNTER7H 0xb87 -#define CSR_MHPMCOUNTER8H 0xb88 -#define CSR_MHPMCOUNTER9H 0xb89 -#define CSR_MHPMCOUNTER10H 0xb8a -#define CSR_MHPMCOUNTER11H 0xb8b -#define CSR_MHPMCOUNTER12H 0xb8c -#define CSR_MHPMCOUNTER13H 0xb8d -#define CSR_MHPMCOUNTER14H 0xb8e -#define CSR_MHPMCOUNTER15H 0xb8f -#define CSR_MHPMCOUNTER16H 0xb90 -#define CSR_MHPMCOUNTER17H 0xb91 -#define CSR_MHPMCOUNTER18H 0xb92 -#define CSR_MHPMCOUNTER19H 0xb93 -#define CSR_MHPMCOUNTER20H 0xb94 -#define CSR_MHPMCOUNTER21H 0xb95 -#define CSR_MHPMCOUNTER22H 0xb96 -#define CSR_MHPMCOUNTER23H 0xb97 -#define CSR_MHPMCOUNTER24H 0xb98 -#define CSR_MHPMCOUNTER25H 0xb99 -#define CSR_MHPMCOUNTER26H 0xb9a -#define CSR_MHPMCOUNTER27H 0xb9b -#define CSR_MHPMCOUNTER28H 0xb9c -#define CSR_MHPMCOUNTER29H 0xb9d -#define CSR_MHPMCOUNTER30H 0xb9e -#define CSR_MHPMCOUNTER31H 0xb9f -#define CAUSE_MISALIGNED_FETCH 0x0 -#define CAUSE_FAULT_FETCH 0x1 -#define CAUSE_ILLEGAL_INSTRUCTION 0x2 -#define CAUSE_BREAKPOINT 0x3 -#define CAUSE_MISALIGNED_LOAD 0x4 -#define CAUSE_FAULT_LOAD 0x5 -#define CAUSE_MISALIGNED_STORE 0x6 -#define CAUSE_FAULT_STORE 0x7 -#define CAUSE_USER_ECALL 0x8 -#define CAUSE_SUPERVISOR_ECALL 0x9 -#define CAUSE_HYPERVISOR_ECALL 0xa -#define CAUSE_MACHINE_ECALL 0xb -#endif -#ifdef DECLARE_INSN -DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) -DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) -DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) -DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) -DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) -DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) -DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) -DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) -DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) -DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) -DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) -DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) -DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) -DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) -DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) -DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) -DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) -DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) -DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) -DECLARE_INSN(add, MATCH_ADD, MASK_ADD) -DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) -DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) -DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) -DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) -DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) -DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) -DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) -DECLARE_INSN(or, MATCH_OR, MASK_OR) -DECLARE_INSN(and, MATCH_AND, MASK_AND) -DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) -DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) -DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) -DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) -DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) -DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) -DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) -DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) -DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) -DECLARE_INSN(lb, MATCH_LB, MASK_LB) -DECLARE_INSN(lh, MATCH_LH, MASK_LH) -DECLARE_INSN(lw, MATCH_LW, MASK_LW) -DECLARE_INSN(ld, MATCH_LD, MASK_LD) -DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) -DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) -DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) -DECLARE_INSN(sb, MATCH_SB, MASK_SB) -DECLARE_INSN(sh, MATCH_SH, MASK_SH) -DECLARE_INSN(sw, MATCH_SW, MASK_SW) -DECLARE_INSN(sd, MATCH_SD, MASK_SD) -DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) -DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) -DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) -DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) -DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) -DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) -DECLARE_INSN(div, MATCH_DIV, MASK_DIV) -DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) -DECLARE_INSN(rem, MATCH_REM, MASK_REM) -DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) -DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) -DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) -DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) -DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) -DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) -DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) -DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) -DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) -DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) -DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) -DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) -DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) -DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) -DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) -DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) -DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) -DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) -DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) -DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) -DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) -DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) -DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) -DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) -DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) -DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) -DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) -DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) -DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) -DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) -DECLARE_INSN(uret, MATCH_URET, MASK_URET) -DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) -DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) -DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) -DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) -DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) -DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) -DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) -DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) -DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) -DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) -DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) -DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) -DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) -DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) -DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) -DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) -DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) -DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) -DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) -DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) -DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) -DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) -DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) -DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) -DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) -DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) -DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) -DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) -DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) -DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) -DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) -DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) -DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) -DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) -DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) -DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) -DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) -DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) -DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) -DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) -DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) -DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) -DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) -DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) -DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) -DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) -DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) -DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) -DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) -DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) -DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) -DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) -DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) -DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) -DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) -DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) -DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) -DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) -DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) -DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) -DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) -DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) -DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) -DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) -DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) -DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) -DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) -DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) -DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) -DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) -DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) -DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) -DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) -DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) -DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) -DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) -DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) -DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) -DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) -DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) -DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) -DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) -DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) -DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) -DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) -DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) -DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) -DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) -DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) -DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) -DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) -DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) -DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) -DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) -DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) -DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) -DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) -DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) -DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) -DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) -DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) -DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) -DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) -DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) -DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) -DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) -DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) -DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) -DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) -DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) -DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) -DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) -DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) -DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) -DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) -DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) -DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) -DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) -DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) -DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) -DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) -DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) -DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) -DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) -DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) -DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) -DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) -DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) -DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) -DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) -DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) -DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) -DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) -DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) -DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) -DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) -DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) -DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) -DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) -DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) -#endif -#ifdef DECLARE_CSR -DECLARE_CSR(fflags, CSR_FFLAGS) -DECLARE_CSR(frm, CSR_FRM) -DECLARE_CSR(fcsr, CSR_FCSR) -DECLARE_CSR(cycle, CSR_CYCLE) -DECLARE_CSR(time, CSR_TIME) -DECLARE_CSR(instret, CSR_INSTRET) -DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) -DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) -DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) -DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) -DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) -DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) -DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) -DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) -DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) -DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) -DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) -DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) -DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) -DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) -DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) -DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) -DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) -DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) -DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) -DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) -DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) -DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) -DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) -DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) -DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) -DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) -DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) -DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) -DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) -DECLARE_CSR(sstatus, CSR_SSTATUS) -DECLARE_CSR(sie, CSR_SIE) -DECLARE_CSR(stvec, CSR_STVEC) -DECLARE_CSR(sscratch, CSR_SSCRATCH) -DECLARE_CSR(sepc, CSR_SEPC) -DECLARE_CSR(scause, CSR_SCAUSE) -DECLARE_CSR(sbadaddr, CSR_SBADADDR) -DECLARE_CSR(sip, CSR_SIP) -DECLARE_CSR(sptbr, CSR_SPTBR) -DECLARE_CSR(mstatus, CSR_MSTATUS) -DECLARE_CSR(misa, CSR_MISA) -DECLARE_CSR(medeleg, CSR_MEDELEG) -DECLARE_CSR(mideleg, CSR_MIDELEG) -DECLARE_CSR(mie, CSR_MIE) -DECLARE_CSR(mtvec, CSR_MTVEC) -DECLARE_CSR(mscratch, CSR_MSCRATCH) -DECLARE_CSR(mepc, CSR_MEPC) -DECLARE_CSR(mcause, CSR_MCAUSE) -DECLARE_CSR(mbadaddr, CSR_MBADADDR) -DECLARE_CSR(mip, CSR_MIP) -DECLARE_CSR(tselect, CSR_TSELECT) -DECLARE_CSR(tdata1, CSR_TDATA1) -DECLARE_CSR(tdata2, CSR_TDATA2) -DECLARE_CSR(tdata3, CSR_TDATA3) -DECLARE_CSR(dcsr, CSR_DCSR) -DECLARE_CSR(dpc, CSR_DPC) -DECLARE_CSR(dscratch, CSR_DSCRATCH) -DECLARE_CSR(mcycle, CSR_MCYCLE) -DECLARE_CSR(minstret, CSR_MINSTRET) -DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) -DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) -DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) -DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) -DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) -DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) -DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) -DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) -DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) -DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) -DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) -DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) -DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) -DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) -DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) -DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) -DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) -DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) -DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) -DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) -DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) -DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) -DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) -DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) -DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) -DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) -DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) -DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) -DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) -DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) -DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) -DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) -DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) -DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) -DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) -DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) -DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) -DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) -DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) -DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) -DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) -DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) -DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) -DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) -DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) -DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) -DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) -DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) -DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) -DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) -DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) -DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) -DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) -DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) -DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) -DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) -DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) -DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) -DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) -DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) -DECLARE_CSR(mvendorid, CSR_MVENDORID) -DECLARE_CSR(marchid, CSR_MARCHID) -DECLARE_CSR(mimpid, CSR_MIMPID) -DECLARE_CSR(mhartid, CSR_MHARTID) -DECLARE_CSR(cycleh, CSR_CYCLEH) -DECLARE_CSR(timeh, CSR_TIMEH) -DECLARE_CSR(instreth, CSR_INSTRETH) -DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) -DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) -DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) -DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) -DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) -DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) -DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) -DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) -DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) -DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) -DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) -DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) -DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) -DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) -DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) -DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) -DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) -DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) -DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) -DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) -DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) -DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) -DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) -DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) -DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) -DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) -DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) -DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) -DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) -DECLARE_CSR(mcycleh, CSR_MCYCLEH) -DECLARE_CSR(minstreth, CSR_MINSTRETH) -DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) -DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) -DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) -DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) -DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) -DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) -DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) -DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) -DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) -DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) -DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) -DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) -DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) -DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) -DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) -DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) -DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) -DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) -DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) -DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) -DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) -DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) -DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) -DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) -DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) -DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) -DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) -DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) -DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) -#endif -#ifdef DECLARE_CAUSE -DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) -DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) -DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) -DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) -DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) -DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) -DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) -DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) -DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) -DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) -DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) -DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) -#endif diff --git a/libcpu/risc-v/rv64/trap.c b/libcpu/risc-v/rv64/trap.c deleted file mode 100755 index f0144157db3..00000000000 --- a/libcpu/risc-v/rv64/trap.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2024/01/11 flyingcys The first version - */ - -#include - -#include - - -struct exception_stack_frame -{ - uint64_t x1; - uint64_t x2; - uint64_t x3; - uint64_t x4; - uint64_t x5; - uint64_t x6; - uint64_t x7; - uint64_t x8; - uint64_t x9; - uint64_t x10; - uint64_t x11; - uint64_t x12; - uint64_t x13; - uint64_t x14; - uint64_t x15; - uint64_t x16; - uint64_t x17; - uint64_t x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - uint64_t x23; - uint64_t x24; - uint64_t x25; - uint64_t x26; - uint64_t x27; - uint64_t x28; - uint64_t x29; - uint64_t x30; - uint64_t x31; -}; - -static void print_stack_frame(uintptr_t * sp) -{ - struct exception_stack_frame * esf = (struct exception_stack_frame *)(sp+1); - - rt_kprintf("\n=================================================================\n"); - rt_kprintf("x1 (ra : Return address ) ==> 0x%08x%08x\n", esf->x1 >> 32 , esf->x1 & UINT32_MAX); - rt_kprintf("x2 (sp : Stack pointer ) ==> 0x%08x%08x\n", esf->x2 >> 32 , esf->x2 & UINT32_MAX); - rt_kprintf("x3 (gp : Global pointer ) ==> 0x%08x%08x\n", esf->x3 >> 32 , esf->x3 & UINT32_MAX); - rt_kprintf("x4 (tp : Thread pointer ) ==> 0x%08x%08x\n", esf->x4 >> 32 , esf->x4 & UINT32_MAX); - rt_kprintf("x5 (t0 : Temporary ) ==> 0x%08x%08x\n", esf->x5 >> 32 , esf->x5 & UINT32_MAX); - rt_kprintf("x6 (t1 : Temporary ) ==> 0x%08x%08x\n", esf->x6 >> 32 , esf->x6 & UINT32_MAX); - rt_kprintf("x7 (t2 : Temporary ) ==> 0x%08x%08x\n", esf->x7 >> 32 , esf->x7 & UINT32_MAX); - rt_kprintf("x8 (s0/fp: Save register,frame pointer ) ==> 0x%08x%08x\n", esf->x8 >> 32 , esf->x8 & UINT32_MAX); - rt_kprintf("x9 (s1 : Save register ) ==> 0x%08x%08x\n", esf->x9 >> 32 , esf->x9 & UINT32_MAX); - rt_kprintf("x10(a0 : Function argument,return value) ==> 0x%08x%08x\n", esf->x10 >> 32 , esf->x10 & UINT32_MAX); - rt_kprintf("x11(a1 : Function argument,return value) ==> 0x%08x%08x\n", esf->x11 >> 32 , esf->x11 & UINT32_MAX); - rt_kprintf("x12(a2 : Function argument ) ==> 0x%08x%08x\n", esf->x12 >> 32 , esf->x12 & UINT32_MAX); - rt_kprintf("x13(a3 : Function argument ) ==> 0x%08x%08x\n", esf->x13 >> 32 , esf->x13 & UINT32_MAX); - rt_kprintf("x14(a4 : Function argument ) ==> 0x%08x%08x\n", esf->x14 >> 32 , esf->x14 & UINT32_MAX); - rt_kprintf("x15(a5 : Function argument ) ==> 0x%08x%08x\n", esf->x15 >> 32 , esf->x15 & UINT32_MAX); - rt_kprintf("x16(a6 : Function argument ) ==> 0x%08x%08x\n", esf->x16 >> 32 , esf->x16 & UINT32_MAX); - rt_kprintf("x17(a7 : Function argument ) ==> 0x%08x%08x\n", esf->x17 >> 32 , esf->x17 & UINT32_MAX); - rt_kprintf("x18(s2 : Save register ) ==> 0x%08x%08x\n", esf->x18 >> 32 , esf->x18 & UINT32_MAX); - rt_kprintf("x19(s3 : Save register ) ==> 0x%08x%08x\n", esf->x19 >> 32 , esf->x19 & UINT32_MAX); - rt_kprintf("x20(s4 : Save register ) ==> 0x%08x%08x\n", esf->x20 >> 32 , esf->x20 & UINT32_MAX); - rt_kprintf("x21(s5 : Save register ) ==> 0x%08x%08x\n", esf->x21 >> 32 , esf->x21 & UINT32_MAX); - rt_kprintf("x22(s6 : Save register ) ==> 0x%08x%08x\n", esf->x22 >> 32 , esf->x22 & UINT32_MAX); - rt_kprintf("x23(s7 : Save register ) ==> 0x%08x%08x\n", esf->x23 >> 32 , esf->x23 & UINT32_MAX); - rt_kprintf("x24(s8 : Save register ) ==> 0x%08x%08x\n", esf->x24 >> 32 , esf->x24 & UINT32_MAX); - rt_kprintf("x25(s9 : Save register ) ==> 0x%08x%08x\n", esf->x25 >> 32 , esf->x25 & UINT32_MAX); - rt_kprintf("x26(s10 : Save register ) ==> 0x%08x%08x\n", esf->x26 >> 32 , esf->x26 & UINT32_MAX); - rt_kprintf("x27(s11 : Save register ) ==> 0x%08x%08x\n", esf->x27 >> 32 , esf->x27 & UINT32_MAX); - rt_kprintf("x28(t3 : Temporary ) ==> 0x%08x%08x\n", esf->x28 >> 32 , esf->x28 & UINT32_MAX); - rt_kprintf("x29(t4 : Temporary ) ==> 0x%08x%08x\n", esf->x29 >> 32 , esf->x29 & UINT32_MAX); - rt_kprintf("x30(t5 : Temporary ) ==> 0x%08x%08x\n", esf->x30 >> 32 , esf->x30 & UINT32_MAX); - rt_kprintf("x31(t6 : Temporary ) ==> 0x%08x%08x\n", esf->x31 >> 32 , esf->x31 & UINT32_MAX); - rt_kprintf("=================================================================\n"); -} - -rt_weak void rt_hw_soft_irq_isr(void) -{ - -} - -rt_weak int rt_hw_tick_isr(void) -{ - return 0; -} - -rt_weak void rt_hw_irq_isr(void) -{ - -} - -rt_weak rt_size_t handle_trap(rt_size_t cause, rt_size_t epc, rt_size_t *sp) -{ - if (cause & (1UL << (__riscv_xlen - 1))) //interrupt - { - if ((cause & 0x1f) == IRQ_M_SOFT) - { - rt_hw_soft_irq_isr(); - } - else if ((cause & 0x1f) == IRQ_M_TIMER) - { - rt_hw_tick_isr(); - } - else if ((cause & 0x1f) == IRQ_M_EXT) - { - rt_hw_irq_isr(); - } - } - else - { - rt_thread_t tid; -#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) - extern long list_thread(); -#endif - - rt_hw_interrupt_disable(); - - tid = rt_thread_self(); - rt_kprintf("\nException:\n"); - switch (cause) - { - case CAUSE_MISALIGNED_FETCH: - rt_kprintf("Instruction address misaligned"); - break; - case CAUSE_FAULT_FETCH: - rt_kprintf("Instruction access fault"); - break; - case CAUSE_ILLEGAL_INSTRUCTION: - rt_kprintf("Illegal instruction"); - break; - case CAUSE_BREAKPOINT: - rt_kprintf("Breakpoint"); - break; - case CAUSE_MISALIGNED_LOAD: - rt_kprintf("Load address misaligned"); - break; - case CAUSE_FAULT_LOAD: - rt_kprintf("Load access fault"); - break; - case CAUSE_MISALIGNED_STORE: - rt_kprintf("Store address misaligned"); - break; - case CAUSE_FAULT_STORE: - rt_kprintf("Store access fault"); - break; - case CAUSE_USER_ECALL: - rt_kprintf("Environment call from U-mode"); - break; - case CAUSE_SUPERVISOR_ECALL: - rt_kprintf("Environment call from S-mode"); - break; - case CAUSE_HYPERVISOR_ECALL: - rt_kprintf("Environment call from H-mode"); - break; - case CAUSE_MACHINE_ECALL: - rt_kprintf("Environment call from M-mode"); - break; - default: - rt_kprintf("Uknown exception : %08lX", cause); - break; - } - rt_kprintf("\n"); - print_stack_frame(sp); - rt_kprintf("exception pc => 0x%08x\n", epc); - rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, tid->parent.name); -#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) - list_thread(); -#endif - while(1); - } - - return epc; -} diff --git a/libcpu/risc-v/t-head/c908/SConscript b/libcpu/risc-v/t-head/SConscript similarity index 100% rename from libcpu/risc-v/t-head/c908/SConscript rename to libcpu/risc-v/t-head/SConscript diff --git a/libcpu/risc-v/t-head/c906/SConscript b/libcpu/risc-v/t-head/c906/SConscript deleted file mode 100644 index 5f750ad65f4..00000000000 --- a/libcpu/risc-v/t-head/c906/SConscript +++ /dev/null @@ -1,13 +0,0 @@ -# RT-Thread building script for component - -from building import * -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') -CPPPATH = [cwd] - -if not GetDepend('ARCH_USING_ASID'): - SrcRemove(src, ['asid.c']) - -group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/libcpu/risc-v/t-head/c906/asm/sbiasm.h b/libcpu/risc-v/t-head/c906/asm/sbiasm.h deleted file mode 100644 index 4639fba68cf..00000000000 --- a/libcpu/risc-v/t-head/c906/asm/sbiasm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SBI_ASM_H -#define _SBI_ASM_H - -.macro SBI_CALL which - li a7, \which - ecall - nop -.endm - -#endif /* _SBI_ASM_H */ diff --git a/libcpu/risc-v/t-head/c906/asm/sbidef.h b/libcpu/risc-v/t-head/c906/asm/sbidef.h deleted file mode 100644 index 5bcf58ade7c..00000000000 --- a/libcpu/risc-v/t-head/c906/asm/sbidef.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019-2020, Xim - * - * SPDX-License-Identifier: Apache-2.0 - * - */ -#ifndef _ASM_SBI_DEF_H -#define _ASM_SBI_DEF_H - -#define SBI_SET_TIMER 0 -#define SBI_CONSOLE_PUTCHAR 1 -#define SBI_CONSOLE_GETCHAR 2 -#define SBI_CLEAR_IPI 3 -#define SBI_SEND_IPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 - -#define SBI_CONSOLE_PUTSTR 9 - -#define SBI_SD_WRITE 10 -#define SBI_SD_READ 11 -#define SBI_NET_WRITE 12 -#define SBI_NET_READ 13 - -#endif /* _ASM_SBI_DEF_H */ diff --git a/libcpu/risc-v/t-head/c906/cache.c b/libcpu/risc-v/t-head/c906/cache.c deleted file mode 100644 index af493e3adf3..00000000000 --- a/libcpu/risc-v/t-head/c906/cache.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-29 lizhirui first version - * 2021-11-05 JasonHu add c906 cache inst - * 2022-11-09 WangXiaoyao Support cache coherence operations; - * improve portability and make - * no assumption on undefined behavior - */ - -#include -#include -#include -#include - -#include "opcode.h" -#include "cache.h" - -#define L1_CACHE_BYTES (64) - -/** - * GCC version not support t-head cache flush, so we use fixed code to achieve. - * The following function cannot be optimized. - */ -static void dcache_wb_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void dcache_inv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void dcache_wbinv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void icache_inv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); - -#define CACHE_OP_RS1 %0 -#define CACHE_OP_RANGE(instr) \ - { \ - register rt_ubase_t i = start & ~(L1_CACHE_BYTES - 1); \ - for (; i < end; i += L1_CACHE_BYTES) \ - { \ - __asm__ volatile(instr ::"r"(i) \ - : "memory"); \ - } \ - } - -static void dcache_wb_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_CVA(CACHE_OP_RS1)); -} - -static void dcache_inv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_IVA(CACHE_OP_RS1)); -} - -static void dcache_wbinv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_CIVA(CACHE_OP_RS1)); -} - -static void icache_inv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_ICACHE_IVA(CACHE_OP_RS1)); -} - -rt_inline rt_uint32_t rt_cpu_icache_line_size(void) -{ - return L1_CACHE_BYTES; -} - -rt_inline rt_uint32_t rt_cpu_dcache_line_size(void) -{ - return L1_CACHE_BYTES; -} - -void rt_hw_cpu_icache_invalidate_local(void *addr, int size) -{ - icache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync_i(); -} - -void rt_hw_cpu_dcache_invalidate_local(void *addr, int size) -{ - dcache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -void rt_hw_cpu_dcache_clean_local(void *addr, int size) -{ - dcache_wb_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -void rt_hw_cpu_dcache_clean_and_invalidate_local(void *addr, int size) -{ - dcache_wbinv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -/** - * ===================================================== - * Architecture Independent API - * ===================================================== - */ - -void rt_hw_cpu_icache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_INVALIDATE) - { - rt_hw_cpu_icache_invalidate_local(addr, size); - } -} - -void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_FLUSH) - { - rt_hw_cpu_dcache_clean_local(addr, size); - } - else - { - rt_hw_cpu_dcache_invalidate_local(addr, size); - } -} - -void rt_hw_sync_cache_local(void *addr, int size) -{ - rt_hw_cpu_dcache_clean_local(addr, size); - rt_hw_cpu_icache_invalidate_local(addr, size); -} diff --git a/libcpu/risc-v/t-head/c906/cache.h b/libcpu/risc-v/t-head/c906/cache.h deleted file mode 100644 index 7476de83cfb..00000000000 --- a/libcpu/risc-v/t-head/c906/cache.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-11-05 JasonHu The first version - */ - -#ifndef CACHE_H__ -#define CACHE_H__ - -#include "opcode.h" - -#ifndef ALWAYS_INLINE -#define ALWAYS_INLINE inline __attribute__((always_inline)) -#endif - -#define rt_hw_cpu_sync() __asm__ volatile(OPC_SYNC:: \ - : "memory") - -#define rt_hw_cpu_sync_i() __asm__ volatile(OPC_SYNC_I:: \ - : "memory"); - -/** - * ======================================== - * Local cpu cache maintainence operations - * ======================================== - */ - -void rt_hw_cpu_dcache_clean_local(void *addr, int size); -void rt_hw_cpu_dcache_invalidate_local(void *addr, int size); -void rt_hw_cpu_dcache_clean_and_invalidate_local(void *addr, int size); - -void rt_hw_cpu_icache_invalidate_local(void *addr, int size); - -ALWAYS_INLINE void rt_hw_cpu_dcache_clean_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_CALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_dcache_invalidate_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_IALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_dcache_clean_and_invalidate_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_CIALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_icache_invalidate_all_local(void) -{ - __asm__ volatile(OPC_ICACHE_IALL :: - : "memory"); - rt_hw_cpu_sync_i(); -} - -#define rt_hw_icache_invalidate_all rt_hw_cpu_icache_invalidate_all - -/** - * ======================================== - * Multi-core cache maintainence operations - * ======================================== - */ - -#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_and_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_and_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_and_invalidate_local - -#define rt_hw_cpu_dcache_clean_all rt_hw_cpu_dcache_clean_all_local -#define rt_hw_cpu_dcache_invalidate_all rt_hw_cpu_dcache_invalidate_all_local -#define rt_hw_cpu_dcache_clean_and_invalidate_all rt_hw_cpu_dcache_clean_and_invalidate_all_local - -#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 Coherent - */ -void rt_hw_sync_cache_local(void *addr, int size); - -#endif /* CACHE_H__ */ diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c deleted file mode 100644 index 2f7a86e6802..00000000000 --- a/libcpu/risc-v/t-head/c906/interrupt.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#include -#include - -#include "interrupt.h" -#include "riscv.h" -#include "plic.h" - -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; - -struct rt_irq_desc isr_table[INTERRUPTS_MAX]; - -static void rt_hw_interrupt_handler(int vector, void *param) -{ - rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); -} - -/** - * This function will initialize hardware interrupt - */ -void rt_hw_interrupt_init(void) -{ - /* init interrupt controller */ - plic_init(); - - rt_int32_t idx; - - rt_memset(isr_table, 0x00, sizeof(isr_table)); - for (idx = 0; idx < INTERRUPTS_MAX; idx++) - { - isr_table[idx].handler = rt_hw_interrupt_handler; - } - - /* 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; -} - -/** - * This function will mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_mask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_disable_irq(vector); -} - -/** - - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_enable_irq(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param handler the interrupt service routine to be installed - * @param param the interrupt service function parameter - * @param name the interrupt name - * @return old handler - */ -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, - void *param, const char *name) -{ - rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return old_handler; - } - - old_handler = isr_table[IRQ_OFFSET + vector].handler; - -#ifdef RT_USING_INTERRUPT_INFO - rt_strncpy(isr_table[IRQ_OFFSET + vector].name, name, RT_NAME_MAX); -#endif /* RT_USING_INTERRUPT_INFO */ - isr_table[IRQ_OFFSET + vector].handler = handler; - isr_table[IRQ_OFFSET + vector].param = param; - - return old_handler; -} diff --git a/libcpu/risc-v/t-head/c906/interrupt.h b/libcpu/risc-v/t-head/c906/interrupt.h deleted file mode 100644 index bdc98972b2c..00000000000 --- a/libcpu/risc-v/t-head/c906/interrupt.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#ifndef __INTERRUPT_H__ -#define __INTERRUPT_H__ - -#include - -#define NR_CPUS 1 - -#define IRQ_OFFSET 16 -#ifndef IRQ_MAX_NR -#define IRQ_MAX_NR 207 -#endif -#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) - -enum { - EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, - EP_INSTRUCTION_ACCESS_FAULT, - EP_ILLEGAL_INSTRUCTION, - EP_BREAKPOINT, - EP_LOAD_ADDRESS_MISALIGNED, - EP_LOAD_ACCESS_FAULT, - EP_STORE_ADDRESS_MISALIGNED, - EP_STORE_ACCESS_FAULT, - EP_ENVIRONMENT_CALL_U_MODE, - EP_ENVIRONMENT_CALL_S_MODE, - EP_RESERVED10, - EP_ENVIRONMENT_CALL_M_MODE, - EP_INSTRUCTION_PAGE_FAULT, /* page attr */ - EP_LOAD_PAGE_FAULT, /* read data */ - EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ -}; - -void rt_hw_interrupt_init(void); -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); - -#endif diff --git a/libcpu/risc-v/t-head/c906/opcode.h b/libcpu/risc-v/t-head/c906/opcode.h deleted file mode 100644 index 27c2f91bf89..00000000000 --- a/libcpu/risc-v/t-head/c906/opcode.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-09 WangXiaoyao Add portable asm support - */ -#ifndef __OPCODE_H__ -#define __OPCODE_H__ - -/** - * @brief binary opcode pseudo operations - * Used to bypass toolchain restriction on extension ISA - * - * WARNING: Xuantie ISAs are not compatible to each other in opcode. - * It's painful to port this file, and should be really careful. - */ - -/** - * @brief RISC-V instruction formats - */ - -/** - * R type: .insn r opcode6, func3, func7, rd, rs1, rs2 - * - * +-------+-----+-----+-------+----+---------+ - * | func7 | rs2 | rs1 | func3 | rd | opcode6 | - * +-------+-----+-----+-------+----+---------+ - * 31 25 20 15 12 7 0 - */ -#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \ - ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2) - -/** - * @brief Xuantie T-HEAD extension ISA format - * Compatible to Xuantie C906R2S1 user manual v06 - */ -#define __OPC_INSN_FORMAT_CACHE(func7, rs2, rs1) \ - __OPC_INSN_FORMAT_R(0x0b, 0x0, func7, x0, rs1, rs2) - -#ifdef _TOOLCHAIN_SUPP_XTHEADE_ISA_ -#define OPC_SYNC "sync" -#define OPC_SYNC_I "sync.i" - -#define OPC_DCACHE_CALL "dcache.call" -#define OPC_DCACHE_IALL "dcache.iall" -#define OPC_DCACHE_CIALL "dcache.ciall" - -#define OPC_ICACHE_IALL "icache.iall" - -#define OPC_DCACHE_CVA(rs1) "dcache.cva "RT_STRINGIFY(rs1) -#define OPC_DCACHE_IVA(rs1) "dcache.iva "RT_STRINGIFY(rs1) -#define OPC_DCACHE_CIVA(rs1) "dcache.civa "RT_STRINGIFY(rs1) - -#define OPC_ICACHE_IVA(rs1) "icache.iva "RT_STRINGIFY(rs1) -#else /* !_TOOLCHAIN_NOT_SUPP_THEAD_ISA_ */ -#define OPC_SYNC ".long 0x0180000B" -#define OPC_SYNC_I ".long 0x01A0000B" - -#define OPC_DCACHE_CALL ".long 0x0010000B" -#define OPC_DCACHE_IALL ".long 0x0020000B" -#define OPC_DCACHE_CIALL ".long 0x0030000B" - -#define OPC_ICACHE_IALL ".long 0x0100000B" - -#define OPC_DCACHE_CVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x4, rs1) -#define OPC_DCACHE_IVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x6, rs1) -#define OPC_DCACHE_CIVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x7, rs1) - -#define OPC_ICACHE_IVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x16, rs1) -#endif /* _TOOLCHAIN_NOT_SUPP_THEAD_ISA_ */ - -#ifdef _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ -#define OPC_FENCE_I "fence.i" -#else /* !_TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ -#define OPC_FENCE_I ".long 0x0000100F" -#endif /* _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ - -#endif /* __OPCODE_H__ */ \ No newline at end of file diff --git a/libcpu/risc-v/t-head/c906/plic.c b/libcpu/risc-v/t-head/c906/plic.c deleted file mode 100644 index 829ee9e4fd4..00000000000 --- a/libcpu/risc-v/t-head/c906/plic.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2021-11-12 JasonHu fix bug that not intr on f133 - * 2023-04-22 flyingcys add plic register ioremap - */ - -#include - -#include - -#include "plic.h" -#include "interrupt.h" -#include "io.h" -#include "encoding.h" -#include "ioremap.h" - -static void *c906_plic_regs = RT_NULL; -extern struct rt_irq_desc isr_table[]; - -struct plic_handler -{ - rt_bool_t present; - void *hart_base; - void *enable_base; -}; - -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler c906_plic_handlers[C906_NR_CPUS]; -static void *c906_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; - -rt_inline void plic_irq_toggle(int hwirq, int enable) -{ - int cpu = 0; - void *priority_addr; - - /* set priority of interrupt, interrupt 0 is zero. */ - priority_addr = (void *)((rt_size_t)c906_plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (c906_irq_priority[hwirq] == RT_NULL) - { - c906_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = c906_irq_priority[hwirq]; -#endif - writel(enable, priority_addr); - struct plic_handler *handler = &c906_plic_handlers[cpu]; - - if (handler->present) - { - plic_toggle(handler, hwirq, enable); - } -} - -static void generic_handle_irq(int irq) -{ - rt_isr_handler_t isr; - void *param; - - if (irq < 0 || irq >= IRQ_MAX_NR) - { - LOG_E("bad irq number %d!\n", irq); - return; - } - - if (!irq) // irq = 0 => no irq - { - LOG_W("no irq!\n"); - return; - } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) - { - isr(irq, param); - } - /* complete irq. */ - plic_complete(irq); -} - -void plic_complete(int irqno) -{ - int cpu = 0; - struct plic_handler *handler = &c906_plic_handlers[cpu]; - - writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); -} - -void plic_disable_irq(int irqno) -{ - plic_irq_toggle(irqno, 0); -} - -void plic_enable_irq(int irqno) -{ - plic_irq_toggle(irqno, 1); -} - -/* - * Handling an interrupt is a two-step process: first you claim the interrupt - * by reading the claim register, then you complete the interrupt by writing - * that source ID back to the same claim register. This automatically enables - * and disables the interrupt, so there's nothing else to do. - */ -void plic_handle_irq(void) -{ - int cpu = 0; - unsigned int irq; - - struct plic_handler *handler = &c906_plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - - if (c906_plic_regs == RT_NULL || !handler->present) - { - LOG_E("plic state not initialized."); - return; - } - - clear_csr(sie, SIE_SEIE); - - while ((irq = readl(claim))) - { - /* ID0 is diabled permantually from spec. */ - if (irq == 0) - { - LOG_E("irq no is zero."); - } - else - { - generic_handle_irq(irq); - } - } - set_csr(sie, SIE_SEIE); -} - -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) -{ - uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); - uint32_t hwirq_mask = 1 << (hwirq % 32); - - if (enable) - { - writel(readl(reg) | hwirq_mask, reg); - } - else - { - writel(readl(reg) & ~hwirq_mask, reg); - } -} - -void plic_init(void) -{ - int nr_irqs; - int nr_context; - int i; - unsigned long hwirq; - int cpu = 0; - - if (c906_plic_regs) - { - LOG_E("plic already initialized!"); - return; - } - - nr_context = C906_NR_CONTEXT; - - c906_plic_regs = (void *)C906_PLIC_PHY_ADDR; - if (!c906_plic_regs) - { - LOG_E("fatal error, plic is reg space is null."); - return; - } - - nr_irqs = C906_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 = &c906_plic_handlers[cpu]; - if (handler->present) - { - threshold = 0xffffffff; - goto done; - } - - handler->present = RT_TRUE; - handler->hart_base = (void *)((rt_size_t)c906_plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART); - handler->enable_base = (void *)((rt_size_t)c906_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); -#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); - } - } - - /* Enable supervisor external interrupts. */ - set_csr(sie, SIE_SEIE); -} diff --git a/libcpu/risc-v/t-head/c906/plic.h b/libcpu/risc-v/t-head/c906/plic.h deleted file mode 100644 index 93235279e2c..00000000000 --- a/libcpu/risc-v/t-head/c906/plic.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2023-04-22 flyingcys add C906_PLIC_PHY_ADDR macro judge - */ - -#ifndef __RISCV64_PLIC_H__ -#define __RISCV64_PLIC_H__ - -#include - -#ifndef C906_PLIC_PHY_ADDR -#define C906_PLIC_PHY_ADDR (0x10000000) -#endif -#define C906_PLIC_NR_EXT_IRQS (IRQ_MAX_NR) -#define C906_NR_CPUS (NR_CPUS) - -/* M and S mode context. */ -#define C906_NR_CONTEXT (2) - -#define MAX_DEVICES 1024 -#define MAX_CONTEXTS 15872 - -/* - * Each interrupt source has a priority register associated with it. - * We always hardwire it to one in Linux. - */ -#define PRIORITY_BASE 0 -#define PRIORITY_PER_ID 4 - -/* - * Each hart context has a vector of interrupt enable bits associated with it. - * There's one bit for each interrupt source. - */ -#define ENABLE_BASE 0x2000 -#define ENABLE_PER_HART 0x80 - -/* - * Each hart context has a set of control registers associated with it. Right - * now there's only two: a source priority threshold over which the hart will - * take an interrupt, and a register to claim interrupts. - */ -#define CONTEXT_BASE 0x200000 -#define CONTEXT_PER_HART 0x1000 -#define CONTEXT_THRESHOLD 0x00 -#define CONTEXT_CLAIM 0x04 - -void plic_init(void); -void plic_enable_irq(int irqno); -void plic_disable_irq(int irqno); -// tell PLIC that we've served this IRQ -void plic_complete(int irq); -void plic_handle_irq(void); - -#endif diff --git a/libcpu/risc-v/t-head/c906/riscv_mmu.h b/libcpu/risc-v/t-head/c906/riscv_mmu.h deleted file mode 100644 index 5cb8b328d67..00000000000 --- a/libcpu/risc-v/t-head/c906/riscv_mmu.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2021-05-03 lizhirui porting to c906 - * 2023-10-12 Shell Add permission control API - */ - -#ifndef __RISCV_MMU_H__ -#define __RISCV_MMU_H__ - -#include -#include -#include "riscv.h" - -#undef PAGE_SIZE - -/* C-SKY extend */ -#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 PAGE_OFFSET_SHIFT 0 -#define PAGE_OFFSET_BIT 12 -#define PAGE_SIZE __SIZE(PAGE_OFFSET_BIT) -#define PAGE_OFFSET_MASK __MASK(PAGE_OFFSET_BIT) -#define VPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT) -#define VPN0_BIT 9 -#define VPN1_SHIFT (VPN0_SHIFT + VPN0_BIT) -#define VPN1_BIT 9 -#define VPN2_SHIFT (VPN1_SHIFT + VPN1_BIT) -#define VPN2_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 PPN_BITS (PPN0_BIT + PPN1_BIT + PPN2_BIT) - -#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 ARCH_ADDRESS_WIDTH_BITS 64 - -#define PHYSICAL_ADDRESS_WIDTH_BITS 56 - -#define PAGE_ATTR_NEXT_LEVEL (0) -#define PAGE_ATTR_RWX (PTE_X | PTE_W | PTE_R) -#define PAGE_ATTR_READONLY (PTE_R) -#define PAGE_ATTR_XN (PTE_W | PTE_R) -#define PAGE_ATTR_READEXECUTE (PTE_X | PTE_R) - -#define PAGE_ATTR_USER (PTE_U) -#define PAGE_ATTR_SYSTEM (0) - -#define PAGE_ATTR_CB (PTE_BUF | PTE_CACHE) -#define PAGE_ATTR_DEV (PTE_SO) - -#define PAGE_DEFAULT_ATTR_LEAF \ - (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_U | \ - PAGE_ATTR_RWX | PTE_V) -#define PAGE_DEFAULT_ATTR_NEXT \ - (PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D | PTE_G | PTE_V) - -#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) - -/** - * encoding of SATP (Supervisor Address Translation and Protection register) - */ -#define SATP_MODE_OFFSET 60 -#define SATP_MODE_BARE 0 -#define SATP_MODE_SV39 8 -#define SATP_MODE_SV48 9 -#define SATP_MODE_SV57 10 -#define SATP_MODE_SV64 11 - -#define ARCH_VADDR_WIDTH 39 -#define SATP_MODE SATP_MODE_SV39 - -#define MMU_MAP_K_DEVICE PTE_WRAP(PAGE_ATTR_DEV | PTE_G | PAGE_ATTR_XN | PTE_V) -#define MMU_MAP_K_RWCB PTE_WRAP(PAGE_ATTR_CB | PTE_G | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_K_RW PTE_WRAP(PTE_G | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_U_RWCB PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_U_ROCB \ - PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_READONLY | PTE_V) -#define MMU_MAP_U_RWCB_XN PTE_WRAP(PAGE_ATTR_CB | PTE_U | PAGE_ATTR_XN | PTE_V) -#define MMU_MAP_U_RW PTE_WRAP(PTE_U | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_EARLY \ - PTE_WRAP(PAGE_ATTR_RWX | PTE_G | PTE_V | PTE_CACHE | PTE_SHARE | PTE_BUF) -#define MMU_MAP_TRACE(attr) (attr) - -#define PTE_XWR_MASK 0xe - -#define ARCH_PAGE_SIZE PAGE_SIZE -#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_INDEX_MASK (ARCH_INDEX_SIZE - 1) - -#define ARCH_MAP_FAILED ((void *)0x8000000000000000) - -void mmu_set_pagetable(rt_ubase_t addr); -void mmu_enable_user_page_access(void); -void mmu_disable_user_page_access(void); - -#define RT_HW_MMU_PROT_READ 1 -#define RT_HW_MMU_PROT_WRITE 2 -#define RT_HW_MMU_PROT_EXECUTE 4 -#define RT_HW_MMU_PROT_KERNEL 8 -#define RT_HW_MMU_PROT_USER 16 -#define RT_HW_MMU_PROT_CACHE 32 - -void rt_hw_asid_init(void); -struct rt_aspace; -void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl); - -/** - * @brief Remove permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be removed - * @return size_t returned attribution - */ -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; - /* remove write permission for kernel */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: - attr &= ~PTE_W; - break; - default: - RT_ASSERT(0); - } - return attr; -} - -/** - * @brief Add permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be added - * @return size_t returned attribution - */ -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); - } - return attr; -} - -/** - * @brief Test permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be test - * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE - */ -rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) -{ - rt_bool_t rc = 0; - 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); - } - - if (rc && (prot & RT_HW_MMU_PROT_USER)) - { - rc = !!(attr & PTE_U); - } - return rc; -} - -#endif diff --git a/libcpu/risc-v/t-head/c906/symbol_analysis.c b/libcpu/risc-v/t-head/c906/symbol_analysis.c deleted file mode 100644 index 83edacb1c43..00000000000 --- a/libcpu/risc-v/t-head/c906/symbol_analysis.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright lizhirui - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-18 lizhirui the first version - * 2021-05-20 lizhirui add os debug support - */ - -#include -#include "symbol_analysis.h" - -#define MEMORY_BASE 0x40000000 -#define MEMORY_SIZE (128 * 0x100000) - -extern rt_size_t _osdebug_start; - -static os_symtab_header *symtab_header = (os_symtab_header *)&_osdebug_start; - -//该函数用于在指定的表中查找某个地址对应的符号的描述结构体指针,返回值的符号遵循规则详见文档 -os_symtab_item *find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address) -{ - rt_size_t left = 0; - rt_size_t right = symbol_num; - os_symtab_item *sym_table = (os_symtab_item *)((rt_size_t)&_osdebug_start + symbol_table_addr); - - while(left < right) - { - rt_size_t mid = (left + right) >> 1; - //rt_kprintf("left = %d,right = %d,mid = %d\n",left,right,mid); - - if(address < sym_table[mid].address) - { - right = mid; - - while((right < symbol_num) && ((right - 1) >= 0) && (sym_table[right].address == sym_table[right - 1].address)) - { - right--; - } - } - else if(address == sym_table[mid].address) - { - left = mid + 1; - break; - } - else - { - left = mid; - - while((left >= 0) && ((left + 1) < symbol_num) && (sym_table[left].address == sym_table[left + 1].address)) - { - left++; - } - - left++; - } - } - - left--; - - if(left == ((rt_size_t)-1)) - { - return RT_NULL; - } - - while((left < symbol_num) && ((left - 1) >= 0) && (sym_table[left].address == sym_table[left - 1].address)) - { - left--; - } - - return &sym_table[left]; -} - -//该函数用于根据给定的符号指针从字符串表中找到对应的符号名指针并返回 -const char *get_symbol_name(os_symtab_item *symbol) -{ - return (const char *)((rt_size_t)&_osdebug_start + symtab_header -> string_table_offset + symbol -> name_offset); -} - -//该函数可以根据给定的符号和地址向中断打印出标准格式的符号信息 -void print_symbol(os_symtab_item *symbol,rt_size_t address) -{ - rt_kprintf("<%s(0x%p)",get_symbol_name(symbol),symbol -> address); - - if(symbol -> size) - { - rt_kprintf(" : 0x%x>",symbol -> size); - } - else - { - rt_kprintf(">"); - } - - if(address > symbol -> address) - { - rt_kprintf(" + 0x%x",address - symbol -> address); - } -} - -//该函数用于打印出一个地址关联的全部符号信息 -void print_symbol_info(rt_size_t address,rt_bool_t function) -{ - os_symtab_item *function_symbol = find_symbol_table(symtab_header -> function_table_offset,symtab_header -> function_table_num,address); - os_symtab_item *object_symbol = find_symbol_table(symtab_header -> object_table_offset,symtab_header -> object_table_num,address); - os_symtab_item *general_symbol = find_symbol_table(symtab_header -> general_symbol_table_offset,symtab_header -> general_symbol_table_num,address); - const char *dot = ""; - rt_bool_t valid = RT_FALSE; - - if(function) - { - while(function_symbol != RT_NULL) - { - if((function_symbol -> address + function_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(function_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(function_symbol[0].address == function_symbol[1].address) - { - function_symbol++; - } - - break; - } - - if(!valid) - { - while(general_symbol != RT_NULL) - { - rt_kprintf(dot); - print_symbol(general_symbol,address); - dot = ","; - valid = RT_TRUE; - - if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(general_symbol[0].address == general_symbol[1].address) - { - general_symbol++; - } - - break; - } - - while(object_symbol != RT_NULL) - { - if((object_symbol -> address + object_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(object_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(object_symbol[0].address == object_symbol[1].address) - { - object_symbol++; - } - - break; - } - } - } - else - { - while(object_symbol != RT_NULL) - { - if((object_symbol -> address + object_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(object_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(object_symbol[0].address == object_symbol[1].address) - { - object_symbol++; - } - - break; - } - - if(!valid) - { - while(general_symbol != RT_NULL) - { - rt_kprintf(dot); - print_symbol(general_symbol,address); - dot = ","; - valid = RT_TRUE; - - if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(general_symbol[0].address == general_symbol[1].address) - { - general_symbol++; - } - - break; - } - - while(function_symbol != RT_NULL) - { - if((function_symbol -> address + function_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(function_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(function_symbol[0].address == function_symbol[1].address) - { - function_symbol++; - } - - break; - } - } - } - - if(dot == "") - { - rt_kprintf(""); - } -} - -//该函数用于在出错时打印出栈跟踪信息 -void print_stacktrace(rt_size_t epc,rt_size_t fp) -{ - rt_kprintf("-----------------------------Dump Stacktrace----------------------------\n\n"); - rt_size_t sp = fp; - rt_size_t i = 0; - - rt_kprintf("address 0x%p(",epc); - print_symbol_info(epc,RT_TRUE); - rt_kprintf(")\n\n"); - - while(1) - { - if((sp >= MEMORY_BASE) && (sp < (MEMORY_BASE + MEMORY_SIZE))) - { - //rt_kprintf("%d: 0x%p\n",i,sp); - rt_size_t *stack = (rt_size_t *)(sp - sizeof(rt_size_t) * 2); - rt_size_t ra = stack[1]; - - if(!ra) - { - break; - } - - rt_kprintf("return to 0x%p(",ra); - print_symbol_info(ra,RT_TRUE); - rt_kprintf(")\n\n"); - //rt_kprintf("ra = 0x%p,fp = 0x%p\n",stack[1],stack[0]); - sp = stack[0]; - i++; - } - else - { - break; - } - } - - rt_kprintf("---------------------------------Dump OK--------------------------------\n"); -} diff --git a/libcpu/risc-v/t-head/c906/symbol_analysis.h b/libcpu/risc-v/t-head/c906/symbol_analysis.h deleted file mode 100644 index a9db46ffd39..00000000000 --- a/libcpu/risc-v/t-head/c906/symbol_analysis.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright lizhirui - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-18 lizhirui the first version - * 2021-05-20 lizhirui add os debug support - */ - -#ifndef __SYMBOL_ANALYSIS_H__ -#define __SYMBOL_ANALYSIS_H__ - - #include - - //osdebug节区头描述结构体 - typedef struct os_symtab_header - { - rt_size_t function_table_offset;//函数表的偏移地址(相对于节区起始地址,下同) - rt_size_t function_table_num;//函数表中的符号数量 - rt_size_t object_table_offset;//对象表的偏移地址 - rt_size_t object_table_num;//对象表中的符号数量 - rt_size_t general_symbol_table_offset;//一般符号(指代类型虽为NONE但带有GLOBAL的符号)表的偏移地址 - rt_size_t general_symbol_table_num;//一般符号表中的符号数量 - rt_size_t string_table_offset;//字符串表的偏移地址 - rt_size_t string_table_size;//字符串表的大小(字节为单位) - }os_symtab_header; - - //符号描述结构体 - typedef struct os_symtab_item - { - rt_size_t name_offset;//符号名称在字符串表中的偏移地址 - rt_size_t address;//该符号所代表的地址 - rt_size_t size;//该符号所代表的大小 - }os_symtab_item; - - os_symtab_item *find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address); - const char *get_symbol_name(os_symtab_item *symbol); - void print_symbol(os_symtab_item *symbol,rt_size_t address); - void print_symbol_info(rt_size_t address,rt_bool_t function); - void print_stacktrace(rt_size_t epc,rt_size_t fp); - -#endif diff --git a/libcpu/risc-v/t-head/c908/asm/sbiasm.h b/libcpu/risc-v/t-head/c908/asm/sbiasm.h deleted file mode 100644 index 4639fba68cf..00000000000 --- a/libcpu/risc-v/t-head/c908/asm/sbiasm.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _SBI_ASM_H -#define _SBI_ASM_H - -.macro SBI_CALL which - li a7, \which - ecall - nop -.endm - -#endif /* _SBI_ASM_H */ diff --git a/libcpu/risc-v/t-head/c908/asm/sbidef.h b/libcpu/risc-v/t-head/c908/asm/sbidef.h deleted file mode 100644 index 5bcf58ade7c..00000000000 --- a/libcpu/risc-v/t-head/c908/asm/sbidef.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019-2020, Xim - * - * SPDX-License-Identifier: Apache-2.0 - * - */ -#ifndef _ASM_SBI_DEF_H -#define _ASM_SBI_DEF_H - -#define SBI_SET_TIMER 0 -#define SBI_CONSOLE_PUTCHAR 1 -#define SBI_CONSOLE_GETCHAR 2 -#define SBI_CLEAR_IPI 3 -#define SBI_SEND_IPI 4 -#define SBI_REMOTE_FENCE_I 5 -#define SBI_REMOTE_SFENCE_VMA 6 -#define SBI_REMOTE_SFENCE_VMA_ASID 7 -#define SBI_SHUTDOWN 8 - -#define SBI_CONSOLE_PUTSTR 9 - -#define SBI_SD_WRITE 10 -#define SBI_SD_READ 11 -#define SBI_NET_WRITE 12 -#define SBI_NET_READ 13 - -#endif /* _ASM_SBI_DEF_H */ diff --git a/libcpu/risc-v/t-head/c908/cache.c b/libcpu/risc-v/t-head/c908/cache.c deleted file mode 100644 index db573fa5f81..00000000000 --- a/libcpu/risc-v/t-head/c908/cache.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-29 lizhirui first version - * 2021-11-05 JasonHu add C908 cache inst - * 2022-11-09 WangXiaoyao Support cache coherence operations; - * improve portability and make - * no assumption on undefined behavior - */ - -#include -#include -#include -#include - -#include "opcode.h" -#include "cache.h" - -#define L1_CACHE_BYTES (64) - -/** - * GCC version not support t-head cache flush, so we use fixed code to achieve. - * The following function cannot be optimized. - */ -static void dcache_wb_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void dcache_inv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void dcache_wbinv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); -static void icache_inv_range(unsigned long start, unsigned long end) __attribute__((optimize("O0"))); - -#define CACHE_OP_RS1 %0 -#define CACHE_OP_RANGE(instr) \ - { \ - rt_ubase_t i = start & ~(L1_CACHE_BYTES - 1); \ - for (; i < end; i += L1_CACHE_BYTES) \ - { \ - __asm__ volatile(instr ::"r"(i) \ - : "memory"); \ - } \ - } - -static void dcache_wb_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_CVA(CACHE_OP_RS1)); -} - -static void dcachel1_wb_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_CVAL1(CACHE_OP_RS1)); -} - -static void dcache_inv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_IVA(CACHE_OP_RS1)); -} - -static void dcache_wbinv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_DCACHE_CIVA(CACHE_OP_RS1)); -} - -static void icache_inv_range(unsigned long start, unsigned long end) -{ - CACHE_OP_RANGE(OPC_ICACHE_IVA(CACHE_OP_RS1)); -} - -rt_inline rt_uint32_t rt_cpu_icache_line_size(void) -{ - return L1_CACHE_BYTES; -} - -rt_inline rt_uint32_t rt_cpu_dcache_line_size(void) -{ - return L1_CACHE_BYTES; -} - -void rt_hw_cpu_icache_invalidate_local(void *addr, int size) -{ - icache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync_i(); -} - -void rt_hw_cpu_dcache_invalidate_local(void *addr, int size) -{ - dcache_inv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -void rt_hw_cpu_dcache_clean_local(void *addr, int size) -{ - dcache_wb_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -void rt_hw_cpu_dcache_clean_invalidate_local(void *addr, int size) -{ - dcache_wbinv_range((unsigned long)addr, (unsigned long)((unsigned char *)addr + size)); - rt_hw_cpu_sync(); -} - -void rt_hw_cpu_dcachel1_clean_local(void *addr, int size) -{ - __asm__ volatile(OPC_DCACHE_CVAL1(a0):: - : "memory"); -} - -/** - * ===================================================== - * Architecture Independent API - * ===================================================== - */ - -void rt_hw_cpu_icache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_INVALIDATE) - { - rt_hw_cpu_icache_invalidate(addr, size); - } -} - -void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_FLUSH) - { - rt_hw_cpu_dcache_clean(addr, size); - } - else - { - rt_hw_cpu_dcache_invalidate(addr, size); - } -} - -void rt_hw_sync_cache_local(void *addr, int size) -{ - rt_hw_cpu_dcachel1_clean_local(addr, size); - rt_hw_cpu_icache_invalidate_local(addr, size); -} diff --git a/libcpu/risc-v/t-head/c908/cache.h b/libcpu/risc-v/t-head/c908/cache.h deleted file mode 100644 index 09ebce6861f..00000000000 --- a/libcpu/risc-v/t-head/c908/cache.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-11-05 JasonHu The first version - * 2022-11-09 WangXiaoyao Distinguish local and broadcast operations - */ - -#ifndef CACHE_H__ -#define CACHE_H__ - -#include "opcode.h" - -#ifndef ALWAYS_INLINE -#define ALWAYS_INLINE inline __attribute__((always_inline)) -#endif - -ALWAYS_INLINE void rt_hw_cpu_sync(void) -{ - asm volatile(OPC_SYNC:: - : "memory"); -} - -ALWAYS_INLINE void rt_hw_cpu_sync_i(void) -{ - asm volatile(OPC_SYNC_I:: - : "memory"); -} - -ALWAYS_INLINE void rt_hw_cpu_sync_s(void) -{ - asm volatile(OPC_SYNC_S:: - : "memory"); -} - -ALWAYS_INLINE void rt_hw_cpu_sync_is(void) -{ - asm volatile(OPC_SYNC_IS:: - : "memory"); -} - -/** - * ======================================== - * Local cpu cache maintainence operations - * ======================================== - */ - -void rt_hw_cpu_dcache_clean_local(void *addr, int size); -void rt_hw_cpu_dcache_invalidate_local(void *addr, int size); -void rt_hw_cpu_dcache_clean_invalidate_local(void *addr, int size); - -void rt_hw_cpu_icache_invalidate_local(void *addr, int size); - -ALWAYS_INLINE void rt_hw_cpu_dcache_clean_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_CALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_dcache_invalidate_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_IALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_dcache_clean_invalidate_all_local(void) -{ - __asm__ volatile(OPC_DCACHE_CIALL :: - : "memory"); - rt_hw_cpu_sync(); -} - -ALWAYS_INLINE void rt_hw_cpu_icache_invalidate_all_local(void) -{ - __asm__ volatile(OPC_ICACHE_IALL :: - : "memory"); - rt_hw_cpu_sync_i(); -} - -#define rt_hw_icache_invalidate_all rt_hw_cpu_icache_invalidate_all - -/** - * ======================================== - * Multi-core cache maintainence operations - * ======================================== - */ - -#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 - -#define rt_hw_cpu_dcache_clean_all rt_hw_cpu_dcache_clean_all_local -#define rt_hw_cpu_dcache_invalidate_all rt_hw_cpu_dcache_invalidate_all_local -#define rt_hw_cpu_dcache_clean_invalidate_all rt_hw_cpu_dcache_clean_invalidate_all_local - -#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 - */ -void rt_hw_sync_cache_local(void *addr, int size); - -#endif /* CACHE_H__ */ diff --git a/libcpu/risc-v/t-head/c908/interrupt.c b/libcpu/risc-v/t-head/c908/interrupt.c deleted file mode 100644 index 2f7a86e6802..00000000000 --- a/libcpu/risc-v/t-head/c908/interrupt.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#include -#include - -#include "interrupt.h" -#include "riscv.h" -#include "plic.h" - -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; - -struct rt_irq_desc isr_table[INTERRUPTS_MAX]; - -static void rt_hw_interrupt_handler(int vector, void *param) -{ - rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); -} - -/** - * This function will initialize hardware interrupt - */ -void rt_hw_interrupt_init(void) -{ - /* init interrupt controller */ - plic_init(); - - rt_int32_t idx; - - rt_memset(isr_table, 0x00, sizeof(isr_table)); - for (idx = 0; idx < INTERRUPTS_MAX; idx++) - { - isr_table[idx].handler = rt_hw_interrupt_handler; - } - - /* 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; -} - -/** - * This function will mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_mask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_disable_irq(vector); -} - -/** - - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return; - } - plic_enable_irq(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param handler the interrupt service routine to be installed - * @param param the interrupt service function parameter - * @param name the interrupt name - * @return old handler - */ -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, - void *param, const char *name) -{ - rt_isr_handler_t old_handler = RT_NULL; - if ((vector < 0) || (vector > IRQ_MAX_NR)) - { - return old_handler; - } - - old_handler = isr_table[IRQ_OFFSET + vector].handler; - -#ifdef RT_USING_INTERRUPT_INFO - rt_strncpy(isr_table[IRQ_OFFSET + vector].name, name, RT_NAME_MAX); -#endif /* RT_USING_INTERRUPT_INFO */ - isr_table[IRQ_OFFSET + vector].handler = handler; - isr_table[IRQ_OFFSET + vector].param = param; - - return old_handler; -} diff --git a/libcpu/risc-v/t-head/c908/interrupt.h b/libcpu/risc-v/t-head/c908/interrupt.h deleted file mode 100644 index 2ee08248375..00000000000 --- a/libcpu/risc-v/t-head/c908/interrupt.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - */ - -#ifndef __INTERRUPT_H__ -#define __INTERRUPT_H__ - -#include - -#define NR_CPUS 1 - -#define IRQ_OFFSET 16 -#ifndef IRQ_MAX_NR -#define IRQ_MAX_NR 200 -#endif -#define INTERRUPTS_MAX (IRQ_OFFSET + IRQ_MAX_NR) - -enum { - EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, - EP_INSTRUCTION_ACCESS_FAULT, - EP_ILLEGAL_INSTRUCTION, - EP_BREAKPOINT, - EP_LOAD_ADDRESS_MISALIGNED, - EP_LOAD_ACCESS_FAULT, - EP_STORE_ADDRESS_MISALIGNED, - EP_STORE_ACCESS_FAULT, - EP_ENVIRONMENT_CALL_U_MODE, - EP_ENVIRONMENT_CALL_S_MODE, - EP_RESERVED10, - EP_ENVIRONMENT_CALL_M_MODE, - EP_INSTRUCTION_PAGE_FAULT, /* page attr */ - EP_LOAD_PAGE_FAULT, /* read data */ - EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ -}; - -void rt_hw_interrupt_init(void); -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); - -#endif diff --git a/libcpu/risc-v/t-head/c908/plic.c b/libcpu/risc-v/t-head/c908/plic.c deleted file mode 100644 index 08cb6c18d2f..00000000000 --- a/libcpu/risc-v/t-head/c908/plic.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2021-11-12 JasonHu fix bug that not intr on f133 - * 2023-04-22 flyingcys add plic register ioremap - */ - -#include - -#include - -#include "plic.h" -#include "interrupt.h" -#include "io.h" -#include "encoding.h" -#include "ioremap.h" - -static void *plic_regs = RT_NULL; -extern struct rt_irq_desc isr_table[]; - -struct plic_handler -{ - rt_bool_t present; - void *hart_base; - void *enable_base; -}; - -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable); -struct plic_handler plic_handlers[C908_NR_CPUS]; -static void *plic_irq_priority[INTERRUPTS_MAX] = {RT_NULL}; - -rt_inline void plic_irq_toggle(int hwirq, int enable) -{ - int cpu = 0; - void *priority_addr; - - /* set priority of interrupt, interrupt 0 is zero. */ - priority_addr = (void *)((rt_size_t)plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); -#ifdef RT_USING_SMART - if (plic_irq_priority[hwirq] == RT_NULL) - { - plic_irq_priority[hwirq] = (void *)rt_ioremap(priority_addr, 0x1000); - } - priority_addr = plic_irq_priority[hwirq]; -#endif - writel(enable, priority_addr); - struct plic_handler *handler = &plic_handlers[cpu]; - - if (handler->present) - { - plic_toggle(handler, hwirq, enable); - } -} - -static void generic_handle_irq(int irq) -{ - rt_isr_handler_t isr; - void *param; - - if (irq < 0 || irq >= IRQ_MAX_NR) - { - LOG_E("bad irq number %d!\n", irq); - return; - } - - if (!irq) // irq = 0 => no irq - { - LOG_W("no irq!\n"); - return; - } - isr = isr_table[IRQ_OFFSET + irq].handler; - param = isr_table[IRQ_OFFSET + irq].param; - if (isr != RT_NULL) - { - isr(irq, param); - } - /* complete irq. */ - plic_complete(irq); -} - -void plic_complete(int irqno) -{ - int cpu = 0; - struct plic_handler *handler = &plic_handlers[cpu]; - - writel(irqno, (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM)); -} - -void plic_disable_irq(int irqno) -{ - plic_irq_toggle(irqno, 0); -} - -void plic_enable_irq(int irqno) -{ - plic_irq_toggle(irqno, 1); -} - -/* - * Handling an interrupt is a two-step process: first you claim the interrupt - * by reading the claim register, then you complete the interrupt by writing - * that source ID back to the same claim register. This automatically enables - * and disables the interrupt, so there's nothing else to do. - */ -void plic_handle_irq(void) -{ - int cpu = 0; - unsigned int irq; - - struct plic_handler *handler = &plic_handlers[cpu]; - void *claim = (void *)((rt_size_t)handler->hart_base + CONTEXT_CLAIM); - - if (plic_regs == RT_NULL || !handler->present) - { - LOG_E("plic state not initialized."); - return; - } - - clear_csr(sie, SIE_SEIE); - - while ((irq = readl(claim))) - { - /* ID0 is diabled permantually from spec. */ - if (irq == 0) - { - LOG_E("irq no is zero."); - } - else - { - generic_handle_irq(irq); - } - } - set_csr(sie, SIE_SEIE); -} - -rt_inline void plic_toggle(struct plic_handler *handler, int hwirq, int enable) -{ - uint32_t *reg = (uint32_t *)((rt_size_t)handler->enable_base + (hwirq / 32) * sizeof(uint32_t)); - uint32_t hwirq_mask = 1 << (hwirq % 32); - - if (enable) - { - writel(readl(reg) | hwirq_mask, reg); - } - else - { - writel(readl(reg) & ~hwirq_mask, reg); - } -} - -void plic_init(void) -{ - int nr_irqs; - int nr_context; - int i; - unsigned long hwirq; - int cpu = 0; - - if (plic_regs) - { - LOG_E("plic already initialized!"); - return; - } - - nr_context = C908_NR_CONTEXT; - - plic_regs = (void *)C908_PLIC_PHY_ADDR; - if (!plic_regs) - { - LOG_E("fatal error, plic is reg space is null."); - return; - } - - 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); -#ifdef RT_USING_SMART - 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); - } - } - - /* Enable supervisor external interrupts. */ - set_csr(sie, SIE_SEIE); -} diff --git a/libcpu/risc-v/t-head/c908/plic.h b/libcpu/risc-v/t-head/c908/plic.h deleted file mode 100644 index 94f00eacdb8..00000000000 --- a/libcpu/risc-v/t-head/c908/plic.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2023, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-10-19 JasonHu first version - * 2023-04-22 flyingcys add C906_PLIC_PHY_ADDR macro judge - */ - -#ifndef __RISCV64_PLIC_H__ -#define __RISCV64_PLIC_H__ - -#include - -#ifndef C908_PLIC_PHY_ADDR -#define C908_PLIC_PHY_ADDR (0xF00000000UL) -#endif -#define C908_PLIC_NR_EXT_IRQS (IRQ_MAX_NR) -#define C908_NR_CPUS (NR_CPUS) - -/* M and S mode context. */ -#define C908_NR_CONTEXT (2) - -#define MAX_DEVICES 1024 -#define MAX_CONTEXTS 15872 - -/* - * Each interrupt source has a priority register associated with it. - * We always hardwire it to one in Linux. - */ -#define PRIORITY_BASE 0 -#define PRIORITY_PER_ID 4 - -/* - * Each hart context has a vector of interrupt enable bits associated with it. - * There's one bit for each interrupt source. - */ -#define ENABLE_BASE 0x2000 -#define ENABLE_PER_HART 0x80 - -/* - * Each hart context has a set of control registers associated with it. Right - * now there's only two: a source priority threshold over which the hart will - * take an interrupt, and a register to claim interrupts. - */ -#define CONTEXT_BASE 0x200000 -#define CONTEXT_PER_HART 0x1000 -#define CONTEXT_THRESHOLD 0x00 -#define CONTEXT_CLAIM 0x04 - -void plic_init(void); -void plic_enable_irq(int irqno); -void plic_disable_irq(int irqno); -// tell PLIC that we've served this IRQ -void plic_complete(int irq); -void plic_handle_irq(void); - -#endif diff --git a/libcpu/risc-v/t-head/c908/riscv_mmu.h b/libcpu/risc-v/t-head/c908/riscv_mmu.h deleted file mode 100644 index 8fbe241f657..00000000000 --- a/libcpu/risc-v/t-head/c908/riscv_mmu.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2021-05-03 lizhirui porting to C906 - * 2023-10-12 Shell Add permission control API - */ - -#ifndef __RISCV_MMU_H__ -#define __RISCV_MMU_H__ - -#include -#include -#include "riscv.h" - -#undef PAGE_SIZE - -/* C-SKY extend */ -#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 PAGE_OFFSET_SHIFT 0 -#define PAGE_OFFSET_BIT 12 -#define PAGE_SIZE __SIZE(PAGE_OFFSET_BIT) -#define PAGE_OFFSET_MASK __MASK(PAGE_OFFSET_BIT) -#define VPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT) -#define VPN0_BIT 9 -#define VPN1_SHIFT (VPN0_SHIFT + VPN0_BIT) -#define VPN1_BIT 9 -#define VPN2_SHIFT (VPN1_SHIFT + VPN1_BIT) -#define VPN2_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 ARCH_ADDRESS_WIDTH_BITS 64 - -#define PHYSICAL_ADDRESS_WIDTH_BITS 56 - -#define PAGE_ATTR_NEXT_LEVEL (0) -#define PAGE_ATTR_RWX (PTE_X | PTE_W | PTE_R) -#define PAGE_ATTR_READONLY (PTE_R) -#define PAGE_ATTR_READEXECUTE (PTE_X | PTE_R) - -#define PAGE_ATTR_USER (PTE_U) -#define PAGE_ATTR_SYSTEM (0) - -#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_NEXT \ - (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G | PTE_SHARE | PTE_BUF | PTE_CACHE | PTE_A | PTE_D) - -#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) - -/** - * encoding of SATP (Supervisor Address Translation and Protection register) - */ -#define SATP_MODE_OFFSET 60 -#define SATP_MODE_BARE 0 -#define SATP_MODE_SV39 8 -#define SATP_MODE_SV48 9 -#define SATP_MODE_SV57 10 -#define SATP_MODE_SV64 11 - -#define ARCH_VADDR_WIDTH 39 -#define SATP_MODE SATP_MODE_SV39 - -//compatible to rt-smart new version -#define MMU_MAP_K_DEVICE (PTE_BUF | PTE_SO | PTE_A | PTE_D | PTE_G | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_K_RW (PTE_SHARE | PTE_A | PTE_D | PTE_G | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_K_RWCB (MMU_MAP_K_RW | PTE_BUF | PTE_CACHE) - -#define MMU_MAP_U_RW (PTE_SHARE | PTE_U | PTE_A | PTE_D | PAGE_ATTR_RWX | PTE_V) -#define MMU_MAP_U_RWCB (MMU_MAP_U_RW | PTE_BUF | PTE_CACHE) -#define MMU_MAP_EARLY \ - PTE_WRAP(PAGE_ATTR_RWX | PTE_G | PTE_V | PTE_CACHE | PTE_SHARE | PTE_BUF) -#define MMU_MAP_TRACE(attr) (attr) - -#define PTE_XWR_MASK 0xe - -#define ARCH_PAGE_SIZE PAGE_SIZE -#define ARCH_PAGE_MASK (ARCH_PAGE_SIZE - 1) -#define ARCH_PAGE_SHIFT PAGE_OFFSET_BIT -#define ARCH_INDEX_WIDTH 9 - -#define ARCH_MAP_FAILED ((void *)0x8000000000000000) - -void mmu_set_pagetable(rt_ubase_t addr); -void mmu_enable_user_page_access(void); -void mmu_disable_user_page_access(void); - -#define RT_HW_MMU_PROT_READ 1 -#define RT_HW_MMU_PROT_WRITE 2 -#define RT_HW_MMU_PROT_EXECUTE 4 -#define RT_HW_MMU_PROT_KERNEL 8 -#define RT_HW_MMU_PROT_USER 16 -#define RT_HW_MMU_PROT_CACHE 32 - -void rt_hw_asid_init(void); -struct rt_aspace; -void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl); - -/** - * @brief Remove permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be removed - * @return size_t returned attribution - */ -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; - /* remove write permission for kernel */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: - attr &= ~PTE_W; - break; - default: - RT_ASSERT(0); - } - return attr; -} - -/** - * @brief Add permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be added - * @return size_t returned attribution - */ -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); - } - return attr; -} - -/** - * @brief Test permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be test - * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE - */ -rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) -{ - rt_bool_t rc = 0; - 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); - } - - if (rc && (prot & RT_HW_MMU_PROT_USER)) - { - rc = !!(attr & PTE_U); - } - return rc; -} - -#endif diff --git a/libcpu/risc-v/t-head/c908/symbol_analysis.c b/libcpu/risc-v/t-head/c908/symbol_analysis.c deleted file mode 100644 index 83edacb1c43..00000000000 --- a/libcpu/risc-v/t-head/c908/symbol_analysis.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright lizhirui - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-18 lizhirui the first version - * 2021-05-20 lizhirui add os debug support - */ - -#include -#include "symbol_analysis.h" - -#define MEMORY_BASE 0x40000000 -#define MEMORY_SIZE (128 * 0x100000) - -extern rt_size_t _osdebug_start; - -static os_symtab_header *symtab_header = (os_symtab_header *)&_osdebug_start; - -//该函数用于在指定的表中查找某个地址对应的符号的描述结构体指针,返回值的符号遵循规则详见文档 -os_symtab_item *find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address) -{ - rt_size_t left = 0; - rt_size_t right = symbol_num; - os_symtab_item *sym_table = (os_symtab_item *)((rt_size_t)&_osdebug_start + symbol_table_addr); - - while(left < right) - { - rt_size_t mid = (left + right) >> 1; - //rt_kprintf("left = %d,right = %d,mid = %d\n",left,right,mid); - - if(address < sym_table[mid].address) - { - right = mid; - - while((right < symbol_num) && ((right - 1) >= 0) && (sym_table[right].address == sym_table[right - 1].address)) - { - right--; - } - } - else if(address == sym_table[mid].address) - { - left = mid + 1; - break; - } - else - { - left = mid; - - while((left >= 0) && ((left + 1) < symbol_num) && (sym_table[left].address == sym_table[left + 1].address)) - { - left++; - } - - left++; - } - } - - left--; - - if(left == ((rt_size_t)-1)) - { - return RT_NULL; - } - - while((left < symbol_num) && ((left - 1) >= 0) && (sym_table[left].address == sym_table[left - 1].address)) - { - left--; - } - - return &sym_table[left]; -} - -//该函数用于根据给定的符号指针从字符串表中找到对应的符号名指针并返回 -const char *get_symbol_name(os_symtab_item *symbol) -{ - return (const char *)((rt_size_t)&_osdebug_start + symtab_header -> string_table_offset + symbol -> name_offset); -} - -//该函数可以根据给定的符号和地址向中断打印出标准格式的符号信息 -void print_symbol(os_symtab_item *symbol,rt_size_t address) -{ - rt_kprintf("<%s(0x%p)",get_symbol_name(symbol),symbol -> address); - - if(symbol -> size) - { - rt_kprintf(" : 0x%x>",symbol -> size); - } - else - { - rt_kprintf(">"); - } - - if(address > symbol -> address) - { - rt_kprintf(" + 0x%x",address - symbol -> address); - } -} - -//该函数用于打印出一个地址关联的全部符号信息 -void print_symbol_info(rt_size_t address,rt_bool_t function) -{ - os_symtab_item *function_symbol = find_symbol_table(symtab_header -> function_table_offset,symtab_header -> function_table_num,address); - os_symtab_item *object_symbol = find_symbol_table(symtab_header -> object_table_offset,symtab_header -> object_table_num,address); - os_symtab_item *general_symbol = find_symbol_table(symtab_header -> general_symbol_table_offset,symtab_header -> general_symbol_table_num,address); - const char *dot = ""; - rt_bool_t valid = RT_FALSE; - - if(function) - { - while(function_symbol != RT_NULL) - { - if((function_symbol -> address + function_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(function_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(function_symbol[0].address == function_symbol[1].address) - { - function_symbol++; - } - - break; - } - - if(!valid) - { - while(general_symbol != RT_NULL) - { - rt_kprintf(dot); - print_symbol(general_symbol,address); - dot = ","; - valid = RT_TRUE; - - if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(general_symbol[0].address == general_symbol[1].address) - { - general_symbol++; - } - - break; - } - - while(object_symbol != RT_NULL) - { - if((object_symbol -> address + object_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(object_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(object_symbol[0].address == object_symbol[1].address) - { - object_symbol++; - } - - break; - } - } - } - else - { - while(object_symbol != RT_NULL) - { - if((object_symbol -> address + object_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(object_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(object_symbol[0].address == object_symbol[1].address) - { - object_symbol++; - } - - break; - } - - if(!valid) - { - while(general_symbol != RT_NULL) - { - rt_kprintf(dot); - print_symbol(general_symbol,address); - dot = ","; - valid = RT_TRUE; - - if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(general_symbol[0].address == general_symbol[1].address) - { - general_symbol++; - } - - break; - } - - while(function_symbol != RT_NULL) - { - if((function_symbol -> address + function_symbol -> size) > address) - { - rt_kprintf(dot); - print_symbol(function_symbol,address); - dot = ","; - valid = RT_TRUE; - } - - if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item))) - { - break; - } - - if(function_symbol[0].address == function_symbol[1].address) - { - function_symbol++; - } - - break; - } - } - } - - if(dot == "") - { - rt_kprintf(""); - } -} - -//该函数用于在出错时打印出栈跟踪信息 -void print_stacktrace(rt_size_t epc,rt_size_t fp) -{ - rt_kprintf("-----------------------------Dump Stacktrace----------------------------\n\n"); - rt_size_t sp = fp; - rt_size_t i = 0; - - rt_kprintf("address 0x%p(",epc); - print_symbol_info(epc,RT_TRUE); - rt_kprintf(")\n\n"); - - while(1) - { - if((sp >= MEMORY_BASE) && (sp < (MEMORY_BASE + MEMORY_SIZE))) - { - //rt_kprintf("%d: 0x%p\n",i,sp); - rt_size_t *stack = (rt_size_t *)(sp - sizeof(rt_size_t) * 2); - rt_size_t ra = stack[1]; - - if(!ra) - { - break; - } - - rt_kprintf("return to 0x%p(",ra); - print_symbol_info(ra,RT_TRUE); - rt_kprintf(")\n\n"); - //rt_kprintf("ra = 0x%p,fp = 0x%p\n",stack[1],stack[0]); - sp = stack[0]; - i++; - } - else - { - break; - } - } - - rt_kprintf("---------------------------------Dump OK--------------------------------\n"); -} diff --git a/libcpu/risc-v/t-head/c908/symbol_analysis.h b/libcpu/risc-v/t-head/c908/symbol_analysis.h deleted file mode 100644 index a9db46ffd39..00000000000 --- a/libcpu/risc-v/t-head/c908/symbol_analysis.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright lizhirui - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-18 lizhirui the first version - * 2021-05-20 lizhirui add os debug support - */ - -#ifndef __SYMBOL_ANALYSIS_H__ -#define __SYMBOL_ANALYSIS_H__ - - #include - - //osdebug节区头描述结构体 - typedef struct os_symtab_header - { - rt_size_t function_table_offset;//函数表的偏移地址(相对于节区起始地址,下同) - rt_size_t function_table_num;//函数表中的符号数量 - rt_size_t object_table_offset;//对象表的偏移地址 - rt_size_t object_table_num;//对象表中的符号数量 - rt_size_t general_symbol_table_offset;//一般符号(指代类型虽为NONE但带有GLOBAL的符号)表的偏移地址 - rt_size_t general_symbol_table_num;//一般符号表中的符号数量 - rt_size_t string_table_offset;//字符串表的偏移地址 - rt_size_t string_table_size;//字符串表的大小(字节为单位) - }os_symtab_header; - - //符号描述结构体 - typedef struct os_symtab_item - { - rt_size_t name_offset;//符号名称在字符串表中的偏移地址 - rt_size_t address;//该符号所代表的地址 - rt_size_t size;//该符号所代表的大小 - }os_symtab_item; - - os_symtab_item *find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address); - const char *get_symbol_name(os_symtab_item *symbol); - void print_symbol(os_symtab_item *symbol,rt_size_t address); - void print_symbol_info(rt_size_t address,rt_bool_t function); - void print_stacktrace(rt_size_t epc,rt_size_t fp); - -#endif diff --git a/libcpu/risc-v/t-head/cache.c b/libcpu/risc-v/t-head/cache.c new file mode 100644 index 00000000000..0434aa626ce --- /dev/null +++ b/libcpu/risc-v/t-head/cache.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-29 lizhirui first version + * 2021-11-05 JasonHu add c906/c908 cache inst + * 2022-11-09 WangXiaoyao Support cache coherence operations; + * improve portability and make + * no assumption on undefined behavior + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#include +#include + +#include +#include +#ifdef RT_USING_SMP +#include +#endif + +#define THEAD_CMD_OP(_op, _sync_op, _start, _size, _cachesize) \ + rt_ubase_t _block = (rt_ubase_t)_start & ~(_cachesize - 1UL) \ + rt_ubase_t _end = (rt_ubase_t)_start + _size; \ + for (; _block < _end; _block += _cachesize) \ + { \ + __asm__ volatile (_op(%0)::"r"(_block):"memory"); \ + } \ + __asm__ volatile (_sync_op:::"memory"); + +static void thead_icache_invalidate_local(void *data) +{ + rt_ubase_t *start_size = data; + rt_uint32_t cachesize = riscv_cache_get_cbom_block_size(); + + THEAD_CMD_OP(OPC_ICACHE_IVA, OPC_SYNC_IS, start_size[0], start_size[1], cachesize); +} + +static void thead_icache_invalidate(void *addr, int size) +{ + rt_ubase_t start_size[2] = { (rt_ubase_t)addr, size }; + + thead_icache_invalidate_local(start_size); + +#ifdef RT_USING_SMP + rt_smp_call_each_cpu(thead_icache_invalidate_local, start_size, SMP_CALL_WAIT_ALL); +#endif +} + +static void thead_icache_invalidate_all_local(void *data) +{ + RT_UNUSED(data); + + __asm__ volatile(OPC_ICACHE_IALL "\n\t" OPC_SYNC_I:::"memory"); +} + +static void thead_icache_invalidate_all(void) +{ + thead_icache_invalidate_all_local(RT_NULL); + +#ifdef RT_USING_SMP + rt_smp_call_each_cpu(thead_icache_invalidate_all_local, RT_NULL, SMP_CALL_WAIT_ALL); +#endif +} + +static void thead_dcache_invalidate(void *addr, int size) +{ + rt_uint32_t cachesize = riscv_cache_get_cbom_block_size(); + + THEAD_CMD_OP(OPC_DCACHE_IVA, OPC_SYNC_S, addr, size, cachesize); +} + +static void thead_dcache_clean(void *addr, int size) +{ + rt_uint32_t cachesize = riscv_cache_get_cbom_block_size(); + + THEAD_CMD_OP(OPC_DCACHE_CVA, OPC_SYNC_S, addr, size, cachesize); +} + +static void thead_dcache_flush(void *addr, int size) +{ + rt_uint32_t cachesize = riscv_cache_get_cbom_block_size(); + + THEAD_CMD_OP(OPC_DCACHE_CIVA, OPC_SYNC_S, addr, size, cachesize); +} + +/** + * ===================================================== + * Architecture Independent API + * ===================================================== + */ + +void rt_hw_cpu_icache_ops(int ops, void *addr, int size) +{ + if (ops == RT_HW_CACHE_INVALIDATE) + { + rt_hw_cpu_icache_invalidate(addr, size); + } +} + +void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) +{ + if (ops == RT_HW_CACHE_FLUSH) + { + thead_dcache_clean(addr, size); + } + else + { + thead_dcache_invalidate(addr, size); + } +} + +void rt_hw_cpu_icache_invalidate_all(void) +{ + thead_icache_invalidate_all(); +} + +void rt_hw_cpu_icache_invalidate(void *addr, rt_size_t size) +{ + thead_icache_invalidate(addr, size); +} + +void rt_hw_cpu_dcache_clean_and_invalidate(void *addr, rt_size_t size) +{ + thead_dcache_flush(addr, size); +} + +void rt_hw_icache_invalidate_all(void) +{ + thead_icache_invalidate_all(); +} + +/** + * @brief Synchronize cache to Point of Unification + */ +void rt_hw_sync_cache_local(void *addr, int size) +{ + __asm__ volatile(OPC_DCACHE_CVAL1(a0)::: "memory"); + + thead_icache_invalidate(addr, size); +} diff --git a/libcpu/risc-v/t-head/mmu_vendor.h b/libcpu/risc-v/t-head/mmu_vendor.h new file mode 100644 index 00000000000..22239bb700d --- /dev/null +++ b/libcpu/risc-v/t-head/mmu_vendor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-01-30 lizhirui first version + * 2021-05-03 lizhirui porting to c906/c908 + * 2023-10-12 Shell Add permission control API + * 2025-04-26 GuEe-GUI Follow the specific and vendor + */ + +#ifndef __MMU_VENDOR_H__ +#define __MMU_VENDOR_H__ + +#include + +/* C-SKY extend */ +#define __PTE_SEC BIT(59) /* Security */ +#define __PTE_SHARE BIT(60) /* Shareable */ +#define __PTE_BUF BIT(61) /* Bufferable */ +#define __PTE_CACHE BIT(62) /* Cacheable */ +#define __PTE_SO BIT(63) /* Strong Order */ + +#define PTE_VENDOR_PMA (__PTE_CACHE | __PTE_BUF | __PTE_SHARE) +#define PTE_VENDOR_NOCACHE (__PTE_BUF | __PTE_SHARE) +#define PTE_VENDOR_IO (__PTE_SO | __PTE_SHARE) + +#define MMU_VENDOR_MAP_K_RW (PTE_ATTR_KERNEL | PTE_G) +#define MMU_VENDOR_MAP_EARLY (MMU_VENDOR_MAP_K_RW | PTE_VENDOR_PMA) + +#endif /* __MMU_VENDOR_H__ */ diff --git a/libcpu/risc-v/t-head/c908/opcode.h b/libcpu/risc-v/t-head/opcode_vendor.h similarity index 73% rename from libcpu/risc-v/t-head/c908/opcode.h rename to libcpu/risc-v/t-head/opcode_vendor.h index 90b002dc4eb..7fb201b7507 100644 --- a/libcpu/risc-v/t-head/c908/opcode.h +++ b/libcpu/risc-v/t-head/opcode_vendor.h @@ -8,8 +8,9 @@ * 2022-11-09 WangXiaoyao Add portable asm support * 2022-03-16 WangXiaoyao Porting to xtheadsync & xtheadcmo ISA extension */ -#ifndef __OPCODE_H__ -#define __OPCODE_H__ + +#ifndef __VENDOR_OPCODE_H__ +#define __VENDOR_OPCODE_H__ /** * @brief binary opcode pseudo operations @@ -23,25 +24,14 @@ * @brief RISC-V instruction formats */ -/** - * R type: .insn r opcode6, func3, func7, rd, rs1, rs2 - * - * +-------+-----+-----+-------+----+---------+ - * | func7 | rs2 | rs1 | func3 | rd | opcode6 | - * +-------+-----+-----+-------+----+---------+ - * 31 25 20 15 12 7 0 - */ -#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \ - ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2) - /** * @brief Xuantie T-HEAD extension ISA format - * Compatible to Xuantie C908 user manual v03 + * Compatible to Xuantie C906R2S1 user manual v06 and C908 user manual v03 */ #define __OPC_INSN_FORMAT_CACHE(func7, rs2, rs1) \ __OPC_INSN_FORMAT_R(0x0b, 0x0, func7, x0, rs1, rs2) -#ifdef _TOOLCHAIN_SUPP_XTHEADE_ISA_ +#ifdef ARCH_TOOLCHAIN_SUPP_XTHEADE_ISA #define OPC_SYNC "sync" #define OPC_SYNC_S "sync.s" #define OPC_SYNC_I "sync.i" @@ -59,7 +49,7 @@ #define OPC_DCACHE_CIVA(rs1) "dcache.civa "RT_STRINGIFY(rs1) #define OPC_ICACHE_IVA(rs1) "icache.iva "RT_STRINGIFY(rs1) -#else /* !_TOOLCHAIN_NOT_SUPP_THEAD_ISA_ */ +#else /* !ARCH_TOOLCHAIN_NOT_SUPP_THEAD_ISA */ #define OPC_SYNC ".long 0x0180000B" #define OPC_SYNC_S ".long 0x0190000B" @@ -78,15 +68,15 @@ #define OPC_DCACHE_CIVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x7, rs1) #define OPC_ICACHE_IVA(rs1) __OPC_INSN_FORMAT_CACHE(0x1, x16, rs1) -#endif /* _TOOLCHAIN_NOT_SUPP_THEAD_ISA_ */ +#endif /* ARCH_TOOLCHAIN_NOT_SUPP_THEAD_ISA */ /** * @brief RISC-V zifencei ISA */ -#ifdef _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ +#ifdef ARCH_TOOLCHAIN_SUPP_ZIFENCEI_ISA #define OPC_FENCE_I "fence.i" -#else /* !_TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ +#else /* !ARCH_TOOLCHAIN_SUPP_ZIFENCEI_ISA */ #define OPC_FENCE_I ".long 0x0000100F" -#endif /* _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ +#endif /* ARCH_TOOLCHAIN_SUPP_ZIFENCEI_ISA */ -#endif /* __OPCODE_H__ */ +#endif /* __VENDOR_OPCODE_H__ */ diff --git a/libcpu/risc-v/t-head/setup.c b/libcpu/risc-v/t-head/setup.c new file mode 100644 index 00000000000..b6e01087f2c --- /dev/null +++ b/libcpu/risc-v/t-head/setup.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2025-04-20 GuEe-GUI the first version + */ + +#include +#include + +void rt_hw_fdt_vendor_install_early(void *fdt) +{ + riscv_isa_ext_set(ZICBOM); + riscv_cache_set_cbom_block_size(L1_CACHE_BYTES); +} diff --git a/libcpu/risc-v/virt64/SConscript b/libcpu/risc-v/virt64/SConscript deleted file mode 100644 index 0e2b4366234..00000000000 --- a/libcpu/risc-v/virt64/SConscript +++ /dev/null @@ -1,10 +0,0 @@ -# RT-Thread building script for component - -from building import * -cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') -CPPPATH = [cwd] - -group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH) - -Return('group') diff --git a/libcpu/risc-v/virt64/cache.c b/libcpu/risc-v/virt64/cache.c deleted file mode 100644 index cd50602e20e..00000000000 --- a/libcpu/risc-v/virt64/cache.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-29 lizhirui first version - */ - -#include -#include -#include -#include -#include - -rt_inline rt_uint32_t rt_cpu_icache_line_size() -{ - return 0; -} - -rt_inline rt_uint32_t rt_cpu_dcache_line_size() -{ - return 0; -} - -void rt_hw_cpu_icache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_INVALIDATE) - { - rt_hw_cpu_icache_invalidate(addr, size); - } -} - -void rt_hw_cpu_dcache_ops(int ops, void *addr, int size) -{ - if (ops == RT_HW_CACHE_FLUSH) - { - rt_hw_cpu_dcache_clean(addr, size); - } - else - { - rt_hw_cpu_dcache_invalidate(addr, size); - } -} - -rt_base_t rt_hw_cpu_icache_status_local() -{ - return 0; -} - -rt_base_t rt_hw_cpu_dcache_status() -{ - return 0; -} - -void rt_hw_sync_cache_local(void *addr, int size) -{ -} diff --git a/libcpu/risc-v/virt64/cache.h b/libcpu/risc-v/virt64/cache.h deleted file mode 100644 index 4ee85327360..00000000000 --- a/libcpu/risc-v/virt64/cache.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-09 RT-Thread The first version - */ -#ifndef __CACHE_H__ -#define __CACHE_H__ - -#include - -/** - * @brief These APIs may not be supported by a specified architecture - * But we have to include to all the cases to be 'general purpose' - */ - -rt_always_inline void rt_hw_cpu_dcache_clean_local(void *addr, int size) -{ - RT_UNUSED(addr); - RT_UNUSED(size); -} - -rt_always_inline void rt_hw_cpu_dcache_invalidate_local(void *addr, int size) -{ - RT_UNUSED(addr); - RT_UNUSED(size); -} - -rt_always_inline void rt_hw_cpu_dcache_clean_and_invalidate_local(void *addr, int size) -{ - RT_UNUSED(addr); - RT_UNUSED(size); -} - -rt_always_inline void rt_hw_cpu_dcache_clean_all_local(void) -{ -} - -rt_always_inline void rt_hw_cpu_dcache_invalidate_all_local(void) -{ -} - -rt_always_inline void rt_hw_cpu_dcache_clean_and_invalidate_all_local(void) -{ -} - -rt_always_inline void rt_hw_cpu_icache_invalidate_local(void *addr, int size) -{ - RT_UNUSED(addr); - RT_UNUSED(size); -} - -rt_always_inline void rt_hw_cpu_icache_invalidate_all_local(void) -{ -} - -/** - * @brief Multi-core - */ - -#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_and_invalidate_local - -#define rt_hw_cpu_dcache_clean_all rt_hw_cpu_dcache_clean_all_local -#define rt_hw_cpu_dcache_invalidate_all rt_hw_cpu_dcache_invalidate_all_local -#define rt_hw_cpu_dcache_clean_and_invalidate_all rt_hw_cpu_dcache_clean_and_invalidate_all_local - -#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 - -#define rt_hw_icache_invalidate_all rt_hw_cpu_icache_invalidate_all - -/** instruction barrier */ -static inline void rt_hw_cpu_sync(void) {} - -/** - * @brief local cpu icahce & dcache synchronization - * - * @param addr - * @param size - */ -void rt_hw_sync_cache_local(void *addr, int size); - -#endif /* __CACHE_H__ */ diff --git a/libcpu/risc-v/virt64/interrupt.c b/libcpu/risc-v/virt64/interrupt.c deleted file mode 100644 index f627210dac2..00000000000 --- a/libcpu/risc-v/virt64/interrupt.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2018/10/01 Bernard The first version - * 2018/12/27 Jesven Change irq enable/disable to cpu0 - */ -#include -#include -#include "tick.h" -#include "encoding.h" -#include "riscv.h" -#include "interrupt.h" - -struct rt_irq_desc irq_desc[MAX_HANDLERS]; - -static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param) -{ - rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector); - return RT_NULL; -} - -int rt_hw_plic_irq_enable(int irq_number) -{ - plic_irq_enable(irq_number); - return 0; -} - -int rt_hw_plic_irq_disable(int irq_number) -{ - plic_irq_disable(irq_number); - return 0; -} - -/** - * This function will un-mask a interrupt. - * @param vector the interrupt number - */ -void rt_hw_interrupt_umask(int vector) -{ - plic_set_priority(vector, 1); - - rt_hw_plic_irq_enable(vector); -} - -/** - * This function will install a interrupt service routine to a interrupt. - * @param vector the interrupt number - * @param new_handler the interrupt service routine to be installed - * @param old_handler the old interrupt service routine - */ -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, - void *param, const char *name) -{ - rt_isr_handler_t old_handler = RT_NULL; - - if(vector < MAX_HANDLERS) - { - old_handler = irq_desc[vector].handler; - if (handler != RT_NULL) - { - irq_desc[vector].handler = (rt_isr_handler_t)handler; - irq_desc[vector].param = param; -#ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); - irq_desc[vector].counter = 0; -#endif - } - } - - return old_handler; -} - -void rt_hw_interrupt_init() -{ - /* Enable machine external interrupts. */ - // set_csr(sie, SIP_SEIP); - int idx = 0; - /* init exceptions table */ - for (idx = 0; idx < MAX_HANDLERS; idx++) - { - irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; - irq_desc[idx].param = RT_NULL; -#ifdef RT_USING_INTERRUPT_INFO - rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); - irq_desc[idx].counter = 0; -#endif - } - - plic_set_threshold(0); -} diff --git a/libcpu/risc-v/virt64/interrupt.h b/libcpu/risc-v/virt64/interrupt.h deleted file mode 100644 index 5b7ff57a476..00000000000 --- a/libcpu/risc-v/virt64/interrupt.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic The first version - */ - -#ifndef INTERRUPT_H__ -#define INTERRUPT_H__ - -#define MAX_HANDLERS 128 - -#include -#include "stack.h" - -enum -{ - EP_INSTRUCTION_ADDRESS_MISALIGNED = 0, - EP_INSTRUCTION_ACCESS_FAULT, - EP_ILLEGAL_INSTRUCTION, - EP_BREAKPOINT, - EP_LOAD_ADDRESS_MISALIGNED, - EP_LOAD_ACCESS_FAULT, - EP_STORE_ADDRESS_MISALIGNED, - EP_STORE_ACCESS_FAULT, - EP_ENVIRONMENT_CALL_U_MODE, - EP_ENVIRONMENT_CALL_S_MODE, - EP_RESERVED10, - EP_ENVIRONMENT_CALL_M_MODE, - EP_INSTRUCTION_PAGE_FAULT, /* page attr */ - EP_LOAD_PAGE_FAULT, /* read data */ - EP_RESERVED14, - EP_STORE_PAGE_FAULT, /* write data */ -}; - -int rt_hw_plic_irq_enable(int irq_number); -int rt_hw_plic_irq_disable(int irq_number); -void rt_hw_interrupt_init(void); -void rt_hw_interrupt_mask(int vector); -rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, const char *name); -void handle_trap(rt_ubase_t xcause, rt_ubase_t xtval, rt_ubase_t xepc, struct rt_hw_stack_frame *sp); - -#endif diff --git a/libcpu/risc-v/virt64/opcode.h b/libcpu/risc-v/virt64/opcode.h deleted file mode 100644 index 14a6a736496..00000000000 --- a/libcpu/risc-v/virt64/opcode.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-11-09 Shell Add portable asm support - */ -#ifndef __OPCODE_H__ -#define __OPCODE_H__ - -/** - * @brief binary opcode pseudo operations - * Used to bypass toolchain restriction on extension ISA - * - */ - -/** - * @brief RISC-V instruction formats - */ - -/** - * R type: .insn r opcode6, func3, func7, rd, rs1, rs2 - * - * +-------+-----+-----+-------+----+---------+ - * | func7 | rs2 | rs1 | func3 | rd | opcode6 | - * +-------+-----+-----+-------+----+---------+ - * 31 25 20 15 12 7 0 - */ -#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \ - ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2) - -#ifdef _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ -#define OPC_FENCE_I "fence.i" -#else /* !_TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ -#define OPC_FENCE_I ".long 0x0000100F" -#endif /* _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */ - -#endif /* __OPCODE_H__ */ \ No newline at end of file diff --git a/libcpu/risc-v/virt64/plic.c b/libcpu/risc-v/virt64/plic.c deleted file mode 100644 index 8aab8b1292b..00000000000 --- a/libcpu/risc-v/virt64/plic.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2022-09-16 WangXiaoyao Porting to rv64 - */ -#include -#include -#include -#include "plic.h" -#include -#include "encoding.h" -#include - -#include -#include -#include - -#ifdef RT_USING_SMART -#include -#else -#define rt_ioremap(addr, ...) (addr) -#endif - -size_t plic_base = 0x0c000000L; - -/* - * Each PLIC interrupt source can be assigned a priority by writing - * to its 32-bit memory-mapped priority register. - * The QEMU-virt (the same as FU540-C000) supports 7 levels of priority. - * A priority value of 0 is reserved to mean "never interrupt" and - * effectively disables the interrupt. - * Priority 1 is the lowest active priority, and priority 7 is the highest. - * Ties between global interrupts of the same priority are broken by - * the Interrupt ID; interrupts with the lowest ID have the highest - * effective priority. - */ -void plic_set_priority(int irq, int priority) -{ - *(uint32_t *)PLIC_PRIORITY(irq) = priority; -} - -/* - * Each global interrupt can be enabled by setting the corresponding - * bit in the enables registers. - */ -void plic_irq_enable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = ((*(uint32_t *)PLIC_ENABLE(hart)) | (1 << irq)); -#ifdef RISCV_VIRT64_S_MODE - set_csr(sie, read_csr(sie) | MIP_SEIP); -#else - set_csr(mie, read_csr(mie) | MIP_MEIP); -#endif -} - -void plic_irq_disable(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_ENABLE(hart) = (((*(uint32_t *)PLIC_ENABLE(hart)) & (~(1 << irq)))); -} - -/* - * PLIC will mask all interrupts of a priority less than or equal to threshold. - * Maximum threshold is 7. - * For example, a threshold value of zero permits all interrupts with - * non-zero priority, whereas a value of 7 masks all interrupts. - * Notice, the threshold is global for PLIC, not for each interrupt source. - */ -void plic_set_threshold(int threshold) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_THRESHOLD(hart) = threshold; -} - -/* - * DESCRIPTION: - * Query the PLIC what interrupt we should serve. - * Perform an interrupt claim by reading the claim register, which - * returns the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - * A successful claim also atomically clears the corresponding pending bit - * on the interrupt source. - * RETURN VALUE: - * the ID of the highest-priority pending interrupt or zero if there - * is no pending interrupt. - */ -int plic_claim(void) -{ - int hart = __raw_hartid(); - int irq = *(uint32_t *)PLIC_CLAIM(hart); - return irq; -} - -/* - * DESCRIPTION: - * Writing the interrupt ID it received from the claim (irq) to the - * complete register would signal the PLIC we've served this IRQ. - * The PLIC does not check whether the completion ID is the same as the - * last claim ID for that target. If the completion ID does not match an - * interrupt source that is currently enabled for the target, the completion - * is silently ignored. - * RETURN VALUE: none - */ -void plic_complete(int irq) -{ - int hart = __raw_hartid(); - *(uint32_t *)PLIC_COMPLETE(hart) = irq; -} - -void plic_set_ie(rt_uint32_t word_index, rt_uint32_t val) -{ - volatile void *plic_ie = (void *)(rt_ubase_t)(plic_base + PLIC_ENABLE_BASE + 0x80 + word_index * 4); - writel(val, plic_ie); -} - -static void _set_sie(int hartid) -{ - for (size_t i = hartid * WORD_CNT_BYTE; i < 32; i++) - plic_set_ie(i, 0xffffffff); -} - -void plic_init() -{ - // PLIC takes up 64 MB space - plic_base = (size_t)rt_ioremap((void *)plic_base, 64 * 1024 * 1024); - - plic_set_threshold(0); - - for (int i = 0; i < CONFIG_IRQ_NR; i++) - { - plic_set_priority(i, 1); - } - - // in a single core system, only current context was set - _set_sie(__raw_hartid()); -} - -extern struct rt_irq_desc irq_desc[MAX_HANDLERS]; -/* - * Handling an interrupt is a two-step process: first you claim the interrupt - * by reading the claim register, then you complete the interrupt by writing - * that source ID back to the same claim register. This automatically enables - * and disables the interrupt, so there's nothing else to do. - */ -void plic_handle_irq(void) -{ - int plic_irq = plic_claim(); - plic_complete(plic_irq); - irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); -} diff --git a/libcpu/risc-v/virt64/plic.h b/libcpu/risc-v/virt64/plic.h deleted file mode 100644 index a13b6d96222..00000000000 --- a/libcpu/risc-v/virt64/plic.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-05-20 bigmagic first version - * 2021-10-20 bernard fix s-mode issue - */ - -#ifndef __PLIC_H__ -#define __PLIC_H__ - -#include -#include - -#define PLIC_PRIORITY_BASE 0x0 -#define PLIC_PENDING_BASE 0x1000 -#define PLIC_ENABLE_BASE 0x2000 -#define PLIC_CONTEXT_BASE 0x200000 - -extern size_t plic_base; - -#define VIRT_PLIC_BASE (plic_base) - -#define PLIC_PRIORITY_OFFSET (0x0) -#define PLIC_PENDING_OFFSET (0x1000) - -#define PLIC_ENABLE_STRIDE 0x80 -#define PLIC_CONTEXT_STRIDE 0x1000 - -/* RT-Thread runs in S-mode on virt64 by default */ -#define RISCV_VIRT64_S_MODE - -#ifndef RISCV_VIRT64_S_MODE -#define PLIC_MENABLE_OFFSET (0x2000) -#define PLIC_MTHRESHOLD_OFFSET (0x200000) -#define PLIC_MCLAIM_OFFSET (0x200004) -#define PLIC_MCOMPLETE_OFFSET (0x200004) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_MENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_MTHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_MCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_MCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) - -#else -#define PLIC_SENABLE_OFFSET (0x2000 + PLIC_ENABLE_STRIDE) -#define PLIC_STHRESHOLD_OFFSET (0x200000 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCLAIM_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) -#define PLIC_SCOMPLETE_OFFSET (0x200004 + PLIC_CONTEXT_STRIDE) - -#define PLIC_ENABLE(hart) (VIRT_PLIC_BASE + PLIC_SENABLE_OFFSET + (hart * 2) * PLIC_ENABLE_STRIDE) -#define PLIC_THRESHOLD(hart) (VIRT_PLIC_BASE + PLIC_STHRESHOLD_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_CLAIM(hart) (VIRT_PLIC_BASE + PLIC_SCLAIM_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#define PLIC_COMPLETE(hart) (VIRT_PLIC_BASE + PLIC_SCOMPLETE_OFFSET + (hart * 2) * PLIC_CONTEXT_STRIDE) -#endif - -#define PLIC_PRIORITY(id) (VIRT_PLIC_BASE + PLIC_PRIORITY_OFFSET + (id) * 4) -#define PLIC_PENDING(id) (VIRT_PLIC_BASE + PLIC_PENDING_OFFSET + ((id) / 32)) - -#define WORD_CNT_BYTE (1024 / 8) - -/* IRQ config in system, max 1024 (from 0 to 1023) */ -#define CONFIG_IRQ_NR (128) -#define CONFIG_IRQ_WORD (CONFIG_IRQ_NR / 32) - -void plic_set_priority(int irq, int priority); -void plic_irq_enable(int irq); -void plic_irq_disable(int irq); -void plic_set_threshold(int mthreshold); -int plic_claim(void); -void plic_complete(int irq); - -void plic_set_thresh(rt_uint32_t val); -void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val); -void plic_init(); -void plic_handle_irq(void); - -#endif diff --git a/libcpu/risc-v/virt64/riscv_mmu.h b/libcpu/risc-v/virt64/riscv_mmu.h deleted file mode 100644 index ca399ab91a9..00000000000 --- a/libcpu/risc-v/virt64/riscv_mmu.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2006-2024, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2021-01-30 lizhirui first version - * 2023-10-12 Shell Add permission control API - */ - -#ifndef __RISCV_MMU_H__ -#define __RISCV_MMU_H__ - -#include -#include -#include "riscv.h" - -#undef PAGE_SIZE - -#define PAGE_OFFSET_SHIFT 0 -#define PAGE_OFFSET_BIT 12 -#define PAGE_SIZE __SIZE(PAGE_OFFSET_BIT) -#define PAGE_OFFSET_MASK __MASK(PAGE_OFFSET_BIT) -#define VPN0_SHIFT (PAGE_OFFSET_SHIFT + PAGE_OFFSET_BIT) -#define VPN0_BIT 9 -#define VPN1_SHIFT (VPN0_SHIFT + VPN0_BIT) -#define VPN1_BIT 9 -#define VPN2_SHIFT (VPN1_SHIFT + VPN1_BIT) -#define VPN2_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 PPN_BITS (PPN0_BIT + PPN1_BIT + PPN2_BIT) - -#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 ARCH_ADDRESS_WIDTH_BITS 64 - -#define PHYSICAL_ADDRESS_WIDTH_BITS 56 - -#define PAGE_ATTR_NEXT_LEVEL (0) -#define PAGE_ATTR_RWX (PTE_X | PTE_W | PTE_R) -#define PAGE_ATTR_READONLY (PTE_R) -#define PAGE_ATTR_READEXECUTE (PTE_X | PTE_R) - -#define PAGE_ATTR_USER (PTE_U) -#define PAGE_ATTR_SYSTEM (0) - -#define PAGE_DEFAULT_ATTR_LEAF (PAGE_ATTR_RWX | PAGE_ATTR_USER | PTE_V | PTE_G) -#define PAGE_DEFAULT_ATTR_NEXT (PAGE_ATTR_NEXT_LEVEL | PTE_V | PTE_G) - -#define PAGE_IS_LEAF(pte) __MASKVALUE(pte, PAGE_ATTR_RWX) - -#define PTE_USED(pte) __MASKVALUE(pte, PTE_V) - -/** - * encoding of SATP (Supervisor Address Translation and Protection register) - */ -#define SATP_MODE_OFFSET 60 -#define SATP_MODE_BARE 0 -#define SATP_MODE_SV39 8 -#define SATP_MODE_SV48 9 -#define SATP_MODE_SV57 10 -#define SATP_MODE_SV64 11 - -#define ARCH_VADDR_WIDTH 39 -#define SATP_MODE SATP_MODE_SV39 - -#define MMU_MAP_K_DEVICE (PTE_G | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_K_RWCB (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_K_RW (PTE_G | PTE_X | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_U_RWCB (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_U_RWCB_XN (PTE_U | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_U_RW (PTE_U | PTE_X | PTE_W | PTE_R | PTE_V) -#define MMU_MAP_EARLY (PAGE_ATTR_RWX | PTE_G | PTE_V) - -#define PTE_XWR_MASK 0xe - -#define ARCH_PAGE_SIZE PAGE_SIZE -#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_INDEX_MASK (ARCH_INDEX_SIZE - 1) - -#define ARCH_MAP_FAILED ((void *)-1) - -void mmu_set_pagetable(rt_ubase_t addr); -void mmu_enable_user_page_access(void); -void mmu_disable_user_page_access(void); - -#define RT_HW_MMU_PROT_READ 1 -#define RT_HW_MMU_PROT_WRITE 2 -#define RT_HW_MMU_PROT_EXECUTE 4 -#define RT_HW_MMU_PROT_KERNEL 8 -#define RT_HW_MMU_PROT_USER 16 -#define RT_HW_MMU_PROT_CACHE 32 - -void rt_hw_asid_init(void); -struct rt_aspace; -void rt_hw_asid_switch_pgtbl(struct rt_aspace *aspace, rt_ubase_t pgtbl); - -/** - * @brief Remove permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be removed - * @return size_t returned attribution - */ -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; - /* remove write permission for kernel */ - case RT_HW_MMU_PROT_WRITE | RT_HW_MMU_PROT_KERNEL: - attr &= ~PTE_W; - break; - default: - RT_ASSERT(0); - } - return attr; -} - -/** - * @brief Add permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be added - * @return size_t returned attribution - */ -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); - } - return attr; -} - -/** - * @brief Test permission from attribution - * - * @param attr architecture specified mmu attribution - * @param prot protect that will be test - * @return rt_bool_t RT_TRUE if the prot is allowed, otherwise RT_FALSE - */ -rt_inline rt_bool_t rt_hw_mmu_attr_test_perm(size_t attr, rt_base_t prot) -{ - rt_bool_t rc = 0; - 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); - } - - if (rc && (prot & RT_HW_MMU_PROT_USER)) - { - rc = !!(attr & PTE_U); - } - return rc; -} - -#endif diff --git a/libcpu/risc-v/virt64/start.c b/libcpu/risc-v/virt64/start.c deleted file mode 100644 index a8c374f6980..00000000000 --- a/libcpu/risc-v/virt64/start.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2006-2022, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes - * 2022-12-07 RT-Thread the first version - */ - -#include -#include -#include "board.h" - -void init_bss(void) -{ - unsigned int *dst; - - dst = &__bss_start; - while (dst < &__bss_end) - { - *dst++ = 0; - } -} diff --git a/src/Kconfig b/src/Kconfig index 099f95e9cfa..caf7c14e8cc 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -46,7 +46,7 @@ config RT_USING_SMART select RT_USING_SYSTEM_WORKQUEUE select RT_USING_CPU_USAGE_TRACER select RT_USING_SCHED_THREAD_CTX - depends on ARCH_ARM_CORTEX_M || ARCH_ARM_ARM9 || ARCH_ARM_CORTEX_A || ARCH_ARMV8 || ARCH_RISCV64 + depends on ARCH_ARM_CORTEX_M || ARCH_ARM_ARM9 || ARCH_ARM_CORTEX_A || ARCH_ARMV8 || (ARCH_RISCV && ARCH_MM_MMU) depends on !RT_USING_NANO help RT-Thread Smart is a microkernel based operating system on RT-Thread. diff --git a/src/clock.c b/src/clock.c index 3481f22c61c..0d711f5180f 100644 --- a/src/clock.c +++ b/src/clock.c @@ -28,7 +28,7 @@ #endif #ifdef RT_USING_SMP -#define rt_tick rt_cpu_index(0)->tick +#define rt_tick rt_cpu_index(rt_hw_master_cpu_id())->tick #else static volatile rt_atomic_t rt_tick = 0; #endif /* RT_USING_SMP */ @@ -139,7 +139,7 @@ void rt_tick_increase(void) /* check timer */ #ifdef RT_USING_SMP - if (rt_cpu_get_id() != 0) + if (rt_cpu_get_id() != rt_hw_master_cpu_id()) { return; } @@ -173,7 +173,7 @@ void rt_tick_increase_tick(rt_tick_t tick) /* check timer */ #ifdef RT_USING_SMP - if (rt_cpu_get_id() != 0) + if (rt_cpu_get_id() != rt_hw_master_cpu_id()) { return; } diff --git a/src/idle.c b/src/idle.c index ce32149f9a8..f30be248695 100644 --- a/src/idle.c +++ b/src/idle.c @@ -127,7 +127,7 @@ static void idle_thread_entry(void *parameter) { RT_UNUSED(parameter); #ifdef RT_USING_SMP - if (rt_cpu_get_id() != 0) + if (rt_cpu_get_id() != rt_hw_master_cpu_id()) { while (1) { diff --git a/src/timer.c b/src/timer.c index ae6da29f760..6518fd18a1c 100644 --- a/src/timer.c +++ b/src/timer.c @@ -750,8 +750,8 @@ void rt_timer_check(void) RT_ASSERT(rt_interrupt_get_nest() > 0); #ifdef RT_USING_SMP - /* Running on core 0 only */ - if (rt_cpu_get_id() != 0) + /* Running on master core only */ + if (rt_cpu_get_id() != rt_hw_master_cpu_id()) { return; }