diff --git a/.github/workflows/spec_test_on_nuttx.yml b/.github/workflows/spec_test_on_nuttx.yml index 12269b56..be209ec2 100644 --- a/.github/workflows/spec_test_on_nuttx.yml +++ b/.github/workflows/spec_test_on_nuttx.yml @@ -59,11 +59,11 @@ jobs: # target: "riscv32_ilp32d", # use_fpu: true # }, - # { - # config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64", - # target: "riscv64", - # use_fpu: false - # }, + { + config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64", + target: "riscv64", + use_fpu: false + }, ] wamr_test_option: [ @@ -85,6 +85,11 @@ jobs: }, ] + exclude: + # XIP is not fully supported yet on RISCV64, some relocations can not be resolved + - target_config: { config: "boards/risc-v/qemu-rv/rv-virt/configs/nsh64" } + wamr_test_option: { mode: "-t aot -X" } + steps: - name: Install Utilities run: | @@ -160,7 +165,7 @@ jobs: find nuttx/boards -name defconfig | xargs sed -i '$a\${{ matrix.wamr_test_option.option }}' - name: Disable FPU for NuttX - if: matrix.target_config.use_fpu== false + if: matrix.target_config.use_fpu == false run: | find nuttx/boards -name defconfig | xargs sed -i '$a\# CONFIG_ARCH_FPU is not set\n' diff --git a/core/iwasm/aot/arch/aot_reloc_riscv.c b/core/iwasm/aot/arch/aot_reloc_riscv.c index d765e0b8..045cab64 100644 --- a/core/iwasm/aot/arch/aot_reloc_riscv.c +++ b/core/iwasm/aot/arch/aot_reloc_riscv.c @@ -11,6 +11,7 @@ #define R_RISCV_CALL_PLT 19 #define R_RISCV_PCREL_HI20 23 #define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 #define R_RISCV_HI20 26 #define R_RISCV_LO12_I 27 #define R_RISCV_LO12_S 28 @@ -101,20 +102,20 @@ static SymbolMap target_sym_map[] = { REG_SYM(__truncdfsf2), REG_SYM(__unorddf2), REG_SYM(__unordsf2), -#if __riscv_xlen == 32 + REG_SYM(__mulsf3), + REG_SYM(__floatundidf), REG_SYM(__fixdfdi), + REG_SYM(__floatsidf), + REG_SYM(__floatunsidf), +#if __riscv_xlen == 32 REG_SYM(__fixdfsi), REG_SYM(__fixsfdi), REG_SYM(__fixsfsi), REG_SYM(__floatdidf), REG_SYM(__floatdisf), - REG_SYM(__floatsidf), REG_SYM(__floatsisf), - REG_SYM(__floatundidf), REG_SYM(__floatundisf), - REG_SYM(__floatunsidf), REG_SYM(__floatunsisf), - REG_SYM(__mulsf3), REG_SYM(__mulsi3), #endif #endif @@ -269,9 +270,10 @@ typedef struct RelocTypeStrMap { } static RelocTypeStrMap reloc_type_str_maps[] = { - RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_CALL), - RELOC_TYPE_MAP(R_RISCV_CALL_PLT), RELOC_TYPE_MAP(R_RISCV_PCREL_HI20), - RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I), RELOC_TYPE_MAP(R_RISCV_HI20), + RELOC_TYPE_MAP(R_RISCV_32), RELOC_TYPE_MAP(R_RISCV_64), + RELOC_TYPE_MAP(R_RISCV_CALL), RELOC_TYPE_MAP(R_RISCV_CALL_PLT), + RELOC_TYPE_MAP(R_RISCV_PCREL_HI20), RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_I), + RELOC_TYPE_MAP(R_RISCV_PCREL_LO12_S), RELOC_TYPE_MAP(R_RISCV_HI20), RELOC_TYPE_MAP(R_RISCV_LO12_I), RELOC_TYPE_MAP(R_RISCV_LO12_S), }; @@ -327,21 +329,37 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, rv_set_val((uint16 *)addr, val_32); break; } + +#if __riscv_xlen == 64 case R_RISCV_64: { uint64 val_64 = - (uint64)((uintptr_t)symbol_addr + (intptr_t)reloc_addend); + (uint64)((intptr_t)symbol_addr + (intptr_t)reloc_addend); + CHECK_RELOC_OFFSET(sizeof(uint64)); + if (val_64 + != (uint64)((intptr_t)symbol_addr + (intptr_t)reloc_addend)) { + goto fail_addr_out_of_range; + } + bh_memcpy_s(addr, 8, &val_64, 8); +#ifdef __riscv_zifencei + __asm__ volatile("fence.i"); +#else + __asm__ volatile("fence"); +#endif break; } +#endif + case R_RISCV_CALL: case R_RISCV_CALL_PLT: + case R_RISCV_PCREL_HI20: /* S + A - P */ { - val = (int32)(intptr_t)((uint8 *)symbol_addr - addr); + val = (int32)(intptr_t)((uint8 *)symbol_addr + reloc_addend - addr); CHECK_RELOC_OFFSET(sizeof(uint32)); - if (val != (intptr_t)((uint8 *)symbol_addr - addr)) { + if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend - addr)) { if (symbol_index >= 0) { /* Call runtime function by plt code */ symbol_addr = (uint8 *)module->code + module->code_size @@ -351,7 +369,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, } } - if (val != (intptr_t)((uint8 *)symbol_addr - addr)) { + if (val != (intptr_t)((uint8 *)symbol_addr + reloc_addend - addr)) { goto fail_addr_out_of_range; } @@ -372,32 +390,15 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, break; } - case R_RISCV_HI20: /* S + A */ - case R_RISCV_PCREL_HI20: /* S + A - P */ + case R_RISCV_HI20: /* S + A */ { - if (reloc_type == R_RISCV_PCREL_HI20) { - val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend - - (intptr_t)addr); - } - else { - val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend); - } + val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend); CHECK_RELOC_OFFSET(sizeof(uint32)); - if (reloc_type == R_RISCV_PCREL_HI20) { - if (val - != ((intptr_t)symbol_addr + (intptr_t)reloc_addend - - (intptr_t)addr)) { - goto fail_addr_out_of_range; - } - } - else { - if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) { - goto fail_addr_out_of_range; - } + if (val != ((intptr_t)symbol_addr + (intptr_t)reloc_addend)) { + goto fail_addr_out_of_range; } - addr = target_section_addr + reloc_offset; insn = rv_get_val((uint16 *)addr); rv_calc_imm(val, &imm_hi, &imm_lo); insn = (insn & 0x00000fff) | (imm_hi << 12); @@ -405,27 +406,44 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr, break; } - case R_RISCV_LO12_I: /* S + A */ case R_RISCV_PCREL_LO12_I: /* S - P */ + case R_RISCV_PCREL_LO12_S: /* S - P */ { - if (reloc_type == R_RISCV_PCREL_LO12_I) { - /* A = 0 */ - val = (int32)((intptr_t)symbol_addr - (intptr_t)addr); - } - else { - val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend); + /* Already handled in R_RISCV_PCREL_HI20, it should be skipped for + * most cases. But it is still needed for some special cases, e.g. + * ``` + * label: + * auipc t0, %pcrel_hi(symbol) # R_RISCV_PCREL_HI20 (symbol) + * lui t1, 1 + * lw t2, t0, %pcrel_lo(label) # R_RISCV_PCREL_LO12_I (label) + * add t2, t2, t1 + * sw t2, t0, %pcrel_lo(label) # R_RISCV_PCREL_LO12_S (label) + * ``` + * In this case, the R_RISCV_PCREL_LO12_I/S relocation should be + * handled after R_RISCV_PCREL_HI20 relocation. + * + * So, if the R_RISCV_PCREL_LO12_I/S relocation is not followed by + * R_RISCV_PCREL_HI20 relocation, it should be handled here but + * not implemented yet. + */ + + if ((uintptr_t)addr - (uintptr_t)symbol_addr + - (uintptr_t)reloc_addend + != 4) { + goto fail_addr_out_of_range; } + break; + } + + case R_RISCV_LO12_I: /* S + A */ + { + + val = (int32)((intptr_t)symbol_addr + (intptr_t)reloc_addend); CHECK_RELOC_OFFSET(sizeof(uint32)); - if (reloc_type == R_RISCV_PCREL_LO12_I) { - if (val != (intptr_t)symbol_addr - (intptr_t)addr) { - goto fail_addr_out_of_range; - } - } - else { - if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) { - goto fail_addr_out_of_range; - } + + if (val != (intptr_t)symbol_addr + (intptr_t)reloc_addend) { + goto fail_addr_out_of_range; } addr = target_section_addr + reloc_offset; diff --git a/tests/wamr-test-suites/spec-test-script/runtest.py b/tests/wamr-test-suites/spec-test-script/runtest.py index ca7dfcd9..6ca1df0d 100755 --- a/tests/wamr-test-suites/spec-test-script/runtest.py +++ b/tests/wamr-test-suites/spec-test-script/runtest.py @@ -1072,6 +1072,17 @@ def compile_wasm_to_aot(wasm_tempfile, aot_tempfile, runner, opts, r, output = ' # exception isn't thrown in several cases cmd.append("--disable-llvm-lto") + # Bounds checks is disabled by default for 64-bit targets, to + # use the hardware based bounds checks. But it is not supported + # in QEMU with NuttX. + # Enable bounds checks explicitly for all targets if running in QEMU. + if opts.qemu: + cmd.append("--bounds-checks=1") + + # RISCV64 requires -mcmodel=medany, which can be set by --size-level=1 + if test_target.startswith("riscv64"): + cmd.append("--size-level=1") + cmd += ["-o", aot_tempfile, wasm_tempfile] log("Running: %s" % " ".join(cmd))