diff --git a/bsp/qemu-virt64-riscv/.config b/bsp/qemu-virt64-riscv/.config index 510c8d77456b31ec1a73120b9015b42d428f6948..797dd28780760915838ea1054eae8a5e94f3e93d 100644 --- a/bsp/qemu-virt64-riscv/.config +++ b/bsp/qemu-virt64-riscv/.config @@ -16,7 +16,7 @@ CONFIG_RT_THREAD_PRIORITY_32=y # CONFIG_RT_THREAD_PRIORITY_256 is not set CONFIG_RT_THREAD_PRIORITY_MAX=32 CONFIG_RT_TICK_PER_SECOND=100 -# CONFIG_RT_USING_OVERFLOW_CHECK is not set +CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 @@ -102,12 +102,12 @@ CONFIG_RT_USING_MSH=y CONFIG_FINSH_USING_MSH=y CONFIG_FINSH_THREAD_NAME="tshell" CONFIG_FINSH_USING_HISTORY=y -CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_HISTORY_LINES=10 CONFIG_FINSH_USING_SYMTAB=y CONFIG_FINSH_USING_DESCRIPTION=y # CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set CONFIG_FINSH_THREAD_PRIORITY=20 -CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_THREAD_STACK_SIZE=16384 CONFIG_FINSH_CMD_SIZE=80 # CONFIG_FINSH_USING_AUTH is not set CONFIG_FINSH_ARG_MAX=10 @@ -142,6 +142,7 @@ CONFIG_RT_USING_DFS_DEVFS=y CONFIG_RT_USING_DFS_ROMFS=y # CONFIG_RT_USING_DFS_CROMFS is not set # CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_TMPFS is not set # CONFIG_RT_USING_DFS_UFFS is not set # CONFIG_RT_USING_DFS_JFFS2 is not set # CONFIG_RT_USING_DFS_NFS is not set @@ -562,6 +563,7 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_HASH_MATCH is not set # CONFIG_PKG_USING_FIRE_PID_CURVE is not set # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set +# CONFIG_PKG_USING_VOFA_PLUS is not set # # system packages @@ -597,7 +599,6 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_UC_CLK is not set # CONFIG_PKG_USING_UC_COMMON is not set # CONFIG_PKG_USING_UC_MODBUS is not set -# CONFIG_PKG_USING_RTDUINO is not set # CONFIG_PKG_USING_FREERTOS_WRAPPER is not set # CONFIG_PKG_USING_CAIRO is not set # CONFIG_PKG_USING_PIXMAN is not set @@ -632,6 +633,7 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_KMULTI_RTIMER is not set # CONFIG_PKG_USING_TFDB is not set # CONFIG_PKG_USING_QPC is not set +# CONFIG_PKG_USING_AGILE_UPGRADE is not set # # peripheral libraries and drivers @@ -643,7 +645,7 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_ADT74XX is not set # CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set -# CONFIG_PKG_USING_RTT_ESP_IDF is not set +# CONFIG_PKG_USING_ESP_IDF is not set # CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set @@ -798,9 +800,176 @@ CONFIG_RT_LWP_SHM_MAX_NR=64 # CONFIG_PKG_USING_MFBD is not set # CONFIG_PKG_USING_SLCAN2RTT is not set # CONFIG_PKG_USING_SOEM is not set -CONFIG_BOARD_virt=y -CONFIG_ENABLE_FPU=y -# CONFIG_RT_USING_USERSPACE_32BIT_LIMIT is not set +# CONFIG_PKG_USING_QPARAM is not set + +# +# Arduino libraries +# +# CONFIG_PKG_USING_RTDUINO is not set + +# +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set +# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set + +# +# Sensors +# +# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set +# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set +# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set +# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set +# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set + +# +# Display +# +# CONFIG_PKG_USING_ARDUINO_U8G2 is not set + +# +# Timing +# +# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set + +# +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set +# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set + +# +# Data Storage +# + +# +# Communication +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set + +# +# Device Control +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set + +# +# Uncategorized +# # # RISC-V QEMU virt64 configs @@ -812,4 +981,9 @@ CONFIG_BSP_USING_VIRTIO_NET=y # CONFIG_BSP_USING_VIRTIO_GPU is not set # CONFIG_BSP_USING_VIRTIO_INPUT is not set # CONFIG_BSP_USING_UART1 is not set +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_ARCH_USING_NEW_CTX_SWITCH=y CONFIG___STACKSIZE__=16384 diff --git a/bsp/qemu-virt64-riscv/Kconfig b/bsp/qemu-virt64-riscv/Kconfig index 4411c401beb172dd92248172717dcefb13621af5..2edc9b260565c61c2d95e6862fc9531a606ba557 100644 --- a/bsp/qemu-virt64-riscv/Kconfig +++ b/bsp/qemu-virt64-riscv/Kconfig @@ -17,10 +17,12 @@ config PKGS_DIR source "$RTT_DIR/Kconfig" source "$PKGS_DIR/Kconfig" +source "driver/Kconfig" -config BOARD_virt +config BOARD_QEMU_VIRT_RV64 bool select ARCH_RISCV64 + select ARCH_CONTEXT_EXTEND select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN select RT_USING_CACHE @@ -35,6 +37,23 @@ config ENABLE_FPU bool "Enable FPU" default y +config ENABLE_VECTOR + bool "Using RISC-V Vector Extension" + 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 @@ -43,7 +62,9 @@ config RT_USING_VIRTIO_MMIO_ALIGN bool "Open packed attribution, this may caused an error on virtio" default n -source "driver/Kconfig" +config ARCH_USING_NEW_CTX_SWITCH + bool + default y config __STACKSIZE__ int "stack size for interrupt" diff --git a/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript b/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..92c4259bdb5cf7bdfaf76518c51ccfd6824bdb1c --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/test/test_vector/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd] + +group = DefineGroup('Vector', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c b/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c new file mode 100644 index 0000000000000000000000000000000000000000..50aae80248032d34116f0656493b1765f593985b --- /dev/null +++ b/bsp/qemu-virt64-riscv/applications/test/test_vector/test_vector.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ +#include +#include +#include +#include + +#if defined(RT_USING_UTEST) && defined(ENABLE_VECTOR) +#include +#include + +void rt_hw_vector_ctx_restore(void *buf); +void rt_hw_vector_ctx_save(void *buf); + +/** + * ============================================================== + * TEST FEATURE + * Use libc `memcpy` which employing V extension codes + * to test V extension features + * ============================================================== + */ +static char *constant = "hello,it's a nice day and i'm happy to see you\n"; +#define ARR_SIZE 4096 +static char array[ARR_SIZE]; + +static void test_feature(void) +{ + memcpy(array, constant, sizeof array); + char *src = constant; + char *dst = array; + int error = 0; + + for (size_t i = 0; i < ARR_SIZE; i++) + { + if (src[i] != dst[i]) + { + error = 1; + break; + } + } + + uassert_false(error); +} + +/** + * ============================================================== + * TEST CONTEXT SAVING + * Create 2 threads employing V extension, verify V states are + * not modified by each other + * ============================================================== + */ +#define TEST_THREAD 2 +#define VECTOR_CTX_BYTES (CTX_VECTOR_REG_NR * REGBYTES) +void *ctx_vector[TEST_THREAD * 2]; + +static rt_sem_t sem; + +void dump_frame(void *frame) +{ + uint64_t *content = frame; + for (size_t i = 0; i < VECTOR_CTX_BYTES / 8; i++) + { + rt_kprintf("%x ", content[i]); + } + rt_kprintf("\n"); +} + +static void vector_child(void *param) +{ + void **ctx = param; + uint64_t *reg = ctx[0]; + uint64_t vtype; + uint64_t vl; + + rt_sem_release(sem); + + rt_hw_vector_ctx_restore(ctx[0]); + + /* STAGE 2, save t2 context */ + test_feature(); + + /** + * @brief vtype & vl will be modified after context saving, + * it's ok because it will be recover after context restoring + * We restore these states manually here. + */ + asm volatile("csrr %0, vtype":"=r"(vtype)); + asm volatile("csrr %0, vl":"=r"(vl)); + rt_hw_vector_ctx_save(ctx[0]); + + rt_memcpy(ctx[1], ctx[0], VECTOR_CTX_BYTES); + + rt_thread_yield(); + + asm volatile("vsetvl x0, %0, %1"::"r"(vl), "r"(vtype)); + rt_hw_vector_ctx_save(ctx[0]); + + uassert_false(rt_memcmp(ctx[1], ctx[0], VECTOR_CTX_BYTES)); +} + +/** + * @brief Test if context save/restore codes work properly + */ +static void test_context() +{ + rt_thread_t child; + uint64_t vtype; + uint64_t vl; + + for (size_t i = 0; i < TEST_THREAD; i++) + { + ctx_vector[i * 2] = calloc(VECTOR_CTX_BYTES, 1); + ctx_vector[i * 2 + 1] = calloc(VECTOR_CTX_BYTES, 1); + } + rt_hw_vector_ctx_restore(ctx_vector[0]); + + child = rt_thread_create("test_vector_child", vector_child, &ctx_vector[2], 4096, 10, 20); + + /* STAGE 1, save t1 context */ + /* assuming that rt libc memcpy do not use vector instruction */ + asm volatile("csrr %0, vtype":"=r"(vtype)); + asm volatile("csrr %0, vl":"=r"(vl)); + rt_hw_vector_ctx_save(ctx_vector[0]); + + rt_memcpy(ctx_vector[1], ctx_vector[0], VECTOR_CTX_BYTES); + + rt_thread_startup(child); + rt_sem_take(sem, 0); + + /* STAGE 3, verify t1 context */ + asm volatile("vsetvl x0, %0, %1"::"r"(vl), "r"(vtype)); + rt_hw_vector_ctx_save(ctx_vector[0]); + uassert_false(rt_memcmp(ctx_vector[1], ctx_vector[0], VECTOR_CTX_BYTES)); + + rt_thread_yield(); +} + +/** + * ============================================================== + * TEST NO VECTOR raise error and recover + * ============================================================== + */ + +static void test_no_vector() +{ + asm volatile ("li t0, 0x600\n" + "csrc sstatus, t0"); + test_feature(); + uassert_true(1); +} + +static rt_err_t utest_tc_init(void) +{ + sem = rt_sem_create("test_ctx", 0, RT_IPC_FLAG_FIFO); + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + rt_sem_delete(sem); + return RT_EOK; +} + +static void testcase(void) +{ + UTEST_UNIT_RUN(test_feature); + UTEST_UNIT_RUN(test_context); + UTEST_UNIT_RUN(test_no_vector); +} + +UTEST_TC_EXPORT(testcase, "testcases.libcpu.vector", utest_tc_init, utest_tc_cleanup, 10); +#endif /* RT_USING_UTEST && ENABLE_VECTOR */ diff --git a/bsp/qemu-virt64-riscv/rtconfig.h b/bsp/qemu-virt64-riscv/rtconfig.h index 2899d7cca1d814c90d639f42d1f3d4e603d4e45f..a142be0ca0c33cb918594950735875e49afe7ea0 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.h +++ b/bsp/qemu-virt64-riscv/rtconfig.h @@ -12,6 +12,7 @@ #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 #define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 @@ -71,11 +72,11 @@ #define FINSH_USING_MSH #define FINSH_THREAD_NAME "tshell" #define FINSH_USING_HISTORY -#define FINSH_HISTORY_LINES 5 +#define FINSH_HISTORY_LINES 10 #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION #define FINSH_THREAD_PRIORITY 20 -#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_THREAD_STACK_SIZE 16384 #define FINSH_CMD_SIZE 80 #define FINSH_ARG_MAX 10 @@ -297,14 +298,48 @@ /* entertainment: terminal games and other interesting software packages */ -#define BOARD_virt -#define ENABLE_FPU + +/* Arduino libraries */ + + +/* Projects */ + + +/* Sensors */ + + +/* Display */ + + +/* Timing */ + + +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + + +/* Device Control */ + + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ /* RISC-V QEMU virt64 configs */ #define RISCV_S_MODE #define BSP_USING_VIRTIO_BLK #define BSP_USING_VIRTIO_NET +#define BOARD_QEMU_VIRT_RV64 +#define ENABLE_FPU +#define ARCH_USING_NEW_CTX_SWITCH #define __STACKSIZE__ 16384 #endif diff --git a/bsp/qemu-virt64-riscv/rtconfig.py b/bsp/qemu-virt64-riscv/rtconfig.py index 9202bd684a891ecbd7f006a065ff370ce54ac8dc..63325f172c8cc1b4a0e8a182b12f28e173dfbb46 100644 --- a/bsp/qemu-virt64-riscv/rtconfig.py +++ b/bsp/qemu-virt64-riscv/rtconfig.py @@ -37,15 +37,15 @@ if PLATFORM == 'gcc': OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' - DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64' - CFLAGS = DEVICE + ' -fvar-tracking -ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields' - AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp' + DEVICE = ' -mcmodel=medany -march=rv64imafdc -mabi=lp64 ' + CFLAGS = DEVICE + '-ffreestanding -fno-common -ffunction-sections -fdata-sections -fstrict-volatile-bitfields' + 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' CPATH = '' LPATH = '' if BUILD == 'debug': - CFLAGS += ' -O0 -ggdb' + CFLAGS += ' -O0 -ggdb -fvar-tracking ' AFLAGS += ' -ggdb' else: CFLAGS += ' -O2 -Os' diff --git a/components/lwp/arch/risc-v/rv64/lwp_gcc.S b/components/lwp/arch/risc-v/rv64/lwp_gcc.S index 2ba9ced92b9e81ae12c5212a27dcfc5903725340..fbf26de6e75ae833c40fb2fa56d733cfce648057 100644 --- a/components/lwp/arch/risc-v/rv64/lwp_gcc.S +++ b/components/lwp/arch/risc-v/rv64/lwp_gcc.S @@ -25,6 +25,8 @@ .global arch_start_umode .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 @@ -57,18 +59,20 @@ arch_crt_start_umode: mv sp, a0//user_sp mv ra, a0//return address mv a0, s0//args + + csrw sscratch, s3 sret//enter user mode .global arch_ret_to_user arch_ret_to_user: call lwp_signal_check beqz a0, ret_to_user_exit - RESTORE_ALL - //now sp is user sp + // now sp is user sp J user_do_signal ret_to_user_exit: RESTORE_ALL + // `RESTORE_ALL` also reset sp to user sp sret /*#ifdef RT_USING_LWP @@ -127,23 +131,27 @@ lwp_check_debug_quit: //#endif */ -.global arch_signal_quit arch_signal_quit: call lwp_signal_restore //a0 is user_ctx mv sp, a0 RESTORE_ALL + csrw sscratch, zero sret user_do_signal: - //now sp is user sp - //save context to user sp + csrw sscratch, sp + RESTORE_ALL + // now sp is user sp + // and in interrupt close SAVE_ALL - //ensure original user sp correct + + // save user sp in SAVE_ALL frame mv t0, sp addi t0, t0, CTX_REG_NR * REGBYTES - STORE t0, CTX_REG_NR * REGBYTES(sp) - OPEN_INTERRUPT + STORE t0, 32 * REGBYTES(sp) + + // save lwp_sigreturn in user memory mv s0, sp la t0, lwp_sigreturn//t0 = src la t1, lwp_sigreturn_end @@ -159,25 +167,53 @@ lwp_sigreturn_copy_loop: mv t1, t2 bnez t1, lwp_sigreturn_copy_loop - mv a0, sp//sp - li a1, 0//pc - li a2, 0//flag + // restore kernel stack + csrrw sp, sscratch, s0 + + /** + * a0: user sp + * a1: user_pc (not used) + * a2: user_flag (not used) + */ + csrr a0, sscratch + mv a1, zero + mv a2, zero call lwp_signal_backup - //a0 = signal id - mv sp, s0//update new sp - mv s2, a0//signal id backup - call lwp_sighandler_get//need a0 returned by lwp_signal_backup - mv ra, s0//lwp_sigreturn func addr - mv s1, s0//if func = 0,s1 = lwp_sigreturn func + // a0 <- signal id + + // restore kernel sp to initial, and load `sp` to user stack + + // s2 <- signal id(a0) + mv s2, a0 + call lwp_sighandler_get + // a0 <- signal_handler + + // ra <- lwp_sigreturn + mv ra, s0 + + mv s1, s0 beqz a0, skip_user_signal_handler + // a0 <- signal_handler mv s1, a0 skip_user_signal_handler: - li t0, 0x100 - csrc sstatus, t0 + // 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 + + /** + * sp <- user sp + * sscratch <- kernel sp + */ + csrrw sp, sscratch, sp + + // sepc <- signal_handler csrw sepc, s1 - mv a0, s2//signal id as arg 0 - sret//enter lwp signal handler + // a0 <- signal id + mv a0, s2 + sret .align 3 lwp_debugreturn: @@ -235,6 +271,7 @@ arch_clone_exit: .global syscall_entry syscall_entry: +#ifndef ARCH_USING_NEW_CTX_SWITCH //swap to thread kernel stack csrr t0, sstatus andi t0, t0, 0x100 @@ -265,7 +302,7 @@ copy_context_loop: addi t1, t1, 8 addi t2, t2, 8 bnez s0, copy_context_loop - +#endif /* ARCH_USING_NEW_CTX_SWITCH */ LOAD s0, 7 * REGBYTES(sp) addi s0, s0, -0xfe beqz s0, arch_signal_quit @@ -289,10 +326,9 @@ arch_syscall_exit: LOAD s0, 2 * REGBYTES(sp) andi s0, s0, 0x100 bnez s0, dont_ret_to_user - li s0, 0 j arch_ret_to_user - dont_ret_to_user: #endif +dont_ret_to_user: #ifdef RT_USING_USERSPACE /* restore setting when syscall exit */ @@ -305,5 +341,6 @@ arch_syscall_exit: //restore context RESTORE_ALL + csrw sscratch, zero sret diff --git a/libcpu/risc-v/virt64/backtrace.c b/libcpu/risc-v/virt64/backtrace.c index e60a2d7f0bc3c789b46c20b32336d960d65bed98..a23f1394ede5618fb30e6a4b60b5207117313b3c 100644 --- a/libcpu/risc-v/virt64/backtrace.c +++ b/libcpu/risc-v/virt64/backtrace.c @@ -18,6 +18,7 @@ static char *_get_elf_name(); void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc) { + extern rt_mmu_info mmu_info; rt_ubase_t *ra; rt_ubase_t *fp; rt_ubase_t vas, vae; @@ -57,15 +58,17 @@ void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc) } ra = fp - 1; - if (*ra < vas || *ra > vae) + if (!rt_hw_mmu_v2p(&mmu_info, ra) || *ra < vas || *ra > vae) break; rt_kprintf(" %p", *ra - 0x04); fp = fp - 2; - if (!fp) + if (!rt_hw_mmu_v2p(&mmu_info, fp)) break; fp = (rt_ubase_t *)(*fp); + if (!fp) + break; } rt_kputs("\r\n"); @@ -76,6 +79,7 @@ static void _assert_backtrace_cb(const char *ex, const char *func, rt_size_t lin rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex, func, line); rt_hw_backtrace(0, 0); + rt_hw_cpu_shutdown(); } static int rt_hw_backtrace_init(void) diff --git a/libcpu/risc-v/virt64/context_gcc.S b/libcpu/risc-v/virt64/context_gcc.S index adf5a50301d16c156f8d9650b9944b2a6f186e26..23a0b014e93a07118f541d0b917ed8f23df4fe4f 100644 --- a/libcpu/risc-v/virt64/context_gcc.S +++ b/libcpu/risc-v/virt64/context_gcc.S @@ -8,13 +8,70 @@ * 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 WangXiaoyao Support User mode RVV; + * Trimming process switch context */ -#define __ASSEMBLY__ #include "cpuport.h" #include "stackframe.h" - .globl rt_hw_context_switch_to +.macro PUSH_8 reg + addi sp, sp, -8 + STORE \reg, (sp) +.endm + +.macro POP_8 reg + LOAD \reg, (sp) + addi sp, sp, 8 +.endm + +.macro RESERVE_CONTEXT + PUSH_8 tp + PUSH_8 ra + PUSH_8 s0 + PUSH_8 s1 + PUSH_8 s2 + PUSH_8 s3 + PUSH_8 s4 + PUSH_8 s5 + PUSH_8 s6 + PUSH_8 s7 + PUSH_8 s8 + PUSH_8 s9 + PUSH_8 s10 + PUSH_8 s11 + csrr s11, sstatus + li s10, (SSTATUS_SPP) + or s11, s11, s10 + PUSH_8 s11 +.endm + +.macro RESTORE_CONTEXT + POP_8 s11 + csrw sstatus, s11 + POP_8 s11 + POP_8 s10 + POP_8 s9 + POP_8 s8 + POP_8 s7 + POP_8 s6 + POP_8 s5 + POP_8 s4 + POP_8 s3 + POP_8 s2 + POP_8 s1 + POP_8 s0 + POP_8 ra + POP_8 tp + 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) @@ -26,31 +83,26 @@ rt_hw_context_switch_to: jal lwp_mmu_switch #endif - RESTORE_ALL + RESTORE_CONTEXT sret /* * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); * - * a0 --> from - * a1 --> to + * a0 --> from SP pointer + * a1 --> to SP pointer + * + * It should only be used on local interrupt disable */ - .globl rt_hw_context_switch +.globl rt_hw_context_switch rt_hw_context_switch: - mv t2, sp - li t0, 0x120//set SPIE and SPP = 1 - csrs sstatus, t0//if enter here,caller must be in system thread - csrw sepc, ra//return address - //saved from thread context - SAVE_ALL - - STORE t2, 32 * REGBYTES(sp)//save user_sp - + RESERVE_CONTEXT STORE sp, (a0) - //restore to thread context + // restore to thread SP LOAD sp, (a1) + // restore Address Space la s0, rt_current_thread LOAD s1, (s0) @@ -59,9 +111,35 @@ rt_hw_context_switch: jal lwp_mmu_switch #endif - LOAD t0, 2 * REGBYTES(sp) - andi t0, t0, 0x100 - beqz t0, arch_ret_to_user - - RESTORE_ALL + RESTORE_CONTEXT sret + +#ifdef ENABLE_VECTOR +/** + * @param a0 pointer to frame bottom + */ +.global rt_hw_vector_ctx_save +rt_hw_vector_ctx_save: + SAVE_VECTOR a0 + ret + +/** + * @param a0 pointer to frame bottom + */ +.global rt_hw_vector_ctx_restore +rt_hw_vector_ctx_restore: + RESTORE_VECTOR a0 + ret + +.global rt_hw_disable_vector +rt_hw_disable_vector: + li t0, SSTATUS_VS + csrc sstatus, t0 + ret + +.global rt_hw_enable_vector +rt_hw_enable_vector: + li t0, SSTATUS_VS + csrs sstatus, t0 + ret +#endif /* ENABLE_VECTOR */ diff --git a/libcpu/risc-v/virt64/cpuport.c b/libcpu/risc-v/virt64/cpuport.c index c4210a283726b7b88f84e0a2042c17abb9164066..09f8d0d1aadd4409ac444d0b58a7b2d5a19483d5 100644 --- a/libcpu/risc-v/virt64/cpuport.c +++ b/libcpu/risc-v/virt64/cpuport.c @@ -14,30 +14,34 @@ #include "cpuport.h" #include "stack.h" +#include "sbi.h" #include +#define K_SSTATUS_DEFAULT (SSTATUS_SPP | SSTATUS_SPIE | SSTATUS_SUM | SSTATUS_FS) /** * @brief from thread used interrupt context switch * */ -volatile rt_ubase_t rt_interrupt_from_thread = 0; +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; +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; - /** - * This function will initialize thread stack + * 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 @@ -45,41 +49,38 @@ volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0; * * @return stack address */ -rt_uint8_t *rt_hw_stack_init(void *tentry, - void *parameter, +rt_uint8_t *rt_hw_stack_init(void *tentry, + void *parameter, rt_uint8_t *stack_addr, - void *texit) + void *texit) { - struct rt_hw_stack_frame *frame; - rt_uint8_t *stk; - int i; - extern int __global_pointer$; - - 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->gp = (rt_ubase_t)&__global_pointer$; - frame->a0 = (rt_ubase_t)parameter; - frame->epc = (rt_ubase_t)tentry; - frame->user_sp_exc_stack = (rt_ubase_t)(((rt_ubase_t)stk) + sizeof(struct rt_hw_stack_frame)); - - /* force to supervisor mode(SPP=1) and set SPIE and SUM to 1 */ -#ifdef ENABLE_FPU - frame->sstatus = 0x00046120; /* enable FPU */ -#else - frame->sstatus = 0x00040120; -#endif - - return stk; + 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; + + /* compatible to RESTORE_CONTEXT */ + extern void _rt_thread_entry(void); + (*--sp) = 0; /* tp */ + (*--sp) = (rt_ubase_t)_rt_thread_entry; /* ra */ + (*--sp) = 0; /* s0(fp) */ + (*--sp) = 0; /* s1 */ + (*--sp) = 0; /* s2 */ + (*--sp) = 0; /* s3 */ + (*--sp) = 0; /* s4 */ + (*--sp) = 0; /* s5 */ + (*--sp) = 0; /* s6 */ + (*--sp) = 0; /* s7 */ + (*--sp) = 0; /* s8 */ + (*--sp) = 0; /* s9 */ + (*--sp) = 0; /* s10 */ + (*--sp) = 0; /* s11 */ + (*--sp) = K_SSTATUS_DEFAULT; /* sstatus */ + + return (rt_uint8_t *)sp; } /* @@ -98,7 +99,7 @@ void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t rt_interrupt_to_thread = to; rt_thread_switch_interrupt_flag = 1; - return ; + return; } #endif /* end of RT_USING_SMP */ @@ -109,14 +110,14 @@ void rt_hw_cpu_shutdown() rt_kprintf("shutdown...\n"); level = rt_hw_interrupt_disable(); - while (level) - { - RT_ASSERT(0); - } + + sbi_shutdown(); + + while (1) + ; } void rt_hw_set_process_id(int pid) { - //TODO + // TODO } - diff --git a/libcpu/risc-v/virt64/cpuport.h b/libcpu/risc-v/virt64/cpuport.h index 9895f9a199851a917464a8ffcc880fdb1984dbc7..a84cdb2d33b129bcf6db28fa7f6320ce8ccd142f 100644 --- a/libcpu/risc-v/virt64/cpuport.h +++ b/libcpu/risc-v/virt64/cpuport.h @@ -20,6 +20,7 @@ #define REGBYTES 8 #else // error here, not portable +#error "Not supported XLEN" #endif /* 33 general register */ @@ -32,8 +33,21 @@ #define CTX_FPU_REG_NR 0 #endif +#ifdef ENABLE_VECTOR + +#if defined(ARCH_VECTOR_VLEN_128) +#define CTX_VECTOR_REGS 64 +#elif defined(ARCH_VECTOR_VLEN_256) +#define CTX_VECTOR_REGS 128 +#endif + +#define CTX_VECTOR_REG_NR (CTX_VECTOR_REGS + 4) +#else +#define CTX_VECTOR_REG_NR 0 +#endif + /* all context registers */ -#define CTX_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) +#define CTX_REG_NR (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR + CTX_VECTOR_REG_NR) #ifndef __ASSEMBLY__ rt_inline void rt_hw_dsb() diff --git a/libcpu/risc-v/virt64/cpuport_gcc.S b/libcpu/risc-v/virt64/cpuport_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..cb636c9a4f4bf6018af97c99d5466a66cbe1abb9 --- /dev/null +++ b/libcpu/risc-v/virt64/cpuport_gcc.S @@ -0,0 +1,22 @@ +/* + * 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" + +.global _rt_thread_entry +_rt_thread_entry: + LOAD ra, (sp) /* texit */ + addi sp, sp, 8 + LOAD a0, (sp) /* parameter */ + addi sp, sp, 8 + LOAD t0, (sp) /* tentry */ + addi sp, sp, 8 + jr t0 diff --git a/libcpu/risc-v/virt64/encoding.h b/libcpu/risc-v/virt64/encoding.h index 44d4cd1aa9929e6765d9f1a9b29ac91aa784203d..2616b8646104b2091e2d3396c398c7992d73598b 100644 --- a/libcpu/risc-v/virt64/encoding.h +++ b/libcpu/risc-v/virt64/encoding.h @@ -23,6 +23,7 @@ #define MSTATUS_HPP 0x00000600 #define MSTATUS_MPP 0x00001800 #define MSTATUS_FS 0x00006000 +#define MSTATUS_VS 0x00000600 #define MSTATUS_XS 0x00018000 #define MSTATUS_MPRV 0x00020000 #define MSTATUS_PUM 0x00040000 @@ -40,8 +41,12 @@ #define SSTATUS_FS_INITIAL 0x00002000 #define SSTATUS_FS_CLEAN 0x00004000 #define SSTATUS_FS_DIRTY 0x00006000 +#define SSTATUS_VS 0x00000600 /* Vector Status */ +#define SSTATUS_VS_INITIAL 0x00000200 +#define SSTATUS_VS_CLEAN 0x00000400 +#define SSTATUS_VS_DIRTY 0x00000600 #define SSTATUS_XS 0x00018000 -#define SSTATUS_PUM 0x00040000 +#define SSTATUS_SUM 0x00040000 #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 diff --git a/libcpu/risc-v/virt64/ext_context.h b/libcpu/risc-v/virt64/ext_context.h new file mode 100644 index 0000000000000000000000000000000000000000..ac757dddb63ddc5612ba3cbbecf357457caf3551 --- /dev/null +++ b/libcpu/risc-v/virt64/ext_context.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-10 RT-Thread the first version, + * compatible to riscv-v-spec-1.0 + */ +#ifndef __EXT_CONTEXT_H__ +#define __EXT_CONTEXT_H__ + +#ifdef __ASSEMBLY__ + +/** + * extension context maintenance + */ + +#include "cpuport.h" +#include "encoding.h" +#include "vector_encoding.h" + +/** + * ================================== + * FPU EXTENSION + * ================================== + */ + +#ifdef ENABLE_FPU +#define FPU_CTX_F0_OFF 0 /* offsetof(fpu_context_t, fpustatus.f[0]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F1_OFF 8 /* offsetof(fpu_context_t, fpustatus.f[1]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F2_OFF 16 /* offsetof(fpu_context_t, fpustatus.f[2]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F3_OFF 24 /* offsetof(fpu_context_t, fpustatus.f[3]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F4_OFF 32 /* offsetof(fpu_context_t, fpustatus.f[4]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F5_OFF 40 /* offsetof(fpu_context_t, fpustatus.f[5]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F6_OFF 48 /* offsetof(fpu_context_t, fpustatus.f[6]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F7_OFF 56 /* offsetof(fpu_context_t, fpustatus.f[7]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F8_OFF 64 /* offsetof(fpu_context_t, fpustatus.f[8]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F9_OFF 72 /* offsetof(fpu_context_t, fpustatus.f[9]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F10_OFF 80 /* offsetof(fpu_context_t, fpustatus.f[10]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F11_OFF 88 /* offsetof(fpu_context_t, fpustatus.f[11]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F12_OFF 96 /* offsetof(fpu_context_t, fpustatus.f[12]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F13_OFF 104 /* offsetof(fpu_context_t, fpustatus.f[13]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F14_OFF 112 /* offsetof(fpu_context_t, fpustatus.f[14]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F15_OFF 120 /* offsetof(fpu_context_t, fpustatus.f[15]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F16_OFF 128 /* offsetof(fpu_context_t, fpustatus.f[16]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F17_OFF 136 /* offsetof(fpu_context_t, fpustatus.f[17]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F18_OFF 144 /* offsetof(fpu_context_t, fpustatus.f[18]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F19_OFF 152 /* offsetof(fpu_context_t, fpustatus.f[19]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F20_OFF 160 /* offsetof(fpu_context_t, fpustatus.f[20]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F21_OFF 168 /* offsetof(fpu_context_t, fpustatus.f[21]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F22_OFF 176 /* offsetof(fpu_context_t, fpustatus.f[22]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F23_OFF 184 /* offsetof(fpu_context_t, fpustatus.f[23]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F24_OFF 192 /* offsetof(fpu_context_t, fpustatus.f[24]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F25_OFF 200 /* offsetof(fpu_context_t, fpustatus.f[25]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F26_OFF 208 /* offsetof(fpu_context_t, fpustatus.f[26]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F27_OFF 216 /* offsetof(fpu_context_t, fpustatus.f[27]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F28_OFF 224 /* offsetof(fpu_context_t, fpustatus.f[28]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F29_OFF 232 /* offsetof(fpu_context_t, fpustatus.f[29]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F30_OFF 240 /* offsetof(fpu_context_t, fpustatus.f[30]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#define FPU_CTX_F31_OFF 248 /* offsetof(fpu_context_t, fpustatus.f[31]) - offsetof(fpu_context_t, fpustatus.f[0]) */ +#endif /* ENABLE_FPU */ + +/** + * ================================== + * VECTOR EXTENSION + * ================================== + */ + +#ifdef ENABLE_VECTOR + +#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) + +.macro GET_VEC_FRAME_LEN, xreg + csrr \xreg, vlenb + slli \xreg, \xreg, 5 + addi \xreg, \xreg, 4 * REGBYTES +.endm + +/** + * @brief save vector extension hardware state + * + * @param dst register storing bottom of storage block + * + */ +.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) + + addi t1, t1, VEC_FRAME_V0 + + // 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) + add t1, t1, t2 + vse8.v v8, (t1) + add t1, t1, t2 + vse8.v v16, (t1) + add t1, t1, t2 + vse8.v v24, (t1) +.endm + +/** + * @brief restore vector extension hardware states + * + * @param dst register storing bottom of storage block + * + */ +.macro RESTORE_VECTOR, dst + // restore vector registers first since it will modify vector states + mv t0, \dst + addi t1, t0, VEC_FRAME_V0 + + VEC_CONFIG_SETVLI(t2, x0, VEC_IMM_SEW_8, VEC_IMM_LMUL_8) + + vle8.v v0, (t1) + add t1, t1, t2 + vle8.v v8, (t1) + add t1, t1, t2 + vle8.v v16, (t1) + add t1, t1, t2 + vle8.v v24, (t1) + + mv t1, t0 + + LOAD t0, VEC_FRAME_VSTART(t1) + csrw vstart, t0 + LOAD t0, VEC_FRAME_VCSR(t1) + csrw vcsr, t0 + + LOAD t0, VEC_FRAME_VTYPE(t1) + LOAD t3, VEC_FRAME_VL(t1) + VEC_CONFIG_SET_VL_VTYPE(t3, t0) +.endm + +#endif /* ENABLE_VECTOR */ + +#endif /* __ASSEMBLY__ */ + +#endif /* __EXT_CONTEXT_H__ */ \ No newline at end of file diff --git a/libcpu/risc-v/virt64/interrupt_gcc.S b/libcpu/risc-v/virt64/interrupt_gcc.S index d2e9bba6e2ad04f952d216eb688215fb47a9fdfd..6cc26731f17f86b25802adc2200ebe8bd62a908f 100644 --- a/libcpu/risc-v/virt64/interrupt_gcc.S +++ b/libcpu/risc-v/virt64/interrupt_gcc.S @@ -9,112 +9,82 @@ * 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 WangXiaoyao Support kernel mode RVV; + * Rewrite trap handling routine */ -#define __ASSEMBLY__ #include "cpuport.h" #include "encoding.h" #include "stackframe.h" - .section .text.entry - .align 2 - .global trap_entry - .extern __stack_cpu0 - .extern get_current_thread_kernel_stack_top + .align 2 + .global trap_entry + .global debug_check_sp trap_entry: - //backup sp - csrrw sp, sscratch, sp - //load interrupt stack - la sp, __stack_cpu0 - //backup context + // 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 - - RESTORE_SYS_GP - - //check syscall - csrr t0, scause - li t1, 8//environment call from u-mode - beq t0, t1, syscall_entry - - csrr a0, scause - csrrc a1, stval, zero - csrr a2, sepc - mv a3, sp - - /* scause, stval, sepc, sp */ - call handle_trap - - /* need to switch new thread */ - la s0, rt_thread_switch_interrupt_flag - lw s2, 0(s0) - beqz s2, spurious_interrupt - sw zero, 0(s0) - -.global rt_hw_context_switch_interrupt_do -rt_hw_context_switch_interrupt_do: - -//swap to thread kernel stack - csrr t0, sstatus - andi t0, t0, 0x100 - beqz t0, __restore_sp_from_tcb_interrupt - -__restore_sp_from_sscratch_interrupt: - csrr t0, sscratch - j __move_stack_context_interrupt + // clear sscratch to say 'now in kernel mode' + csrw sscratch, zero -__restore_sp_from_tcb_interrupt: - la s0, rt_interrupt_from_thread - LOAD a0, 0(s0) - jal rt_thread_sp_to_thread - jal get_thread_kernel_stack_top - mv t0, a0 - -__move_stack_context_interrupt: - mv t1, sp//src - mv sp, t0//switch stack - addi sp, sp, -CTX_REG_NR * REGBYTES - //copy context - li s0, CTX_REG_NR//cnt - mv t2, sp//dst - -copy_context_loop_interrupt: - LOAD t0, 0(t1) - STORE t0, 0(t2) - addi s0, s0, -1 - addi t1, t1, 8 - addi t2, t2, 8 - bnez s0, copy_context_loop_interrupt - - 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) - - #ifdef RT_USING_USERSPACE - mv a0, s1 - jal rt_thread_sp_to_thread - jal lwp_mmu_switch - #endif - -spurious_interrupt: - LOAD t0, 2 * REGBYTES(sp) - andi t0, t0, 0x100 - beqz t0, arch_ret_to_user + RESTORE_SYS_GP + // now we are ready to enter interrupt / excepiton handler +_distinguish_syscall: + csrr t0, scause + // TODO swap 8 with config macro name + li t1, 8 + beq t0, t1, syscall_entry + // syscall never return here + +_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) + jal rt_hw_context_switch + +_resume_execution: + LOAD t0, FRAME_OFF_SSTATUS(sp) + andi t0, t0, SSTATUS_SPP + beqz t0, arch_ret_to_user + +_resume_kernel: RESTORE_ALL + csrw sscratch, zero sret .global rt_hw_interrupt_enable rt_hw_interrupt_enable: - fence.i csrs sstatus, a0 /* restore to old csr */ jr ra .global rt_hw_interrupt_disable rt_hw_interrupt_disable: csrrci a0, sstatus, 2 /* clear SIE */ - fence.i jr ra diff --git a/libcpu/risc-v/virt64/riscv_mmu.c b/libcpu/risc-v/virt64/riscv_mmu.c index e08dfc6735f21e8e6b84c69137c73627deff3e64..e79ca8b37b0ad195e7bdc4f8de83c5fcd9a45c68 100644 --- a/libcpu/risc-v/virt64/riscv_mmu.c +++ b/libcpu/risc-v/virt64/riscv_mmu.c @@ -30,10 +30,10 @@ void mmu_set_pagetable(rt_ubase_t addr) void mmu_enable_user_page_access() { - set_csr(sstatus, SSTATUS_PUM); + set_csr(sstatus, SSTATUS_SUM); } void mmu_disable_user_page_access() { - clear_csr(sstatus, SSTATUS_PUM); + clear_csr(sstatus, SSTATUS_SUM); } diff --git a/libcpu/risc-v/virt64/stack.h b/libcpu/risc-v/virt64/stack.h index bd47570d9871f1eb372b15d39c0f94e67d4084b8..d619d3fd3517ec7d9d5ebf1e4d0dd9f1c15544c8 100644 --- a/libcpu/risc-v/virt64/stack.h +++ b/libcpu/risc-v/virt64/stack.h @@ -50,6 +50,9 @@ struct rt_hw_stack_frame #ifdef ENABLE_FPU rt_ubase_t f[CTX_FPU_REG_NR]; /* f0~f31 */ #endif +#ifdef ENABLE_VECTOR + rt_ubase_t v[CTX_VECTOR_REG_NR]; +#endif }; #endif diff --git a/libcpu/risc-v/virt64/stackframe.h b/libcpu/risc-v/virt64/stackframe.h index 1e191900b4a262e7aefb08611fd7e5ed832fb310..5b546f01f9c1ec80c08c739da3c2bfbe3f6b589c 100644 --- a/libcpu/risc-v/virt64/stackframe.h +++ b/libcpu/risc-v/virt64/stackframe.h @@ -8,6 +8,7 @@ * 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 WangXiaoyao Support kernel mode RVV; */ #ifndef __STACKFRAME_H__ @@ -15,49 +16,12 @@ #include "cpuport.h" #include "encoding.h" +#include "ext_context.h" -#ifdef ENABLE_FPU -#define FPU_CTX_F0_OFF 0 /* offsetof(fpu_context_t, fpustatus.f[0]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F1_OFF 8 /* offsetof(fpu_context_t, fpustatus.f[1]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F2_OFF 16 /* offsetof(fpu_context_t, fpustatus.f[2]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F3_OFF 24 /* offsetof(fpu_context_t, fpustatus.f[3]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F4_OFF 32 /* offsetof(fpu_context_t, fpustatus.f[4]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F5_OFF 40 /* offsetof(fpu_context_t, fpustatus.f[5]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F6_OFF 48 /* offsetof(fpu_context_t, fpustatus.f[6]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F7_OFF 56 /* offsetof(fpu_context_t, fpustatus.f[7]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F8_OFF 64 /* offsetof(fpu_context_t, fpustatus.f[8]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F9_OFF 72 /* offsetof(fpu_context_t, fpustatus.f[9]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F10_OFF 80 /* offsetof(fpu_context_t, fpustatus.f[10]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F11_OFF 88 /* offsetof(fpu_context_t, fpustatus.f[11]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F12_OFF 96 /* offsetof(fpu_context_t, fpustatus.f[12]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F13_OFF 104 /* offsetof(fpu_context_t, fpustatus.f[13]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F14_OFF 112 /* offsetof(fpu_context_t, fpustatus.f[14]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F15_OFF 120 /* offsetof(fpu_context_t, fpustatus.f[15]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F16_OFF 128 /* offsetof(fpu_context_t, fpustatus.f[16]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F17_OFF 136 /* offsetof(fpu_context_t, fpustatus.f[17]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F18_OFF 144 /* offsetof(fpu_context_t, fpustatus.f[18]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F19_OFF 152 /* offsetof(fpu_context_t, fpustatus.f[19]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F20_OFF 160 /* offsetof(fpu_context_t, fpustatus.f[20]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F21_OFF 168 /* offsetof(fpu_context_t, fpustatus.f[21]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F22_OFF 176 /* offsetof(fpu_context_t, fpustatus.f[22]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F23_OFF 184 /* offsetof(fpu_context_t, fpustatus.f[23]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F24_OFF 192 /* offsetof(fpu_context_t, fpustatus.f[24]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F25_OFF 200 /* offsetof(fpu_context_t, fpustatus.f[25]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F26_OFF 208 /* offsetof(fpu_context_t, fpustatus.f[26]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F27_OFF 216 /* offsetof(fpu_context_t, fpustatus.f[27]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F28_OFF 224 /* offsetof(fpu_context_t, fpustatus.f[28]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F29_OFF 232 /* offsetof(fpu_context_t, fpustatus.f[29]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F30_OFF 240 /* offsetof(fpu_context_t, fpustatus.f[30]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#define FPU_CTX_F31_OFF 248 /* offsetof(fpu_context_t, fpustatus.f[31]) - offsetof(fpu_context_t, fpustatus.f[0]) */ -#endif /* ENABLE_FPU */ +#define BYTES(idx) ((idx) * REGBYTES) +#define FRAME_OFF_SSTATUS BYTES(2) -/** - * The register `tp` always save/restore when context switch, - * we call `lwp_user_setting_save` when syscall enter, - * call `lwp_user_setting_restore` when syscall exit - * and modify context stack after `lwp_user_setting_restore` called - * so that the `tp` can be the correct thread area value. - */ +#ifdef __ASSEMBLY__ .macro SAVE_ALL @@ -65,16 +29,20 @@ /* reserve float registers */ addi sp, sp, -CTX_FPU_REG_NR * REGBYTES #endif /* ENABLE_FPU */ +#ifdef ENABLE_VECTOR + /* reserve float registers */ + addi sp, sp, -CTX_VECTOR_REG_NR * REGBYTES +#endif /* ENABLE_VECTOR */ /* save general registers */ addi sp, sp, -CTX_GENERAL_REG_NR * REGBYTES STORE x1, 1 * REGBYTES(sp) csrr x1, sstatus - STORE x1, 2 * REGBYTES(sp) + STORE x1, FRAME_OFF_SSTATUS(sp) csrr x1, sepc - STORE x1, 0 * REGBYTES(sp) + STORE x1, 0 * REGBYTES(sp) STORE x3, 3 * REGBYTES(sp) STORE x4, 4 * REGBYTES(sp) /* save tp */ @@ -157,14 +125,42 @@ #endif /* ENABLE_FPU */ +#ifdef ENABLE_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 /* ENABLE_VECTOR */ .endm +/** + * @brief Restore All General Registers, for interrupt handling + * + */ .macro RESTORE_ALL +#ifdef ENABLE_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 /* ENABLE_VECTOR */ + #ifdef ENABLE_FPU /* restore float register */ - mv t2, sp - addi t2, t2, CTX_GENERAL_REG_NR * REGBYTES /* skip all normal reg */ + addi t2, sp, CTX_GENERAL_REG_NR * REGBYTES li t0, SSTATUS_FS csrs sstatus, t0 @@ -211,9 +207,11 @@ #endif /* ENABLE_FPU */ /* restore general register */ + addi t0, sp, CTX_REG_NR * REGBYTES + csrw sscratch, t0 /* resw ra to sepc */ - LOAD x1, 0 * REGBYTES(sp) + LOAD x1, 0 * REGBYTES(sp) csrw sepc, x1 LOAD x1, 2 * REGBYTES(sp) @@ -270,4 +268,6 @@ csrci sstatus, 2 .endm -#endif +#endif /* __ASSEMBLY__ */ + +#endif /* __STACKFRAME_H__ */ diff --git a/libcpu/risc-v/virt64/startup_gcc.S b/libcpu/risc-v/virt64/startup_gcc.S index cc31cca51f0ad6f64d03ca17c84ca0e668d07f68..700f31181deef9c7235448f06d9eded2883f68b8 100644 --- a/libcpu/risc-v/virt64/startup_gcc.S +++ b/libcpu/risc-v/virt64/startup_gcc.S @@ -11,7 +11,6 @@ */ #define SSTATUS_FS 0x00006000U /* initial state of FPU, clear to disable */ -#define __ASSEMBLY__ #include boot_hartid: .int @@ -87,5 +86,9 @@ _start: la sp, __stack_start__ li t0, __STACKSIZE__ add sp, sp, t0 - csrw sscratch, sp + + /** + * sscratch is always zero on kernel mode + */ + csrw sscratch, zero j primary_cpu_entry diff --git a/libcpu/risc-v/virt64/trap.c b/libcpu/risc-v/virt64/trap.c index dc8398784cc5b55743e4415629c2b34d65b78339..35392559d60c2d5155b0560478c1e0e2cf123b88 100644 --- a/libcpu/risc-v/virt64/trap.c +++ b/libcpu/risc-v/virt64/trap.c @@ -45,7 +45,7 @@ void dump_regs(struct rt_hw_stack_frame *regs) 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_PUM) ? "Permit to Access User Page" : "Not Permit to Access User Page"); + 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_size_t satp_v = read_csr(satp); rt_kprintf("satp = 0x%p\n", satp_v); @@ -172,9 +172,69 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw sys_exit(-1); } +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; +} + +static void handle_nested_trap_panic( + rt_size_t cause, + rt_size_t tval, + rt_size_t epc, + struct rt_hw_stack_frame *eframe) +{ + LOG_E("\n-------- [SEVER ERROR] --------"); + LOG_E("Nested trap detected"); + LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", cause, tval, epc); + dump_regs(eframe); + rt_hw_cpu_shutdown(); +} + +#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 */ + /* Trap entry */ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp) { + ENTER_TRAP; rt_size_t id = __MASKVALUE(scause, __MASK(63UL)); const char *msg; @@ -195,6 +255,8 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw } else { + // trap cannot nested when handling another trap / interrupt + CHECK_NESTED_PANIC(scause, stval, sepc, sp); rt_size_t id = __MASKVALUE(scause, __MASK(63UL)); const char *msg; @@ -213,11 +275,18 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw } else { +#ifdef ENABLE_VECTOR + if (scause == 0x2) + { + if (!(sp->sstatus & SSTATUS_VS) && illegal_inst_recoverable(stval, sp)) + goto _exit; + } +#endif /* ENABLE_VECTOR */ if (!(sp->sstatus & 0x100)) { handle_user(scause, stval, sepc, sp); // if handle_user() return here, jump to u mode then - return; + goto _exit; } // handle kernel exception: @@ -228,7 +297,6 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw dump_regs(sp); rt_kprintf("--------------Thread list--------------\n"); rt_kprintf("current thread: %s\n", rt_thread_self()->name); - list_process(); extern struct rt_thread *rt_current_thread; rt_kprintf("--------------Backtrace--------------\n"); @@ -237,4 +305,7 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw while (1) ; } +_exit: + EXIT_TRAP; + return ; } diff --git a/libcpu/risc-v/virt64/vector_encoding.h b/libcpu/risc-v/virt64/vector_encoding.h new file mode 100644 index 0000000000000000000000000000000000000000..5445843f064f55a201a55caa6555b9c1809c4412 --- /dev/null +++ b/libcpu/risc-v/virt64/vector_encoding.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-10 RT-Thread the first version, + * compatible to riscv-v-spec-1.0 + */ + +#ifndef __VECTOR_ENCODING_H__ +#define __VECTOR_ENCODING_H__ + +/** + * 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 +/* 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 +/* TAIL & MASK agnostic bits */ +#define VEC_IMM_TAIL_AGNOSTIC ta +#define VEC_IMM_MASK_AGNOSTIC ma +#define VEC_IMM_TAMA VEC_IMM_TAIL_AGNOSTIC, VEC_IMM_MASK_AGNOSTIC +#define VEC_IMM_TAMU VEC_IMM_TAIL_AGNOSTIC +#define VEC_IMM_TUMA VEC_IMM_MASK_AGNOSTIC + +/** + * 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 + +#endif /* __VECTOR_ENCODING_H__ */ \ No newline at end of file