From 283dc1b2bd6df10a55b4addaefec83a1be91a9cc Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Fri, 28 Nov 2025 17:30:28 +0100 Subject: [PATCH 1/8] Add riscv-wamr-qemu platform --- README.md | 11 + docker/Dockerfile | 34 ++ platform/riscv-wamr-qemu/file2c/file2c.c | 46 +++ platform/riscv-wamr-qemu/main.c | 52 +++ .../riscv-wamr-qemu/scripts/c2wamr-qemu.sh | 185 +++++++++ platform/riscv-wamr-qemu/startup.S | 21 + platform/riscv-wamr-qemu/syscalls.c | 75 ++++ platform/riscv-wamr-qemu/uart.c | 29 ++ platform/riscv-wamr-qemu/uart.h | 7 + platform/riscv-wamr-qemu/virt.ld | 62 +++ .../wamr-platform/baremetal_clock.c | 22 + .../wamr-platform/baremetal_file.c | 384 +++++++++++++++++ .../wamr-platform/baremetal_file.h | 42 ++ .../wamr-platform/baremetal_platform.c | 179 ++++++++ .../wamr-platform/baremetal_socket.c | 386 ++++++++++++++++++ .../wamr-platform/baremetal_socket.h | 23 ++ .../wamr-platform/baremetal_thread.c | 160 ++++++++ .../wamr-platform/baremetal_thread.h | 15 + .../wamr-platform/baremetal_time.c | 64 +++ .../wamr-platform/baremetal_time.h | 16 + .../wamr-platform/platform_init.c | 16 + .../wamr-platform/platform_internal.h | 118 ++++++ .../wamr-platform/shared_platform.cmake | 18 + 23 files changed, 1965 insertions(+) create mode 100644 platform/riscv-wamr-qemu/file2c/file2c.c create mode 100644 platform/riscv-wamr-qemu/main.c create mode 100755 platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh create mode 100644 platform/riscv-wamr-qemu/startup.S create mode 100644 platform/riscv-wamr-qemu/syscalls.c create mode 100644 platform/riscv-wamr-qemu/uart.c create mode 100644 platform/riscv-wamr-qemu/uart.h create mode 100644 platform/riscv-wamr-qemu/virt.ld create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h create mode 100644 platform/riscv-wamr-qemu/wamr-platform/platform_init.c create mode 100644 platform/riscv-wamr-qemu/wamr-platform/platform_internal.h create mode 100644 platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake diff --git a/README.md b/README.md index 7cd368e..c541a5f 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,17 @@ qemu-system-riscv64 -machine virt -bios none \ -kernel build/bin/println.riscv.elf -nographic ``` +#### QEMU RISC-V WAMR +```bash +./platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh \ + examples/build-wasm/tinygo/fibonacci.wasm \ + build/bin/fibonacci.wamr.elf + +# Run in QEMU +qemu-system-riscv64 -machine virt -bios none \ + -kernel build/bin/fibonacci.wamr.elf -nographic +``` + ## Examples All examples below use Go, but the same principles apply to any language that compiles to WASM with WASI support. diff --git a/docker/Dockerfile b/docker/Dockerfile index c607dd0..aec7a0e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -29,6 +29,8 @@ RUN apt-get update && apt-get install -y \ cmake \ libglib2.0-dev \ libslirp-dev \ + libpthread-stubs0-dev \ + wget \ && rm -rf /var/lib/apt/lists/* # Build RISC-V GNU Toolchain @@ -59,6 +61,38 @@ RUN git clone https://git.qemu.org/git/qemu.git && \ cd .. && \ rm -r qemu +# Build WAMR with ZKVM platform +RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git /opt/wamr +COPY platform/riscv-wamr-qemu/wamr-platform/ /opt/wamr/core/shared/platform/zkvm/ +RUN cd /opt/wamr && \ + sed -i "s/find_package(Threads REQUIRED)/find_package(Threads)/g" CMakeLists.txt && \ + cmake . \ + -DWAMR_BUILD_PLATFORM=zkvm \ + -DWAMR_BUILD_TARGET=AOT \ + -DWAMR_BUILD_LIBC_BUILTIN=1 \ + -DWAMR_BUILD_LIB_PTHREAD=0 \ + -DWAMR_BUILD_THREAD_MGR=0 \ + -DWAMR_BUILD_WASI_THREADS=0 \ + -DTHREADS_PREFER_PTHREAD_FLAG=OFF \ + -DCMAKE_THREAD_LIBS_INIT="" \ + -DWAMR_BUILD_FAST_INTERP=1 \ + -DWAMR_BUILD_JIT=0 \ + -DWAMR_BUILD_AOT=1 \ + -DCMAKE_SYSTEM_PROCESSOR=riscv64 \ + -DWAMR_BUILD_TARGET=RISCV64_LP64 \ + -DCMAKE_C_COMPILER=/opt/riscv-newlib/bin/riscv64-unknown-elf-gcc \ + -DCMAKE_CXX_COMPILER=/opt/riscv-newlib/bin/riscv64-unknown-elf-g++ \ + -DCMAKE_ASM_COMPILER=/opt/riscv-newlib/bin/riscv64-unknown-elf-gcc \ + -DWASM_ENABLE_SIMDE=OFF \ + -DWAMR_BUILD_SIMD=0 && \ + make + +# Use pre-compiled wamrc +RUN wget https://github.com/bytecodealliance/wasm-micro-runtime/releases/download/WAMR-2.4.4/wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz && \ + tar xf wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz && \ + mv wamrc /usr/local/bin/ && \ + rm wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz + # Add toolchains to PATH ENV PATH="/opt/riscv-newlib/bin:/opt/w2c2/w2c2:${PATH}" diff --git a/platform/riscv-wamr-qemu/file2c/file2c.c b/platform/riscv-wamr-qemu/file2c/file2c.c new file mode 100644 index 0000000..387b1a2 --- /dev/null +++ b/platform/riscv-wamr-qemu/file2c/file2c.c @@ -0,0 +1,46 @@ +/* originally from https://github.com/IngwiePhoenix/file2c */ + +#include +#include +#include +#include + + +void help(char* me) { + printf("file2c originally by IngwiePhoenix | Convert a file into a C source file.\n"); + printf("Usage: %s inputFile varName > output", me); +} + +int main(int argc, char* argv[]) { + if(argc != 3) { help(argv[0]); exit(1); } + else { + char* fn = argv[1]; + char* varName = argv[2]; + FILE* f = fopen(fn, "rb"); + if(!f) { fprintf(stderr, "Error while opening file."); exit(1); } + + // Get filesize... + int filesize; + struct stat stat_buf; + int rc = stat(fn, &stat_buf); + filesize = stat_buf.st_size; + + printf("const char %s[] = {\n ",varName); + unsigned long n = 0; + while(!feof(f)) { + unsigned char c; + if(fread(&c, 1, 1, f) == 0) break; + ++n; + if((int)n == filesize) { + printf("0x%.2X", (int)c); + } else { + printf("0x%.2X, ", (int)c); + } + if(n % 20 == 0) printf("\n "); + } + fclose(f); + printf("\n};\n"); + printf("int %s_length=%i;\n",varName,filesize); + } + return 0; +} diff --git a/platform/riscv-wamr-qemu/main.c b/platform/riscv-wamr-qemu/main.c new file mode 100644 index 0000000..49e6d01 --- /dev/null +++ b/platform/riscv-wamr-qemu/main.c @@ -0,0 +1,52 @@ +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" +#include + +extern const char wasmModuleBuffer[]; +extern int wasmModuleBuffer_length; + +int main(void) { + int argc = 0; + char *argv[0]; + + char error_buf[128]; + + wasm_module_t module; + wasm_module_inst_t module_inst; + wasm_function_inst_t func; + wasm_exec_env_t exec_env; + uint32 size, stack_size = 8092, heap_size = 8092; + + wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); + + /* initialize the wasm runtime by default configurations */ + if (!wasm_runtime_init()) { + printf("runtime init failed\n"); + exit(1); + } + + /* parse the WASM file from buffer and create a WASM module */ + module = wasm_runtime_load(wasmModuleBuffer, wasmModuleBuffer_length, error_buf, sizeof(error_buf)); + if (module == 0) { + printf("runtime load module failed: %s\n", error_buf); + exit(1); + } + + /* create an instance of the WASM module (WASM linear memory is ready) */ + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, error_buf, sizeof(error_buf)); + if (module_inst == 0) { + printf("wasm_runtime_instantiate failed as module_inst=%p: %s\n", module_inst, error_buf); + exit(1); + } + + if (!wasm_application_execute_main(module_inst, argc, argv)) { + printf("error executing main\n"); + /* TODO: check wasm_runtime_get_exception(..) */ + } + + printf("wasm_runtime_unload...\n"); + wasm_runtime_unload(module); + + return 0; +} diff --git a/platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh b/platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh new file mode 100755 index 0000000..a7b3d7f --- /dev/null +++ b/platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh @@ -0,0 +1,185 @@ +#!/bin/bash +set -e + +#set -x ## TODO : remove debug + +# c2riscv-wamr-qemu - Compile WASM to WAMR RISC-V QEMU binary +# Usage: ./platform/riscv-wamr-qemu/scripts/c2riscv-wamr-qemu.sh + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WAMR_QEMU_DIR="$(dirname "$SCRIPT_DIR")" +DOCKER_DIR="$WAMR_QEMU_DIR/../../docker" +PROJECT_ROOT="$WAMR_QEMU_DIR/../.." +WAMR_ROOT=/opt/wamr + + + +# Check arguments +if [ $# -lt 2 ]; then + echo "Usage: $0 " + echo "" + echo "Compiles a C package (from w2c2) to WAMR-based RISC-V binary for QEMU virt machine." + echo "" + echo "Arguments:" + echo " guest-c-package-dir Directory containing guest.c, guest.h, w2c2_base.h" + echo " output-elf Output RISC-V ELF binary path" + echo "" + echo "Example:" + echo " $0 build/.c-packages/println build/bin/println.riscv.elf" + echo "" + echo "To run in QEMU:" + echo " qemu-system-riscv64 -machine virt -bios none \\" + echo " -kernel build/bin/println.riscv.elf -nographic \\" + echo " -semihosting-config enable=on,target=native" + echo "" + exit 1 +fi + +INPUT_WASM="$1" +OUTPUT="$2" + +# Change to project root +cd "$PROJECT_ROOT" + +# Convert to relative paths if needed +if [[ "$INPUT_WASM" == /* ]]; then + INPUT_WASM=$(realpath --relative-to="$PROJECT_ROOT" "$INPUT_WASM" 2>/dev/null || echo "$INPUT_WASM") +fi +if [[ "$OUTPUT" == /* ]]; then + OUTPUT=$(realpath --relative-to="$PROJECT_ROOT" "$OUTPUT" 2>/dev/null || echo "$OUTPUT") +fi + +# Validate input exists +if [ ! -f "$INPUT_WASM" ]; then + echo "Error: Input file '$INPUT_WASM' not found" + exit 1 +fi + +## Verify guest package exists +#if [ ! -f "$INPUT_WASM/guest.c" ] || [ ! -f "$GU#EST_DIR/guest.h" ]; then +# echo "Error: Guest package not found at $GU#EST_DIR" +# echo "Expected files: guest.c, guest.h, w2c#2_base.h" +# exit 1 +#fi + +# Create output directory +mkdir -p "$(dirname "$OUTPUT")" + +echo "======================================" +echo "C to WAMR RISC-V QEMU Compilation" +echo "======================================" +echo "Guest package: $INPUT_WASM" +echo "Output binary: $OUTPUT" +echo "" + +# Bundle wasm binary within output elf +"$DOCKER_DIR/docker-shell.sh" \ + wamrc --target=riscv64 \ + --target-abi=lp64 \ + --cpu=generic-rv64 \ + --cpu-features='+i,+m,+a' \ + --opt-level=0 \ + --size-level=1 \ + -o $OUTPUT.riscv64.wamr $1 + +gcc platform/riscv-wamr-qemu/file2c/file2c.c \ + -o platform/riscv-wamr-qemu/file2c/file2c + +# The byte buffer can be WASM binary data when +# interpreter or JIT is enabled, or AOT binary +# data when AOT is enabled. +# +# https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/core/iwasm/include/wasm_export.h +platform/riscv-wamr-qemu/file2c/file2c \ + $OUTPUT.riscv64.wamr \ + wasmModuleBuffer > $OUTPUT.riscv64.wamr.c + +# Compile everything in one command via Docker +echo "Compiling..." + +# RISC-V toolchain prefix +PREFIX=/opt/riscv-newlib/bin/riscv64-unknown-elf- + +# Compiler flags (using -O0 for faster compilation of large generated files) +CFLAGS=( + -march=rv64ima + -mabi=lp64 + -mcmodel=medany + -specs=nosys.specs + -D__bool_true_false_are_defined + -ffunction-sections + -fdata-sections + -O0 + -g + -Wall +) + +# Include directories +INCLUDES=( + -I"$WAMR_ROOT/core/iwasm/include" + -I"$WAMR_ROOT/core/shared/utils" + -I"$WAMR_ROOT/core/shared/utils/uncommon" + -I"$WAMR_ROOT/core/shared/platform/zkvm" + -Iwasi/embedded + -Iplatform/riscv-qemu +) + +# Source files +SOURCES=( + platform/riscv-wamr-qemu/main.c + platform/riscv-wamr-qemu/syscalls.c + platform/riscv-wamr-qemu/uart.c + "$OUTPUT.riscv64.wamr.c" +) + +# Assembly source +ASM_SOURCE=platform/riscv-wamr-qemu/startup.S + +# Linker script +LINKER_SCRIPT=platform/riscv-wamr-qemu/virt.ld + +# Linker flags (matching demo-qemu-virt-riscv/Makefile) +LDFLAGS=( + -T"$LINKER_SCRIPT" + -nostartfiles + -static + -L"$WAMR_ROOT" + -liwasm + -Wl,--gc-sections + -Wl,-Map="${OUTPUT%.elf}.map" +) + +# Link libraries +LIBS=(-lc -lm -lgcc) + +"$DOCKER_DIR/docker-shell.sh" ${PREFIX}gcc \ + "${CFLAGS[@]}" \ + "${INCLUDES[@]}" \ + "${SOURCES[@]}" \ + "$ASM_SOURCE" \ + "${LDFLAGS[@]}" \ + "${LIBS[@]}" \ + -o "$OUTPUT" 2>&1 + +# Check if compilation succeeded +if [ $? -eq 0 ] && [ -f "$OUTPUT" ]; then + SIZE=$(du -h "$OUTPUT" | cut -f1) + echo "Compiled successfully" + echo "" + echo "======================================" + echo "Binary created successfully!" + echo "======================================" + echo "" + echo "Location: $OUTPUT" + echo "Size: $SIZE" + echo "" + echo "To run in QEMU:" + echo " qemu-system-riscv64 -machine virt -bios none \\" + echo " -kernel $OUTPUT -nographic \\" + echo " -semihosting-config enable=on,target=native" + echo "" +else + echo "Error: Compilation failed" + exit 1 +fi + diff --git a/platform/riscv-wamr-qemu/startup.S b/platform/riscv-wamr-qemu/startup.S new file mode 100644 index 0000000..84cdef6 --- /dev/null +++ b/platform/riscv-wamr-qemu/startup.S @@ -0,0 +1,21 @@ +.section .text.init +.global _start + +_start: + la sp, _stack_top + + # Clear BSS section - using symbols defined in our linker script + la t0, _bss_start + la t1, _bss_end +clear_bss: + bgeu t0, t1, bss_done + sb zero, 0(t0) + addi t0, t0, 1 + j clear_bss +bss_done: + + # Jump to C code + call main + + # In case main returns +1: j 1b \ No newline at end of file diff --git a/platform/riscv-wamr-qemu/syscalls.c b/platform/riscv-wamr-qemu/syscalls.c new file mode 100644 index 0000000..749e3e5 --- /dev/null +++ b/platform/riscv-wamr-qemu/syscalls.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +#include "uart.h" + +int _write(int file, char *ptr, int len) { + // We're only handling stdout and stderr + if (file != STDOUT_FILENO && file != STDERR_FILENO) { + errno = EBADF; + return -1; + } + + int i; + for (i = 0; i < len; i++) { + uart_putc(ptr[i]); + } + return len; +} + +int _read(int file, char *ptr, int len) { + // We're only handling stdin + if (file != STDIN_FILENO) { + errno = EBADF; + return -1; + } + + int i; + for (i = 0; i < len; i++) { + ptr[i] = uart_getc(); + if (ptr[i] == '\r' || ptr[i] == '\n') { + i++; + break; + } + } + return i; +} + +// Other required syscalls with minimal implementations +int _open(const char *name, int flags, int mode) { errno = ENOSYS; return -1; } +int _close(int file) { return -1; } +int _lseek(int file, int ptr, int dir) { return 0; } +int _fstat(int file, struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} +int _isatty(int file) { + return 1; +} + +void* _sbrk(int incr) { + extern char _end; // Defined by the linker - start of heap + extern char _stack_bottom; // Defined in our linker script - bottom of stack area + + static char *heap_end = &_end; + char *prev_heap_end = heap_end; + + // Calculate safe stack limit - stack grows down from _stack_top towards _stack_bottom + char *stack_limit = &_stack_bottom; + + // Check if heap would grow too close to stack + if (heap_end + incr > stack_limit) { + errno = ENOMEM; + return (void*) -1; // Return error + } + + heap_end += incr; + return (void*) prev_heap_end; +} + +// Required stubs +void _exit(int code) { while (1); } +int _kill(int pid, int sig) { return -1; } +int _getpid(void) { return 1; } diff --git a/platform/riscv-wamr-qemu/uart.c b/platform/riscv-wamr-qemu/uart.c new file mode 100644 index 0000000..6f9db27 --- /dev/null +++ b/platform/riscv-wamr-qemu/uart.c @@ -0,0 +1,29 @@ +#include "uart.h" + +// QEMU UART registers - these addresses are for QEMU's 16550A UART +#define UART_BASE 0x10000000 +#define UART_THR (*(volatile char *)(UART_BASE + 0x00)) // Transmit Holding Register +#define UART_RBR (*(volatile char *)(UART_BASE + 0x00)) // Receive Buffer Register +#define UART_LSR (*(volatile char *)(UART_BASE + 0x05)) // Line Status Register + +#define UART_LSR_TX_IDLE (1 << 5) // Transmitter idle +#define UART_LSR_RX_READY (1 << 0) // Receiver ready + +void uart_putc(char c) { + // Wait until transmitter is idle + while ((UART_LSR & UART_LSR_TX_IDLE) == 0); + UART_THR = c; + + // Special handling for newline (send CR+LF) + if (c == '\n') { + while ((UART_LSR & UART_LSR_TX_IDLE) == 0); + UART_THR = '\r'; + } +} + +char uart_getc(void) { + // Wait for data + while ((UART_LSR & UART_LSR_RX_READY) == 0); + return UART_RBR; +} + diff --git a/platform/riscv-wamr-qemu/uart.h b/platform/riscv-wamr-qemu/uart.h new file mode 100644 index 0000000..580fc3e --- /dev/null +++ b/platform/riscv-wamr-qemu/uart.h @@ -0,0 +1,7 @@ +#ifndef UART_H +#define UART_H + +void uart_putc(char c); +char uart_getc(void); + +#endif diff --git a/platform/riscv-wamr-qemu/virt.ld b/platform/riscv-wamr-qemu/virt.ld new file mode 100644 index 0000000..155df67 --- /dev/null +++ b/platform/riscv-wamr-qemu/virt.ld @@ -0,0 +1,62 @@ +OUTPUT_FORMAT("elf64-littleriscv") +OUTPUT_ARCH("riscv") +ENTRY(_start) + +MEMORY +{ + RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 64M +} + +SECTIONS +{ + /* Code section */ + .text : { + *(.text.init) + *(.text) + } > RAM + + /* Read-only data */ + .rodata : { + *(.rodata) + } > RAM + + /* Initialized data */ + .data : { + *(.data) + } > RAM + + /* Small initialized data */ + .sdata : { + *(.sdata) + } > RAM + + /* BSS section with explicit symbols */ + .bss : { + _bss_start = .; /* Define BSS start symbol */ + *(.bss) + *(COMMON) + . = ALIGN(8); + _bss_end = .; /* Define BSS end symbol */ + } > RAM + + /* Small BSS section */ + .sbss : { + _sbss_start = .; + *(.sbss) + *(.sbss.*) + . = ALIGN(8); + _sbss_end = .; + } > RAM + + /* End marker for heap start */ + . = ALIGN(8); + _end = .; /* Heap starts here and grows upwards */ + + /* Stack grows downward from the end of RAM */ + _stack_size = 64K; + _stack_top = ORIGIN(RAM) + LENGTH(RAM); + _stack_bottom = _stack_top - _stack_size; + + /* Ensure we don't overlap with heap */ + ASSERT(_end <= _stack_bottom, "Error: Heap collides with stack") +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c new file mode 100644 index 0000000..aabcfd3 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" +#include "platform_api_vmcore.h" + +__wasi_errno_t +os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) +{ + printf("os_clock_res_get\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, + __wasi_timestamp_t *time) +{ + printf("os_clock_time_get\n"); + return __WASI_ENOSYS; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c new file mode 100644 index 0000000..9651949 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#include +#include + +int +ocall_get_errno() +{ + return errno; +} + +static inline bool +os_is_virtual_fd(int fd) +{ + switch (fd) { + case STDIN_FILENO: + case STDOUT_FILENO: + case STDERR_FILENO: + return true; + default: + return false; + }; +} + +__wasi_errno_t +os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) +{ + printf("os_fstat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fstatat(os_file_handle handle, const char *path, + struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) +{ + printf("os_fstatat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) +{ + printf("os_file_get_fdflags\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) +{ + printf("os_file_set_fdflags\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fdatasync(os_file_handle handle) +{ + printf("os_fdatasync\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fsync(os_file_handle handle) +{ + printf("os_fsync\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_open_preopendir(const char *path, os_file_handle *out) +{ + printf("os_open_preopendir\n"); + return __WASI_ENOSYS; +} + + +__wasi_errno_t +os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, + __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, + wasi_libc_file_access_mode access_mode, os_file_handle *out) +{ + printf("os_openat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_file_get_access_mode(os_file_handle handle, + wasi_libc_file_access_mode *access_mode) +{ + printf("os_file_get_access_mode\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_close(os_file_handle handle, bool is_stdio) +{ + printf("os_close\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nread) +{ + printf("os_preadv\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + __wasi_filesize_t offset, size_t *nwritten) +{ + printf("os_pwritev\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, + size_t *nread) +{ + printf("os_readv\n"); + return __WASI_ENOSYS; +} + +/* With wasi-libc we need to redirect write on stdout/err to printf */ +// TODO: handle write on stdin +__wasi_errno_t +os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, + size_t *nwritten) +{ + printf("os_writev\n"); + ssize_t total_written = 0; + // Write data from each buffer + for (int i = 0; i < iovcnt; i++) { + printf("%s", iov[i].buf); + total_written += iov[i].buf_len; + } + + *nwritten = total_written; + + return __WASI_ESUCCESS; + +} + +__wasi_errno_t +os_fallocate(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length) +{ + printf("os_fallocate\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_ftruncate(os_file_handle handle, __wasi_filesize_t size) +{ + printf("os_ftruncate\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) +{ + printf("os_futimens\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_utimensat(os_file_handle handle, const char *path, + __wasi_timestamp_t access_time, + __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, + __wasi_lookupflags_t lookup_flags) +{ + printf("os_utimensat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readlinkat(os_file_handle handle, const char *path, char *buf, + size_t bufsize, size_t *nread) +{ + printf("os_readlinkat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_linkat(os_file_handle from_handle, const char *from_path, + os_file_handle to_handle, const char *to_path, + __wasi_lookupflags_t lookup_flags) +{ + printf("os_linkat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) +{ + printf("os_symlinkat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_mkdirat(os_file_handle handle, const char *path) +{ + printf("os_mkdirat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_renameat(os_file_handle old_handle, const char *old_path, + os_file_handle new_handle, const char *new_path) +{ + printf("os_renameat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_unlinkat(os_file_handle handle, const char *path, bool is_dir) +{ + printf("os_unlinkat\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_lseek(os_file_handle handle, __wasi_filedelta_t offset, + __wasi_whence_t whence, __wasi_filesize_t *new_offset) +{ + printf("os_lseek\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_fadvise(os_file_handle handle, __wasi_filesize_t offset, + __wasi_filesize_t length, __wasi_advice_t advice) +{ + printf("os_fadvise\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_isatty(os_file_handle handle) +{ + printf("os_isatty\n"); + return __WASI_ENOTTY; +} + +os_file_handle +os_convert_stdin_handle(os_raw_file_handle raw_stdin) +{ + return 0; +} + +os_file_handle +os_convert_stdout_handle(os_raw_file_handle raw_stdout) +{ + return 1; +} + +os_file_handle +os_convert_stderr_handle(os_raw_file_handle raw_stderr) +{ + return 2; +} + +__wasi_errno_t +os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) +{ + printf("os_fdopendir\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_rewinddir(os_dir_stream dir_stream) +{ + printf("os_rewinddir\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) +{ + printf("os_seekdir\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, + const char **d_name) +{ + printf("os_readdir\n"); + return __WASI_ENOSYS; +} + +__wasi_errno_t +os_closedir(os_dir_stream dir_stream) +{ + printf("os_closedir\n"); + return __WASI_ENOSYS; +} + +os_dir_stream +os_get_invalid_dir_stream() +{ + return NULL; +} + +bool +os_is_dir_stream_valid(os_dir_stream *dir_stream) +{ + return false; +} + +bool +os_is_handle_valid(os_file_handle *handle) +{ + if (handle == NULL) + return false; + return *handle >= 0; +} + +char * +os_realpath(const char *path, char *resolved_path) +{ + return NULL; +} + +bool +os_compare_file_handle(os_file_handle handle1, os_file_handle handle2) +{ + return handle1 == handle2; +} + +bool +os_is_stdin_handle(os_file_handle handle) +{ + return handle == 0; +} + +bool +os_is_stdout_handle(os_file_handle handle) +{ + return handle == 1; +} + +bool +os_is_stderr_handle(os_file_handle handle) +{ + return handle == 2; +} + +int +os_ioctl(os_file_handle handle, int request, ...) +{ + return __WASI_ENOSYS; +} + +int +os_poll(os_poll_file_handle *fds, os_nfds_t nfs, int timeout) +{ + return BHT_ERROR; +} + +int +sched_yield(void) +{ + return BHT_ERROR; +} + +int +get_errno(void) +{ + int ret; + + if (ocall_get_errno(&ret) != 0) { + return -1; + } + return ret; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h new file mode 100644 index 0000000..fd121e2 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BAREMETAL_FILE_H +#define _BAREMETAL_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define POLLIN 0x001 +#define POLLPRI 0x002 +#define POLLOUT 0x004 +#define POLLERR 0x008 +#define POLLHUP 0x010 +#define POLLNVAL 0x020 +#define POLLRDNORM 0x040 +#define POLLRDBAND 0x080 +#define POLLWRNORM 0x100 +#define POLLWRBAND 0x200 + +#define FIONREAD 0x541B + +struct pollfd { + int fd; + short events; + short revents; +}; + +int +sched_yield(void); + +int +get_errno(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BAREMETAL_FILE_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c new file mode 100644 index 0000000..790d136 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-FileCopyrightText: 2024 Siemens AG (For Zephyr usermode changes) + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#define OUTPUT_ADDR 0xa0010000 + +void writeuartc(const char c) { + char *ptr_val = (char *)(0xa0000000+512); + *ptr_val = c; +} + +int outputCount = 0; + +// https://github.com/eth-act/skunkworks-tama/blob/main/tamaboards/zkvm/board.go +void printk(uint32_t val) { + // TODO: This is a stub. Just write to the output address + // Write directly to OUTPUT_ADDR + // Format: [count:u32][data:bytes] + // First update the count at OUTPUT_ADDR + outputCount+=1; + uint32_t *ptr_count = (uint32_t *)OUTPUT_ADDR; + *ptr_count = outputCount; + + // Write the byte at OUTPUT_ADDR + 4 + (outputCount-1) + uint32_t *ptr_val = (uint32_t *)(OUTPUT_ADDR+4+4*(outputCount-1)); + *ptr_val = val; +} + +static int +_stdout_hook_iwasm(int c) +{ + printk((int32_t) c); + return 1; +} + +int +os_thread_sys_init(); + +void +os_thread_sys_destroy(); + +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + +int +os_dumps_proc_mem_info(char *out, unsigned int size) +{ + return -1; +} + +#if 0 +struct out_context { + int count; +}; + +typedef int (*out_func_t)(int c, void *ctx); + +static int +char_out(int c, void *ctx) +{ + struct out_context *out_ctx = (struct out_context*)ctx; + out_ctx->count++; + return _stdout_hook_iwasm(c); +} + +int +os_vprintf(const char *fmt, va_list ap) +{ +#if 0 + struct out_context ctx = { 0 }; + cbvprintf(char_out, &ctx, fmt, ap); + return ctx.count; +#else + vprintk(fmt, ap); + return 0; +#endif +} +#endif + +int +os_printf(const char *format, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, format); +#ifndef BH_VPRINTF + ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif + va_end(ap); + + return ret; +} + +int +os_vprintf(const char *format, va_list ap) +{ +#ifndef BH_VPRINTF + return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif +} + +void * +os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) +{ + void *addr; + + if ((uint64)size >= UINT32_MAX) + return NULL; + + addr = BH_MALLOC(size); + + if (addr) + memset(addr, 0, size); + return addr; +} + +int +os_getpagesize(void) +{ + return 4096; +} + + +void * +os_mremap(void *old_addr, size_t old_size, size_t new_size) +{ + return os_mremap_slow(old_addr, old_size, new_size); +} + +void +os_munmap(void *addr, size_t size) +{ + BH_FREE(addr); +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + return 0; +} + +void +os_dcache_flush() +{} + +void +os_icache_flush(void *start, size_t len) +{} + +os_raw_file_handle +os_invalid_raw_handle(void) +{ + return -1; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c new file mode 100644 index 0000000..343426f --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c @@ -0,0 +1,386 @@ +/* + * Copyright 2024 Sony Semiconductor Solutions Corporation. + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +int +os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, + unsigned int *addrlen) +{ + return BHT_ERROR; +} + +int +os_socket_connect(bh_socket_t socket, const char *addr, int port) +{ + return BHT_ERROR; +} + +int +os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr) +{ + return BHT_ERROR; +} + +int +os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, + int flags, const bh_sockaddr_t *dest_addr) +{ + return BHT_ERROR; +} + +int +os_socket_addr_resolve(const char *host, const char *service, + uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, size_t addr_info_size, + size_t *max_info_size) +{ + return BHT_ERROR; +} + +int +os_socket_close(bh_socket_t socket) +{ + return BHT_ERROR; +} + +int +os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) +{ + return BHT_ERROR; +} + +int +os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) +{ + return BHT_ERROR; +} + +int +os_socket_bind(bh_socket_t socket, const char *host, int *port) +{ + return BHT_ERROR; +} + +int +os_socket_listen(bh_socket_t socket, int max_client) +{ + return BHT_ERROR; +} + +int +os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) +{ + return BHT_ERROR; +} + +int +os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) +{ + return BHT_ERROR; +} + +__wasi_errno_t +os_socket_shutdown(bh_socket_t socket) +{ + printf("os_socket_shutdown\n"); + return __WASI_ENOSYS; +} + +int +os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) +{ + return BHT_ERROR; +} + +int +os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) +{ + return BHT_ERROR; +} + +int +os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) +{ + return BHT_ERROR; +} + +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) +{ + return BHT_ERROR; +} + +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + return BHT_ERROR; +} + +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) +{ + return BHT_ERROR; +} + +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + return BHT_ERROR; +} + +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) +{ + return BHT_ERROR; +} + +int +os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) +{ + return BHT_ERROR; +} + +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) +{ + return BHT_ERROR; +} + +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) +{ + return BHT_ERROR; +} + +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) +{ + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) +{ + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) +{ + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) +{ + return BHT_ERROR; +} + +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + return BHT_ERROR; +} + +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + return BHT_ERROR; +} + +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + return BHT_ERROR; +} + +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + return BHT_ERROR; +} + +int +os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled) +{ + return BHT_ERROR; +} + +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled) +{ + return BHT_ERROR; +} + +static void +swap16(uint8 *pData) +{ + uint8 value = *pData; + *(pData) = *(pData + 1); + *(pData + 1) = value; +} + +static void +swap32(uint8 *pData) +{ + uint8 value = *pData; + *pData = *(pData + 3); + *(pData + 3) = value; + + value = *(pData + 1); + *(pData + 1) = *(pData + 2); + *(pData + 2) = value; +} + +/** In-enclave implementation of POSIX functions **/ +static bool +is_little_endian() +{ + long i = 0x01020304; + unsigned char *c = (unsigned char *)&i; + return (*c == 0x04) ? true : false; +} + +uint16 +htons(uint16 value) +{ + uint16 ret; + if (is_little_endian()) { + ret = value; + swap16((uint8 *)&ret); + return ret; + } + + return value; +} + +uint32 +htonl(uint32 value) +{ + uint32 ret; + if (is_little_endian()) { + ret = value; + swap32((uint8 *)&ret); + return ret; + } + + return value; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h new file mode 100644 index 0000000..64586d4 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _BAREMETAL_SOCKET_H +#define _BAREMETAL_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t +htonl(uint32_t value); + +uint16_t +htons(uint16_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BAREMETAL_SOCKET_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c new file mode 100644 index 0000000..6d22141 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + + +korp_tid +os_self_thread() +{ + return 0; +} + +int +os_mutex_init(korp_mutex *mutex) +{ + return BHT_OK; +} + +int +os_mutex_destroy(korp_mutex *mutex) +{ + return BHT_OK; +} + +int +os_mutex_lock(korp_mutex *mutex) +{ + return 0; +} + +int +os_mutex_unlock(korp_mutex *mutex) +{ + return 0; +} + +int +os_cond_init(korp_cond *cond) +{ + return BHT_OK; +} + +int +os_cond_destroy(korp_cond *cond) +{ + return BHT_OK; +} + +int +os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + return BHT_OK; +} + +int +os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds) +{ + os_printf("warning: baremetal pthread_cond_timedwait isn't supported, " + "calling pthread_cond_wait instead!\n"); + return BHT_ERROR; +} + +int +os_cond_signal(korp_cond *cond) +{ + return BHT_OK; +} + +int +os_cond_broadcast(korp_cond *cond) +{ + return BHT_OK; +} + +int +os_thread_join(korp_tid thread, void **value_ptr) +{ + return 0; +} + +int +os_thread_detach(korp_tid thread) +{ + /* baremetal pthread_detach isn't provided, return directly. */ + return 0; +} + +void +os_thread_exit(void *retval) +{ + return; +} + +uint8 * +os_thread_get_stack_boundary() +{ + /* TODO: get baremetal stack boundary */ + return NULL; +} + +void +os_thread_jit_write_protect_np(bool enabled) +{} + +int +os_rwlock_init(korp_rwlock *lock) +{ + return BHT_OK; +} + +int +os_rwlock_rdlock(korp_rwlock *lock) +{ + return BHT_OK; +} + +int +os_rwlock_wrlock(korp_rwlock *lock) +{ + return BHT_OK; +} + +int +os_rwlock_unlock(korp_rwlock *lock) +{ + return BHT_OK; +} + +int +os_rwlock_destroy(korp_rwlock *lock) +{ + return BHT_OK; +} + +int +os_thread_signal_init(os_signal_handler handler) +{ + return 0; +} + +bool +os_thread_signal_inited() +{ + return false; +} + +void +os_thread_signal_destroy() +{} + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { + if (once_control != 0) { + // TODO + init_routine(); + } + return 0; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h new file mode 100644 index 0000000..7f63e0d --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h @@ -0,0 +1,15 @@ +#ifndef _BAREMETAL_THREAD_H +#define _BAREMETAL_THREAD_H + +int pthread_condattr_init(pthread_condattr_t *attr); +int pthread_condattr_destroy(pthread_condattr_t *attr); + +int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); + +int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id); + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); + +#define PTHREAD_ONCE_INIT {} + +#endif /* end of _BAREMETAL_THREAD_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c new file mode 100644 index 0000000..d5c1983 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +#define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__) +#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__) + +int +ocall_clock_gettime(int *p_ret, unsigned clock_id, void *tp_buf, + unsigned int tp_buf_size); +int +ocall_clock_getres(int *p_ret, int clock_id, void *res_buf, + unsigned int res_buf_size); +int +ocall_utimensat(int *p_ret, int dirfd, const char *pathname, + const void *times_buf, unsigned int times_buf_size, int flags); +int +ocall_futimens(int *p_ret, int fd, const void *times_buf, + unsigned int times_buf_size); + +int +ocall_clock_nanosleep(unsigned clock_id, int flags, const void *req_buf, + unsigned int req_buf_size, const void *rem_buf, + unsigned int rem_buf_size) +{ + return clock_nanosleep((clockid_t)clock_id, flags, + (struct timespec *)req_buf, + (struct timespec *)rem_buf); +} + +uint64 +os_time_get_boot_us() +{ + return 0; +} + +uint64 +os_time_thread_cputime_us(void) +{ + return 0; +} + +int +clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, + struct timespec *remain) +{ + int ret; + + if (ocall_clock_nanosleep(clock_id, flags, (void *)request, + sizeof(struct timespec), (void *)remain, + sizeof(struct timespec)) + != 0) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) + errno = get_errno(); + + return ret; +} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h new file mode 100644 index 0000000..ad151e2 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h @@ -0,0 +1,16 @@ +#ifndef _BAREMETAL_TIME_H +#define _BAREMETAL_TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +int +clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, + struct timespec *remain); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _BAREMETAL_TIME_H */ \ No newline at end of file diff --git a/platform/riscv-wamr-qemu/wamr-platform/platform_init.c b/platform/riscv-wamr-qemu/wamr-platform/platform_init.c new file mode 100644 index 0000000..0ab0592 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/platform_init.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{} diff --git a/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h b/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h new file mode 100644 index 0000000..3aa242f --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * Copyright (C) 2023 Dylibso. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#define DIR int + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "baremetal_file.h" +#include "baremetal_socket.h" +#include "baremetal_time.h" +#include "baremetal_thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_ZKVM +#define BH_PLATFORM_ZKVM +#endif + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef pthread_t korp_tid; +typedef pthread_mutex_t korp_mutex; +typedef pthread_cond_t korp_cond; +typedef pthread_t korp_thread; +typedef int korp_rwlock; +typedef int korp_sem; + +#define bh_socket_t int + +typedef int os_file_handle; +typedef DIR *os_dir_stream; +typedef int os_raw_file_handle; +typedef struct pollfd os_poll_file_handle; +typedef int os_nfds_t; +typedef struct timespec os_timespec; + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC 4 +#endif + +static inline os_file_handle +os_get_invalid_handle(void) +{ + return -1; +} + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ + || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ + || defined(BUILD_TARGET_RISCV64_LP64) + +#include + +typedef jmp_buf korp_jmpbuf; + +#define os_setjmp setjmp +#define os_longjmp longjmp +#define os_alloca alloca + +typedef void (*os_signal_handler)(void *sig_addr); + +int +os_thread_signal_init(os_signal_handler handler); + +void +os_thread_signal_destroy(); + +bool +os_thread_signal_inited(); + +void +os_signal_unmask(); + +void +os_sigreturn(); +#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ +#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ + +int +os_getpagesize(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake b/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake new file mode 100644 index 0000000..b7dd707 --- /dev/null +++ b/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake @@ -0,0 +1,18 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# Copyright (C) 2023 Dylibso. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_ZKVM) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake) +set (source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) + +set (PLATFORM_SHARED_SOURCE ${source_all}) + From 85589734200255e63ac9b8d2b28d1c18e0ebed1f Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Tue, 2 Dec 2025 15:40:17 +0100 Subject: [PATCH 2/8] improve wamr setup such that fibonacci calculation possible --- README.md | 6 +- .../{c2wamr-qemu.sh => wasm2wamr-qemu.sh} | 4 +- platform/riscv-wamr-qemu/syscalls.c | 8 +- platform/riscv-wamr-qemu/virt.ld | 107 ++++++++++-------- .../wamr-platform/baremetal_clock.c | 11 +- 5 files changed, 78 insertions(+), 58 deletions(-) rename platform/riscv-wamr-qemu/scripts/{c2wamr-qemu.sh => wasm2wamr-qemu.sh} (97%) diff --git a/README.md b/README.md index c541a5f..65e12a1 100644 --- a/README.md +++ b/README.md @@ -97,12 +97,12 @@ qemu-system-riscv64 -machine virt -bios none \ #### QEMU RISC-V WAMR ```bash -./platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh \ - examples/build-wasm/tinygo/fibonacci.wasm \ +./platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh \ + examples/build-wasm/go/fibonacci.wasm \ build/bin/fibonacci.wamr.elf # Run in QEMU -qemu-system-riscv64 -machine virt -bios none \ +qemu-system-riscv64 -machine virt -m 1024M -bios none \ -kernel build/bin/fibonacci.wamr.elf -nographic ``` diff --git a/platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh similarity index 97% rename from platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh rename to platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh index a7b3d7f..9e1c98a 100755 --- a/platform/riscv-wamr-qemu/scripts/c2wamr-qemu.sh +++ b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh @@ -174,8 +174,8 @@ if [ $? -eq 0 ] && [ -f "$OUTPUT" ]; then echo "Size: $SIZE" echo "" echo "To run in QEMU:" - echo " qemu-system-riscv64 -machine virt -bios none \\" - echo " -kernel $OUTPUT -nographic \\" + echo " qemu-system-riscv64 -machine virt -m 1024M \\" + echo " -bios none -kernel $OUTPUT -nographic \\" echo " -semihosting-config enable=on,target=native" echo "" else diff --git a/platform/riscv-wamr-qemu/syscalls.c b/platform/riscv-wamr-qemu/syscalls.c index 749e3e5..2df15ee 100644 --- a/platform/riscv-wamr-qemu/syscalls.c +++ b/platform/riscv-wamr-qemu/syscalls.c @@ -50,14 +50,14 @@ int _isatty(int file) { } void* _sbrk(int incr) { - extern char _end; // Defined by the linker - start of heap - extern char _stack_bottom; // Defined in our linker script - bottom of stack area + extern char _heap_start; // Defined by the linker - start of heap + extern char _stack_top; // Defined in our linker script - top of stack area - static char *heap_end = &_end; + static char *heap_end = &_heap_start; char *prev_heap_end = heap_end; // Calculate safe stack limit - stack grows down from _stack_top towards _stack_bottom - char *stack_limit = &_stack_bottom; + char *stack_limit = &_stack_top; // Check if heap would grow too close to stack if (heap_end + incr > stack_limit) { diff --git a/platform/riscv-wamr-qemu/virt.ld b/platform/riscv-wamr-qemu/virt.ld index 155df67..eebfbc6 100644 --- a/platform/riscv-wamr-qemu/virt.ld +++ b/platform/riscv-wamr-qemu/virt.ld @@ -1,62 +1,73 @@ +/* Linker script for QEMU RISC-V virt machine */ + OUTPUT_FORMAT("elf64-littleriscv") OUTPUT_ARCH("riscv") ENTRY(_start) -MEMORY -{ - RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 64M +/* QEMU virt machine memory map */ +MEMORY { + ram (wxa) : ORIGIN = 0x80000000, LENGTH = 1024M } SECTIONS { - /* Code section */ - .text : { - *(.text.init) - *(.text) - } > RAM - - /* Read-only data */ - .rodata : { - *(.rodata) - } > RAM - - /* Initialized data */ - .data : { - *(.data) - } > RAM - - /* Small initialized data */ - .sdata : { - *(.sdata) - } > RAM - - /* BSS section with explicit symbols */ - .bss : { - _bss_start = .; /* Define BSS start symbol */ - *(.bss) - *(COMMON) + /* Start of RAM */ + . = 0x80000000; + + /* Code section */ + .text : { + KEEP(*(.text.init)) /* Keep startup code first */ + *(.text .text.*) + *(.gnu.linkonce.t.*) + } >ram + + /* Align to 8 bytes */ + . = ALIGN(8); + + /* Global pointer for efficient access to small data */ + PROVIDE(__global_pointer$ = . + 0x800); + + /* Read-only data */ + .rodata : { + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } >ram + + /* Align to 8 bytes */ . = ALIGN(8); - _bss_end = .; /* Define BSS end symbol */ - } > RAM - - /* Small BSS section */ - .sbss : { - _sbss_start = .; - *(.sbss) - *(.sbss.*) + + /* Initialized data */ + .data : { + *(.data .data.*) + *(.sdata .sdata.*) + *(.gnu.linkonce.d.*) + } >ram + + /* Align to 8 bytes */ . = ALIGN(8); - _sbss_end = .; - } > RAM - /* End marker for heap start */ - . = ALIGN(8); - _end = .; /* Heap starts here and grows upwards */ + /* Uninitialized data (BSS) */ + .bss : { + PROVIDE(_bss_start = .); + *(.bss .bss.*) + *(.sbss .sbss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + PROVIDE(_bss_end = .); + } >ram + + /* Align to page boundary */ + . = ALIGN(0x1000); + + /* Heap for malloc */ + PROVIDE(_heap_start = .); + . = . + 512M; /* 512MB heap */ + PROVIDE(_heap_end = .); - /* Stack grows downward from the end of RAM */ - _stack_size = 64K; - _stack_top = ORIGIN(RAM) + LENGTH(RAM); - _stack_bottom = _stack_top - _stack_size; + /* Stack grows downward from top of RAM */ + . = . + 128M; /* 128MB stack */ + PROVIDE(_stack_top = .); - /* Ensure we don't overlap with heap */ - ASSERT(_end <= _stack_bottom, "Error: Heap collides with stack") + /* End marker */ + PROVIDE(_end = .); } diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c index aabcfd3..af33eb8 100644 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c @@ -6,6 +6,9 @@ #include "platform_api_extension.h" #include "platform_api_vmcore.h" +// Jan 1st 2025 in nanoseconds +#define OS_CLOCK_TIME_START 1735686000e9 + __wasi_errno_t os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) { @@ -13,10 +16,16 @@ os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) return __WASI_ENOSYS; } +uint64 os_clock_current_time = 0; + __wasi_errno_t os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, __wasi_timestamp_t *time) { printf("os_clock_time_get\n"); - return __WASI_ENOSYS; + + *time = OS_CLOCK_TIME_START + os_clock_current_time; + os_clock_current_time += 100; + + return __WASI_ESUCCESS; } From 2d78f49b989c4b92564c733a410497995449ac1c Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Tue, 2 Dec 2025 16:55:24 +0100 Subject: [PATCH 3/8] Fix os_writev --- .../riscv-wamr-qemu/wamr-platform/baremetal_file.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c index 9651949..dadcea4 100644 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c +++ b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c @@ -48,7 +48,8 @@ __wasi_errno_t os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) { printf("os_file_get_fdflags\n"); - return __WASI_ENOSYS; + *flags = 0; + return __WASI_ESUCCESS; } __wasi_errno_t @@ -134,11 +135,14 @@ __wasi_errno_t os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, size_t *nwritten) { - printf("os_writev\n"); ssize_t total_written = 0; + // Write data from each buffer for (int i = 0; i < iovcnt; i++) { - printf("%s", iov[i].buf); + const char *buf = (const char *)iov[i].buf; + for (int j = 0; j < iov[i].buf_len; j++) { + putchar(buf[j]); + } total_written += iov[i].buf_len; } From f0e4ab72dc91755e16855b2e55f3f21e36292108 Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Wed, 3 Dec 2025 16:58:27 +0100 Subject: [PATCH 4/8] Fix running Go on WAMR platform --- platform/riscv-wamr-qemu/main.c | 6 +++--- platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/platform/riscv-wamr-qemu/main.c b/platform/riscv-wamr-qemu/main.c index 49e6d01..e0fbabe 100644 --- a/platform/riscv-wamr-qemu/main.c +++ b/platform/riscv-wamr-qemu/main.c @@ -16,7 +16,7 @@ int main(void) { wasm_module_inst_t module_inst; wasm_function_inst_t func; wasm_exec_env_t exec_env; - uint32 size, stack_size = 8092, heap_size = 8092; + uint32 size, stack_size = 16*1024*1024; wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); @@ -34,7 +34,7 @@ int main(void) { } /* create an instance of the WASM module (WASM linear memory is ready) */ - module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, error_buf, sizeof(error_buf)); + module_inst = wasm_runtime_instantiate(module, stack_size, 0, error_buf, sizeof(error_buf)); if (module_inst == 0) { printf("wasm_runtime_instantiate failed as module_inst=%p: %s\n", module_inst, error_buf); exit(1); @@ -42,7 +42,7 @@ int main(void) { if (!wasm_application_execute_main(module_inst, argc, argv)) { printf("error executing main\n"); - /* TODO: check wasm_runtime_get_exception(..) */ + printf("exception: %s\n", wasm_runtime_get_exception(module_inst)); } printf("wasm_runtime_unload...\n"); diff --git a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh index 9e1c98a..da746c1 100755 --- a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh +++ b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh @@ -66,13 +66,23 @@ fi mkdir -p "$(dirname "$OUTPUT")" echo "======================================" -echo "C to WAMR RISC-V QEMU Compilation" +echo "WASM to WAMR RISC-V QEMU Compilation" echo "======================================" echo "Guest package: $INPUT_WASM" echo "Output binary: $OUTPUT" echo "" # Bundle wasm binary within output elf +# +# Without --bounds-checks=1 an error +# +# runtime: morestack on g0 +# +# is shown. Enabling it seems to trigger a calculation of +# the stack boundary +# +# https://github.com/bytecodealliance/wasm-micro-runtime/issues/3966 +# https://github.com/bytecodealliance/wasm-micro-runtime/pull/3967 "$DOCKER_DIR/docker-shell.sh" \ wamrc --target=riscv64 \ --target-abi=lp64 \ @@ -80,6 +90,7 @@ echo "" --cpu-features='+i,+m,+a' \ --opt-level=0 \ --size-level=1 \ + --bounds-checks=1 \ -o $OUTPUT.riscv64.wamr $1 gcc platform/riscv-wamr-qemu/file2c/file2c.c \ From d93f97babe7dded345b7f388acb8d4cdd0f3ad36 Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Fri, 12 Dec 2025 12:22:26 +0100 Subject: [PATCH 5/8] Register missing soft float related symbols --- docker/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/Dockerfile b/docker/Dockerfile index aec7a0e..07d3d6a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -66,6 +66,9 @@ RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git /opt/wa COPY platform/riscv-wamr-qemu/wamr-platform/ /opt/wamr/core/shared/platform/zkvm/ RUN cd /opt/wamr && \ sed -i "s/find_package(Threads REQUIRED)/find_package(Threads)/g" CMakeLists.txt && \ + sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatundisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ + sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatdisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ + sed -i "/SymbolMap target_sym_map/a REG_SYM(__ltsf2)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ cmake . \ -DWAMR_BUILD_PLATFORM=zkvm \ -DWAMR_BUILD_TARGET=AOT \ From ae199e58ef46f9c646a60e5e96108eb0da8cf113 Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Sat, 13 Dec 2025 17:03:37 +0100 Subject: [PATCH 6/8] Fix slow compile times with WAMR * Compile wamrc from source * Use LLVM 19 in wamrc --- docker/Dockerfile | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 07d3d6a..13d4a95 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,6 +10,7 @@ RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ python3-tomli \ + python3.10-venv \ libmpc-dev \ libmpfr-dev \ libgmp-dev \ @@ -30,7 +31,10 @@ RUN apt-get update && apt-get install -y \ libglib2.0-dev \ libslirp-dev \ libpthread-stubs0-dev \ - wget \ + g++-multilib \ + libgcc-9-dev \ + lib32gcc-9-dev \ + ccache \ && rm -rf /var/lib/apt/lists/* # Build RISC-V GNU Toolchain @@ -62,6 +66,20 @@ RUN git clone https://git.qemu.org/git/qemu.git && \ rm -r qemu # Build WAMR with ZKVM platform +# +# Some symbols such as __floatundisf, __floatdisf, __ltsf2 need to be +# explicitly registered for working soft float support on the target +# platform +# +# https://github.com/bytecodealliance/wasm-micro-runtime/issues/418 +# https://github.com/bytecodealliance/wasm-micro-runtime/issues/531 +# +# Additionally use LLVM 19. Profiling wamrc when compiling a large wasm +# file like stateful.wasm shows that AttemptToFoldSymbolOffsetDifference +# consumes most of the compile time. LLVM 19 contains a fix for this +# though +# +# https://github.com/llvm/llvm-project/issues/81440 RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git /opt/wamr COPY platform/riscv-wamr-qemu/wamr-platform/ /opt/wamr/core/shared/platform/zkvm/ RUN cd /opt/wamr && \ @@ -69,6 +87,7 @@ RUN cd /opt/wamr && \ sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatundisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatdisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ sed -i "/SymbolMap target_sym_map/a REG_SYM(__ltsf2)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ + sed -i "s/18\.x/19.x/g" build-scripts/build_llvm.py && \ cmake . \ -DWAMR_BUILD_PLATFORM=zkvm \ -DWAMR_BUILD_TARGET=AOT \ @@ -88,16 +107,14 @@ RUN cd /opt/wamr && \ -DCMAKE_ASM_COMPILER=/opt/riscv-newlib/bin/riscv64-unknown-elf-gcc \ -DWASM_ENABLE_SIMDE=OFF \ -DWAMR_BUILD_SIMD=0 && \ + make && \ + cd /opt/wamr/wamr-compiler && \ + ./build_llvm.sh && \ + cmake . && \ make -# Use pre-compiled wamrc -RUN wget https://github.com/bytecodealliance/wasm-micro-runtime/releases/download/WAMR-2.4.4/wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz && \ - tar xf wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz && \ - mv wamrc /usr/local/bin/ && \ - rm wamrc-2.4.4-x86_64-ubuntu-22.04.tar.gz - # Add toolchains to PATH -ENV PATH="/opt/riscv-newlib/bin:/opt/w2c2/w2c2:${PATH}" +ENV PATH="/opt/riscv-newlib/bin:/opt/w2c2/w2c2:/opt/wamr/wamr-compiler:${PATH}" RUN apt update && apt install -y gcc-riscv64-linux-gnu From 744076210a785ffd00f17538dffea655786c9527 Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Thu, 18 Dec 2025 11:34:39 +0100 Subject: [PATCH 7/8] Improved benchmarking for WAMR, LLVM 20 --- README.md | 9 +- docker/Dockerfile | 27 +- platform/riscv-qemu/scripts/c2riscv-qemu.sh | 2 +- platform/riscv-wamr-qemu/main.c | 22 + .../riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh | 10 +- platform/riscv-wamr-qemu/startup.S | 14 +- platform/riscv-wamr-qemu/syscalls.c | 2 +- platform/riscv-wamr-qemu/virt.ld | 4 +- .../wamr-platform/baremetal_clock.c | 31 -- .../wamr-platform/baremetal_file.c | 388 ------------------ .../wamr-platform/baremetal_file.h | 42 -- .../wamr-platform/baremetal_platform.c | 179 -------- .../wamr-platform/baremetal_socket.c | 386 ----------------- .../wamr-platform/baremetal_socket.h | 23 -- .../wamr-platform/baremetal_thread.c | 160 -------- .../wamr-platform/baremetal_thread.h | 15 - .../wamr-platform/baremetal_time.c | 64 --- .../wamr-platform/baremetal_time.h | 16 - .../wamr-platform/platform_init.c | 16 - .../wamr-platform/platform_internal.h | 118 ------ .../wamr-platform/shared_platform.cmake | 18 - 21 files changed, 64 insertions(+), 1482 deletions(-) delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/platform_init.c delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/platform_internal.h delete mode 100644 platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake diff --git a/README.md b/README.md index 65e12a1..da56479 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ ziskemu -e build/bin/println.zkvm.elf ``` #### QEMU RISC-V + ```bash ./platform/riscv-qemu/scripts/c2riscv-qemu.sh \ build/c-packages/println \ @@ -96,14 +97,18 @@ qemu-system-riscv64 -machine virt -bios none \ ``` #### QEMU RISC-V WAMR + +Include OpenSBI BIOS (`-bios default` instead of `-bios none`) such that a shutdown function is present for improved benchmarking. + ```bash ./platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh \ examples/build-wasm/go/fibonacci.wasm \ build/bin/fibonacci.wamr.elf # Run in QEMU -qemu-system-riscv64 -machine virt -m 1024M -bios none \ - -kernel build/bin/fibonacci.wamr.elf -nographic +./docker/docker-shell.sh qemu-system-riscv64 -machine virt -m 1024M \ + -kernel build/bin/fibonacci.wamr.elf -nographic -icount shift=0 \ + -plugin /libinsn.so ``` ## Examples diff --git a/docker/Dockerfile b/docker/Dockerfile index 13d4a95..db9fa3a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -56,9 +56,16 @@ RUN git clone https://github.com/turbolent/w2c2.git /opt/w2c2 && \ RUN apt update && apt install -y git build-essential ninja-build pkg-config libglib2.0-dev libpixman-1-dev +# Include patch for insn.c because otherwise this error appears due to unknown +# instructions: +# +# ERROR:../tests/tcg/plugins/insn.c:97:vcpu_init: assertion failed: (count > 0) +# +# https://lists.gnu.org/archive/html/qemu-discuss/2025-08/msg00001.html RUN git clone https://git.qemu.org/git/qemu.git && \ cd qemu && \ - ./configure --target-list=riscv64-linux-user --enable-plugins && \ + sed -i 's/g_assert(count > 0)/g_assert(count >= 0)/g' tests/tcg/plugins/insn.c && \ + ./configure --target-list=riscv64-linux-user,riscv64-softmmu --enable-plugins && \ make -j4 && \ make install && \ cp build/tests/tcg/plugins/libinsn.so /libinsn.so && \ @@ -74,20 +81,16 @@ RUN git clone https://git.qemu.org/git/qemu.git && \ # https://github.com/bytecodealliance/wasm-micro-runtime/issues/418 # https://github.com/bytecodealliance/wasm-micro-runtime/issues/531 # -# Additionally use LLVM 19. Profiling wamrc when compiling a large wasm -# file like stateful.wasm shows that AttemptToFoldSymbolOffsetDifference +# Additionally use LLVM 20. Profiling wamrc when compiling a large wasm +# file like stateless.wasm shows that AttemptToFoldSymbolOffsetDifference # consumes most of the compile time. LLVM 19 contains a fix for this -# though +# though. Also large code model is in principle supported for RISC-V +# since version 20. # # https://github.com/llvm/llvm-project/issues/81440 -RUN git clone https://github.com/bytecodealliance/wasm-micro-runtime.git /opt/wamr -COPY platform/riscv-wamr-qemu/wamr-platform/ /opt/wamr/core/shared/platform/zkvm/ -RUN cd /opt/wamr && \ - sed -i "s/find_package(Threads REQUIRED)/find_package(Threads)/g" CMakeLists.txt && \ - sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatundisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ - sed -i "/SymbolMap target_sym_map/a REG_SYM(__floatdisf)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ - sed -i "/SymbolMap target_sym_map/a REG_SYM(__ltsf2)," core/iwasm/aot/arch/aot_reloc_riscv.c && \ - sed -i "s/18\.x/19.x/g" build-scripts/build_llvm.py && \ +RUN git clone https://github.com/psilva261/wasm-micro-runtime-zkvm.git /opt/wamr/ && \ + cd /opt/wamr && \ + git checkout zkvm && \ cmake . \ -DWAMR_BUILD_PLATFORM=zkvm \ -DWAMR_BUILD_TARGET=AOT \ diff --git a/platform/riscv-qemu/scripts/c2riscv-qemu.sh b/platform/riscv-qemu/scripts/c2riscv-qemu.sh index 2b93232..f87f949 100755 --- a/platform/riscv-qemu/scripts/c2riscv-qemu.sh +++ b/platform/riscv-qemu/scripts/c2riscv-qemu.sh @@ -69,7 +69,7 @@ PREFIX=/opt/riscv-newlib/bin/riscv64-unknown-elf- # Compiler flags (using -O0 for faster compilation of large generated files) CFLAGS=( - -march=rv64ima + -march=rv64ima_zicsr -mabi=lp64 -mcmodel=medany -specs=nosys.specs diff --git a/platform/riscv-wamr-qemu/main.c b/platform/riscv-wamr-qemu/main.c index e0fbabe..7122246 100644 --- a/platform/riscv-wamr-qemu/main.c +++ b/platform/riscv-wamr-qemu/main.c @@ -6,6 +6,12 @@ extern const char wasmModuleBuffer[]; extern int wasmModuleBuffer_length; +static inline unsigned long rdinstret(void) { + unsigned long v; + asm volatile ("csrr %0, instret" : "=r"(v)); + return v; +} + int main(void) { int argc = 0; char *argv[0]; @@ -17,6 +23,10 @@ int main(void) { wasm_function_inst_t func; wasm_exec_env_t exec_env; uint32 size, stack_size = 16*1024*1024; + unsigned long instrs_start, instrs_init, instrs_load, instrs_inst, + instrs_exec, instrs_unload, instrs_end; + + instrs_start = rdinstret(); wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); @@ -25,6 +35,7 @@ int main(void) { printf("runtime init failed\n"); exit(1); } + instrs_init = rdinstret(); /* parse the WASM file from buffer and create a WASM module */ module = wasm_runtime_load(wasmModuleBuffer, wasmModuleBuffer_length, error_buf, sizeof(error_buf)); @@ -32,6 +43,7 @@ int main(void) { printf("runtime load module failed: %s\n", error_buf); exit(1); } + instrs_load = rdinstret(); /* create an instance of the WASM module (WASM linear memory is ready) */ module_inst = wasm_runtime_instantiate(module, stack_size, 0, error_buf, sizeof(error_buf)); @@ -39,14 +51,24 @@ int main(void) { printf("wasm_runtime_instantiate failed as module_inst=%p: %s\n", module_inst, error_buf); exit(1); } + instrs_inst = rdinstret(); if (!wasm_application_execute_main(module_inst, argc, argv)) { printf("error executing main\n"); printf("exception: %s\n", wasm_runtime_get_exception(module_inst)); } + instrs_exec = rdinstret(); printf("wasm_runtime_unload...\n"); wasm_runtime_unload(module); + instrs_end = instrs_unload = rdinstret(); + + printf("instructions runtime init: %lu\n", instrs_init-instrs_start); + printf("instructions runtime load: %lu\n", instrs_load-instrs_init); + printf("instructions runtime instantiate: %lu\n", instrs_inst-instrs_load); + printf("instructions runtime exec: %lu\n", instrs_exec-instrs_inst); + printf("instructions runtime unload: %lu\n", instrs_unload-instrs_exec); + printf("instructions in total: %lu\n", instrs_end-instrs_start); return 0; } diff --git a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh index da746c1..d0da3a3 100755 --- a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh +++ b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh @@ -28,7 +28,8 @@ if [ $# -lt 2 ]; then echo " $0 build/.c-packages/println build/bin/println.riscv.elf" echo "" echo "To run in QEMU:" - echo " qemu-system-riscv64 -machine virt -bios none \\" + echo " ./docker/docker-shell.sh qemu-system-riscv64 -machine virt \\" + echo " -m 1024M -icount shift=0 -plugin /libinsn.so \\" echo " -kernel build/bin/println.riscv.elf -nographic \\" echo " -semihosting-config enable=on,target=native" echo "" @@ -113,7 +114,7 @@ PREFIX=/opt/riscv-newlib/bin/riscv64-unknown-elf- # Compiler flags (using -O0 for faster compilation of large generated files) CFLAGS=( - -march=rv64ima + -march=rv64ima_zicsr -mabi=lp64 -mcmodel=medany -specs=nosys.specs @@ -185,8 +186,9 @@ if [ $? -eq 0 ] && [ -f "$OUTPUT" ]; then echo "Size: $SIZE" echo "" echo "To run in QEMU:" - echo " qemu-system-riscv64 -machine virt -m 1024M \\" - echo " -bios none -kernel $OUTPUT -nographic \\" + echo " ./docker/docker-shell.sh qemu-system-riscv64 -machine virt \\" + echo " -m 1024M -icount shift=0 -plugin /libinsn.so \\" + echo " -kernel $OUTPUT -nographic \\" echo " -semihosting-config enable=on,target=native" echo "" else diff --git a/platform/riscv-wamr-qemu/startup.S b/platform/riscv-wamr-qemu/startup.S index 84cdef6..0fb4e34 100644 --- a/platform/riscv-wamr-qemu/startup.S +++ b/platform/riscv-wamr-qemu/startup.S @@ -4,7 +4,7 @@ _start: la sp, _stack_top - # Clear BSS section - using symbols defined in our linker script + /* Clear BSS section - using symbols defined in our linker script */ la t0, _bss_start la t1, _bss_end clear_bss: @@ -14,8 +14,14 @@ clear_bss: j clear_bss bss_done: - # Jump to C code + /* Call main */ call main - # In case main returns -1: j 1b \ No newline at end of file + /* https://github.com/xypron/riscv_test_payload (MIT-licensed) */ + li a7, 0x53525354 # SBI extension: SRST (System Reset) + li a6, 0 # Function: system reset + li a0, 0 # Reset type: shutdown + li a1, 0 # Reset reason: no reason + ecall # Perform system shutdown +end: + j end diff --git a/platform/riscv-wamr-qemu/syscalls.c b/platform/riscv-wamr-qemu/syscalls.c index 2df15ee..593ab63 100644 --- a/platform/riscv-wamr-qemu/syscalls.c +++ b/platform/riscv-wamr-qemu/syscalls.c @@ -70,6 +70,6 @@ void* _sbrk(int incr) { } // Required stubs -void _exit(int code) { while (1); } +void _exit(int code) {} int _kill(int pid, int sig) { return -1; } int _getpid(void) { return 1; } diff --git a/platform/riscv-wamr-qemu/virt.ld b/platform/riscv-wamr-qemu/virt.ld index eebfbc6..eb6828f 100644 --- a/platform/riscv-wamr-qemu/virt.ld +++ b/platform/riscv-wamr-qemu/virt.ld @@ -6,13 +6,13 @@ ENTRY(_start) /* QEMU virt machine memory map */ MEMORY { - ram (wxa) : ORIGIN = 0x80000000, LENGTH = 1024M + ram (wxa) : ORIGIN = 0x80200000, LENGTH = 1024M } SECTIONS { /* Start of RAM */ - . = 0x80000000; + . = 0x80200000; /* Code section */ .text : { diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c deleted file mode 100644 index af33eb8..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_clock.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_extension.h" -#include "platform_api_vmcore.h" - -// Jan 1st 2025 in nanoseconds -#define OS_CLOCK_TIME_START 1735686000e9 - -__wasi_errno_t -os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution) -{ - printf("os_clock_res_get\n"); - return __WASI_ENOSYS; -} - -uint64 os_clock_current_time = 0; - -__wasi_errno_t -os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision, - __wasi_timestamp_t *time) -{ - printf("os_clock_time_get\n"); - - *time = OS_CLOCK_TIME_START + os_clock_current_time; - os_clock_current_time += 100; - - return __WASI_ESUCCESS; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c deleted file mode 100644 index dadcea4..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" -#include "platform_api_extension.h" - -#include -#include - -int -ocall_get_errno() -{ - return errno; -} - -static inline bool -os_is_virtual_fd(int fd) -{ - switch (fd) { - case STDIN_FILENO: - case STDOUT_FILENO: - case STDERR_FILENO: - return true; - default: - return false; - }; -} - -__wasi_errno_t -os_fstat(os_file_handle handle, struct __wasi_filestat_t *buf) -{ - printf("os_fstat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_fstatat(os_file_handle handle, const char *path, - struct __wasi_filestat_t *buf, __wasi_lookupflags_t lookup_flags) -{ - printf("os_fstatat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_file_get_fdflags(os_file_handle handle, __wasi_fdflags_t *flags) -{ - printf("os_file_get_fdflags\n"); - *flags = 0; - return __WASI_ESUCCESS; -} - -__wasi_errno_t -os_file_set_fdflags(os_file_handle handle, __wasi_fdflags_t flags) -{ - printf("os_file_set_fdflags\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_fdatasync(os_file_handle handle) -{ - printf("os_fdatasync\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_fsync(os_file_handle handle) -{ - printf("os_fsync\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_open_preopendir(const char *path, os_file_handle *out) -{ - printf("os_open_preopendir\n"); - return __WASI_ENOSYS; -} - - -__wasi_errno_t -os_openat(os_file_handle handle, const char *path, __wasi_oflags_t oflags, - __wasi_fdflags_t fd_flags, __wasi_lookupflags_t lookup_flags, - wasi_libc_file_access_mode access_mode, os_file_handle *out) -{ - printf("os_openat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_file_get_access_mode(os_file_handle handle, - wasi_libc_file_access_mode *access_mode) -{ - printf("os_file_get_access_mode\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_close(os_file_handle handle, bool is_stdio) -{ - printf("os_close\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_preadv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, - __wasi_filesize_t offset, size_t *nread) -{ - printf("os_preadv\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_pwritev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, - __wasi_filesize_t offset, size_t *nwritten) -{ - printf("os_pwritev\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_readv(os_file_handle handle, const struct __wasi_iovec_t *iov, int iovcnt, - size_t *nread) -{ - printf("os_readv\n"); - return __WASI_ENOSYS; -} - -/* With wasi-libc we need to redirect write on stdout/err to printf */ -// TODO: handle write on stdin -__wasi_errno_t -os_writev(os_file_handle handle, const struct __wasi_ciovec_t *iov, int iovcnt, - size_t *nwritten) -{ - ssize_t total_written = 0; - - // Write data from each buffer - for (int i = 0; i < iovcnt; i++) { - const char *buf = (const char *)iov[i].buf; - for (int j = 0; j < iov[i].buf_len; j++) { - putchar(buf[j]); - } - total_written += iov[i].buf_len; - } - - *nwritten = total_written; - - return __WASI_ESUCCESS; - -} - -__wasi_errno_t -os_fallocate(os_file_handle handle, __wasi_filesize_t offset, - __wasi_filesize_t length) -{ - printf("os_fallocate\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_ftruncate(os_file_handle handle, __wasi_filesize_t size) -{ - printf("os_ftruncate\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_futimens(os_file_handle handle, __wasi_timestamp_t access_time, - __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags) -{ - printf("os_futimens\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_utimensat(os_file_handle handle, const char *path, - __wasi_timestamp_t access_time, - __wasi_timestamp_t modification_time, __wasi_fstflags_t fstflags, - __wasi_lookupflags_t lookup_flags) -{ - printf("os_utimensat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_readlinkat(os_file_handle handle, const char *path, char *buf, - size_t bufsize, size_t *nread) -{ - printf("os_readlinkat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_linkat(os_file_handle from_handle, const char *from_path, - os_file_handle to_handle, const char *to_path, - __wasi_lookupflags_t lookup_flags) -{ - printf("os_linkat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_symlinkat(const char *old_path, os_file_handle handle, const char *new_path) -{ - printf("os_symlinkat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_mkdirat(os_file_handle handle, const char *path) -{ - printf("os_mkdirat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_renameat(os_file_handle old_handle, const char *old_path, - os_file_handle new_handle, const char *new_path) -{ - printf("os_renameat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_unlinkat(os_file_handle handle, const char *path, bool is_dir) -{ - printf("os_unlinkat\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_lseek(os_file_handle handle, __wasi_filedelta_t offset, - __wasi_whence_t whence, __wasi_filesize_t *new_offset) -{ - printf("os_lseek\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_fadvise(os_file_handle handle, __wasi_filesize_t offset, - __wasi_filesize_t length, __wasi_advice_t advice) -{ - printf("os_fadvise\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_isatty(os_file_handle handle) -{ - printf("os_isatty\n"); - return __WASI_ENOTTY; -} - -os_file_handle -os_convert_stdin_handle(os_raw_file_handle raw_stdin) -{ - return 0; -} - -os_file_handle -os_convert_stdout_handle(os_raw_file_handle raw_stdout) -{ - return 1; -} - -os_file_handle -os_convert_stderr_handle(os_raw_file_handle raw_stderr) -{ - return 2; -} - -__wasi_errno_t -os_fdopendir(os_file_handle handle, os_dir_stream *dir_stream) -{ - printf("os_fdopendir\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_rewinddir(os_dir_stream dir_stream) -{ - printf("os_rewinddir\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_seekdir(os_dir_stream dir_stream, __wasi_dircookie_t position) -{ - printf("os_seekdir\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_readdir(os_dir_stream dir_stream, __wasi_dirent_t *entry, - const char **d_name) -{ - printf("os_readdir\n"); - return __WASI_ENOSYS; -} - -__wasi_errno_t -os_closedir(os_dir_stream dir_stream) -{ - printf("os_closedir\n"); - return __WASI_ENOSYS; -} - -os_dir_stream -os_get_invalid_dir_stream() -{ - return NULL; -} - -bool -os_is_dir_stream_valid(os_dir_stream *dir_stream) -{ - return false; -} - -bool -os_is_handle_valid(os_file_handle *handle) -{ - if (handle == NULL) - return false; - return *handle >= 0; -} - -char * -os_realpath(const char *path, char *resolved_path) -{ - return NULL; -} - -bool -os_compare_file_handle(os_file_handle handle1, os_file_handle handle2) -{ - return handle1 == handle2; -} - -bool -os_is_stdin_handle(os_file_handle handle) -{ - return handle == 0; -} - -bool -os_is_stdout_handle(os_file_handle handle) -{ - return handle == 1; -} - -bool -os_is_stderr_handle(os_file_handle handle) -{ - return handle == 2; -} - -int -os_ioctl(os_file_handle handle, int request, ...) -{ - return __WASI_ENOSYS; -} - -int -os_poll(os_poll_file_handle *fds, os_nfds_t nfs, int timeout) -{ - return BHT_ERROR; -} - -int -sched_yield(void) -{ - return BHT_ERROR; -} - -int -get_errno(void) -{ - int ret; - - if (ocall_get_errno(&ret) != 0) { - return -1; - } - return ret; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h deleted file mode 100644 index fd121e2..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_file.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BAREMETAL_FILE_H -#define _BAREMETAL_FILE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define POLLIN 0x001 -#define POLLPRI 0x002 -#define POLLOUT 0x004 -#define POLLERR 0x008 -#define POLLHUP 0x010 -#define POLLNVAL 0x020 -#define POLLRDNORM 0x040 -#define POLLRDBAND 0x080 -#define POLLWRNORM 0x100 -#define POLLWRBAND 0x200 - -#define FIONREAD 0x541B - -struct pollfd { - int fd; - short events; - short revents; -}; - -int -sched_yield(void); - -int -get_errno(void); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _BAREMETAL_FILE_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c deleted file mode 100644 index 790d136..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_platform.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-FileCopyrightText: 2024 Siemens AG (For Zephyr usermode changes) - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" -#include "platform_api_extension.h" - -#define OUTPUT_ADDR 0xa0010000 - -void writeuartc(const char c) { - char *ptr_val = (char *)(0xa0000000+512); - *ptr_val = c; -} - -int outputCount = 0; - -// https://github.com/eth-act/skunkworks-tama/blob/main/tamaboards/zkvm/board.go -void printk(uint32_t val) { - // TODO: This is a stub. Just write to the output address - // Write directly to OUTPUT_ADDR - // Format: [count:u32][data:bytes] - // First update the count at OUTPUT_ADDR - outputCount+=1; - uint32_t *ptr_count = (uint32_t *)OUTPUT_ADDR; - *ptr_count = outputCount; - - // Write the byte at OUTPUT_ADDR + 4 + (outputCount-1) - uint32_t *ptr_val = (uint32_t *)(OUTPUT_ADDR+4+4*(outputCount-1)); - *ptr_val = val; -} - -static int -_stdout_hook_iwasm(int c) -{ - printk((int32_t) c); - return 1; -} - -int -os_thread_sys_init(); - -void -os_thread_sys_destroy(); - -void * -os_malloc(unsigned size) -{ - return malloc(size); -} - -void * -os_realloc(void *ptr, unsigned size) -{ - return realloc(ptr, size); -} - -void -os_free(void *ptr) -{ - free(ptr); -} - -int -os_dumps_proc_mem_info(char *out, unsigned int size) -{ - return -1; -} - -#if 0 -struct out_context { - int count; -}; - -typedef int (*out_func_t)(int c, void *ctx); - -static int -char_out(int c, void *ctx) -{ - struct out_context *out_ctx = (struct out_context*)ctx; - out_ctx->count++; - return _stdout_hook_iwasm(c); -} - -int -os_vprintf(const char *fmt, va_list ap) -{ -#if 0 - struct out_context ctx = { 0 }; - cbvprintf(char_out, &ctx, fmt, ap); - return ctx.count; -#else - vprintk(fmt, ap); - return 0; -#endif -} -#endif - -int -os_printf(const char *format, ...) -{ - int ret = 0; - va_list ap; - - va_start(ap, format); -#ifndef BH_VPRINTF - ret += vprintf(format, ap); -#else - ret += BH_VPRINTF(format, ap); -#endif - va_end(ap); - - return ret; -} - -int -os_vprintf(const char *format, va_list ap) -{ -#ifndef BH_VPRINTF - return vprintf(format, ap); -#else - return BH_VPRINTF(format, ap); -#endif -} - -void * -os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file) -{ - void *addr; - - if ((uint64)size >= UINT32_MAX) - return NULL; - - addr = BH_MALLOC(size); - - if (addr) - memset(addr, 0, size); - return addr; -} - -int -os_getpagesize(void) -{ - return 4096; -} - - -void * -os_mremap(void *old_addr, size_t old_size, size_t new_size) -{ - return os_mremap_slow(old_addr, old_size, new_size); -} - -void -os_munmap(void *addr, size_t size) -{ - BH_FREE(addr); -} - -int -os_mprotect(void *addr, size_t size, int prot) -{ - return 0; -} - -void -os_dcache_flush() -{} - -void -os_icache_flush(void *start, size_t len) -{} - -os_raw_file_handle -os_invalid_raw_handle(void) -{ - return -1; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c deleted file mode 100644 index 343426f..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2024 Sony Semiconductor Solutions Corporation. - * - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" -#include "platform_api_extension.h" - -int -os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, - unsigned int *addrlen) -{ - return BHT_ERROR; -} - -int -os_socket_connect(bh_socket_t socket, const char *addr, int port) -{ - return BHT_ERROR; -} - -int -os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, - bh_sockaddr_t *src_addr) -{ - return BHT_ERROR; -} - -int -os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, - int flags, const bh_sockaddr_t *dest_addr) -{ - return BHT_ERROR; -} - -int -os_socket_addr_resolve(const char *host, const char *service, - uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4, - bh_addr_info_t *addr_info, size_t addr_info_size, - size_t *max_info_size) -{ - return BHT_ERROR; -} - -int -os_socket_close(bh_socket_t socket) -{ - return BHT_ERROR; -} - -int -os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) -{ - return BHT_ERROR; -} - -int -os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) -{ - return BHT_ERROR; -} - -int -os_socket_bind(bh_socket_t socket, const char *host, int *port) -{ - return BHT_ERROR; -} - -int -os_socket_listen(bh_socket_t socket, int max_client) -{ - return BHT_ERROR; -} - -int -os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) -{ - return BHT_ERROR; -} - -int -os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) -{ - return BHT_ERROR; -} - -__wasi_errno_t -os_socket_shutdown(bh_socket_t socket) -{ - printf("os_socket_shutdown\n"); - return __WASI_ENOSYS; -} - -int -os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) -{ - return BHT_ERROR; -} - -int -os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) -{ - return BHT_ERROR; -} - -int -os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) -{ - return BHT_ERROR; -} - -int -os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) -{ - return BHT_ERROR; -} - -int -os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) -{ - return BHT_ERROR; -} - -int -os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) -{ - return BHT_ERROR; -} - -int -os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) -{ - return BHT_ERROR; -} - -int -os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) -{ - return BHT_ERROR; -} - -int -os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) -{ - return BHT_ERROR; -} - -int -os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) -{ - return BHT_ERROR; -} - -int -os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) -{ - return BHT_ERROR; -} - -int -os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) -{ - return BHT_ERROR; -} - -int -os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) -{ - return BHT_ERROR; -} - -int -os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) -{ - return BHT_ERROR; -} - -int -os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) -{ - return BHT_ERROR; -} - -int -os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_set_ip_add_membership(bh_socket_t socket, - bh_ip_addr_buffer_t *imr_multiaddr, - uint32_t imr_interface, bool is_ipv6) -{ - return BHT_ERROR; -} - -int -os_socket_set_ip_drop_membership(bh_socket_t socket, - bh_ip_addr_buffer_t *imr_multiaddr, - uint32_t imr_interface, bool is_ipv6) -{ - return BHT_ERROR; -} - -int -os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) -{ - return BHT_ERROR; -} - -int -os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) -{ - return BHT_ERROR; -} - -int -os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) -{ - return BHT_ERROR; -} - -int -os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) -{ - return BHT_ERROR; -} - -int -os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled) -{ - return BHT_ERROR; -} - -int -os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled) -{ - return BHT_ERROR; -} - -static void -swap16(uint8 *pData) -{ - uint8 value = *pData; - *(pData) = *(pData + 1); - *(pData + 1) = value; -} - -static void -swap32(uint8 *pData) -{ - uint8 value = *pData; - *pData = *(pData + 3); - *(pData + 3) = value; - - value = *(pData + 1); - *(pData + 1) = *(pData + 2); - *(pData + 2) = value; -} - -/** In-enclave implementation of POSIX functions **/ -static bool -is_little_endian() -{ - long i = 0x01020304; - unsigned char *c = (unsigned char *)&i; - return (*c == 0x04) ? true : false; -} - -uint16 -htons(uint16 value) -{ - uint16 ret; - if (is_little_endian()) { - ret = value; - swap16((uint8 *)&ret); - return ret; - } - - return value; -} - -uint32 -htonl(uint32 value) -{ - uint32 ret; - if (is_little_endian()) { - ret = value; - swap32((uint8 *)&ret); - return ret; - } - - return value; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h deleted file mode 100644 index 64586d4..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_socket.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _BAREMETAL_SOCKET_H -#define _BAREMETAL_SOCKET_H - -#ifdef __cplusplus -extern "C" { -#endif - -uint32_t -htonl(uint32_t value); - -uint16_t -htons(uint16_t value); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _BAREMETAL_SOCKET_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c deleted file mode 100644 index 6d22141..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" -#include "platform_api_extension.h" - - -korp_tid -os_self_thread() -{ - return 0; -} - -int -os_mutex_init(korp_mutex *mutex) -{ - return BHT_OK; -} - -int -os_mutex_destroy(korp_mutex *mutex) -{ - return BHT_OK; -} - -int -os_mutex_lock(korp_mutex *mutex) -{ - return 0; -} - -int -os_mutex_unlock(korp_mutex *mutex) -{ - return 0; -} - -int -os_cond_init(korp_cond *cond) -{ - return BHT_OK; -} - -int -os_cond_destroy(korp_cond *cond) -{ - return BHT_OK; -} - -int -os_cond_wait(korp_cond *cond, korp_mutex *mutex) -{ - return BHT_OK; -} - -int -os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds) -{ - os_printf("warning: baremetal pthread_cond_timedwait isn't supported, " - "calling pthread_cond_wait instead!\n"); - return BHT_ERROR; -} - -int -os_cond_signal(korp_cond *cond) -{ - return BHT_OK; -} - -int -os_cond_broadcast(korp_cond *cond) -{ - return BHT_OK; -} - -int -os_thread_join(korp_tid thread, void **value_ptr) -{ - return 0; -} - -int -os_thread_detach(korp_tid thread) -{ - /* baremetal pthread_detach isn't provided, return directly. */ - return 0; -} - -void -os_thread_exit(void *retval) -{ - return; -} - -uint8 * -os_thread_get_stack_boundary() -{ - /* TODO: get baremetal stack boundary */ - return NULL; -} - -void -os_thread_jit_write_protect_np(bool enabled) -{} - -int -os_rwlock_init(korp_rwlock *lock) -{ - return BHT_OK; -} - -int -os_rwlock_rdlock(korp_rwlock *lock) -{ - return BHT_OK; -} - -int -os_rwlock_wrlock(korp_rwlock *lock) -{ - return BHT_OK; -} - -int -os_rwlock_unlock(korp_rwlock *lock) -{ - return BHT_OK; -} - -int -os_rwlock_destroy(korp_rwlock *lock) -{ - return BHT_OK; -} - -int -os_thread_signal_init(os_signal_handler handler) -{ - return 0; -} - -bool -os_thread_signal_inited() -{ - return false; -} - -void -os_thread_signal_destroy() -{} - -int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { - if (once_control != 0) { - // TODO - init_routine(); - } - return 0; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h deleted file mode 100644 index 7f63e0d..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_thread.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _BAREMETAL_THREAD_H -#define _BAREMETAL_THREAD_H - -int pthread_condattr_init(pthread_condattr_t *attr); -int pthread_condattr_destroy(pthread_condattr_t *attr); - -int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); - -int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id); - -int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); - -#define PTHREAD_ONCE_INIT {} - -#endif /* end of _BAREMETAL_THREAD_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c deleted file mode 100644 index d5c1983..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" - -#define TRACE_FUNC() os_printf("undefined %s\n", __FUNCTION__) -#define TRACE_OCALL_FAIL() os_printf("ocall %s failed!\n", __FUNCTION__) - -int -ocall_clock_gettime(int *p_ret, unsigned clock_id, void *tp_buf, - unsigned int tp_buf_size); -int -ocall_clock_getres(int *p_ret, int clock_id, void *res_buf, - unsigned int res_buf_size); -int -ocall_utimensat(int *p_ret, int dirfd, const char *pathname, - const void *times_buf, unsigned int times_buf_size, int flags); -int -ocall_futimens(int *p_ret, int fd, const void *times_buf, - unsigned int times_buf_size); - -int -ocall_clock_nanosleep(unsigned clock_id, int flags, const void *req_buf, - unsigned int req_buf_size, const void *rem_buf, - unsigned int rem_buf_size) -{ - return clock_nanosleep((clockid_t)clock_id, flags, - (struct timespec *)req_buf, - (struct timespec *)rem_buf); -} - -uint64 -os_time_get_boot_us() -{ - return 0; -} - -uint64 -os_time_thread_cputime_us(void) -{ - return 0; -} - -int -clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, - struct timespec *remain) -{ - int ret; - - if (ocall_clock_nanosleep(clock_id, flags, (void *)request, - sizeof(struct timespec), (void *)remain, - sizeof(struct timespec)) - != 0) { - TRACE_OCALL_FAIL(); - return -1; - } - - if (ret == -1) - errno = get_errno(); - - return ret; -} diff --git a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h b/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h deleted file mode 100644 index ad151e2..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/baremetal_time.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _BAREMETAL_TIME_H -#define _BAREMETAL_TIME_H - -#ifdef __cplusplus -extern "C" { -#endif - -int -clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, - struct timespec *remain); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _BAREMETAL_TIME_H */ \ No newline at end of file diff --git a/platform/riscv-wamr-qemu/wamr-platform/platform_init.c b/platform/riscv-wamr-qemu/wamr-platform/platform_init.c deleted file mode 100644 index 0ab0592..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/platform_init.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "platform_api_vmcore.h" - -int -bh_platform_init() -{ - return 0; -} - -void -bh_platform_destroy() -{} diff --git a/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h b/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h deleted file mode 100644 index 3aa242f..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/platform_internal.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * Copyright (C) 2023 Dylibso. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _PLATFORM_INTERNAL_H -#define _PLATFORM_INTERNAL_H - -#define DIR int - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "baremetal_file.h" -#include "baremetal_socket.h" -#include "baremetal_time.h" -#include "baremetal_thread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef BH_PLATFORM_ZKVM -#define BH_PLATFORM_ZKVM -#endif - -/* Stack size of applet threads's native part. */ -#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) - -/* Default thread priority */ -#define BH_THREAD_DEFAULT_PRIORITY 0 - -typedef pthread_t korp_tid; -typedef pthread_mutex_t korp_mutex; -typedef pthread_cond_t korp_cond; -typedef pthread_t korp_thread; -typedef int korp_rwlock; -typedef int korp_sem; - -#define bh_socket_t int - -typedef int os_file_handle; -typedef DIR *os_dir_stream; -typedef int os_raw_file_handle; -typedef struct pollfd os_poll_file_handle; -typedef int os_nfds_t; -typedef struct timespec os_timespec; - -#ifndef CLOCK_MONOTONIC -#define CLOCK_MONOTONIC 4 -#endif - -static inline os_file_handle -os_get_invalid_handle(void) -{ - return -1; -} - -#if WASM_DISABLE_HW_BOUND_CHECK == 0 -#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \ - || defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_RISCV64_LP64D) \ - || defined(BUILD_TARGET_RISCV64_LP64) - -#include - -typedef jmp_buf korp_jmpbuf; - -#define os_setjmp setjmp -#define os_longjmp longjmp -#define os_alloca alloca - -typedef void (*os_signal_handler)(void *sig_addr); - -int -os_thread_signal_init(os_signal_handler handler); - -void -os_thread_signal_destroy(); - -bool -os_thread_signal_inited(); - -void -os_signal_unmask(); - -void -os_sigreturn(); -#endif /* end of BUILD_TARGET_X86_64/AMD_64/AARCH64/RISCV64 */ -#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ - -int -os_getpagesize(void); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake b/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake deleted file mode 100644 index b7dd707..0000000 --- a/platform/riscv-wamr-qemu/wamr-platform/shared_platform.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# Copyright (C) 2023 Dylibso. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) - -add_definitions(-DBH_PLATFORM_ZKVM) - -include_directories(${PLATFORM_SHARED_DIR}) -include_directories(${PLATFORM_SHARED_DIR}/../include) - -file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) - -include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake) -set (source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE}) - -set (PLATFORM_SHARED_SOURCE ${source_all}) - From a26bc346c6d4fe997113b91a922aa605203ff346 Mon Sep 17 00:00:00 2001 From: Philip Silva Date: Mon, 22 Dec 2025 11:09:27 +0100 Subject: [PATCH 8/8] Add WAMR Benchmarks: use plugin, update README and script --- README.md | 8 ++++--- go_benchmark.sh | 5 +++++ platform/riscv-wamr-qemu/main.c | 22 ------------------- .../riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh | 12 +++++----- 4 files changed, 15 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index da56479..7d8491b 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Include OpenSBI BIOS (`-bios default` instead of `-bios none`) such that a shutd # Run in QEMU ./docker/docker-shell.sh qemu-system-riscv64 -machine virt -m 1024M \ - -kernel build/bin/fibonacci.wamr.elf -nographic -icount shift=0 \ + -kernel build/bin/fibonacci.wamr.elf -nographic -d plugin \ -plugin /libinsn.so ``` @@ -211,9 +211,9 @@ Please note that: - `./platform/riscv-qemu-user/scripts/c2riscv-qemu-user.sh` uses target `-march=rv64imad -march=rv64imad` whereas Go direct compilation uses `rv64gc`. - `wasmtime` targets rv64gc -|program|through WASM, w2c2, -O0|through WASM, w2c2, optimized|though WASM, wasmtme|through WASM, wasmer (cranelift)|directly| +|program|through WASM, w2c2, -O0|through WASM, w2c2, optimized|through WAMR, -O0|though WASM, wasmtme|through WASM, wasmer (cranelift)|directly| |---|---|---|---|---|---| -|`stateless`|12,866,052,519|2,110,574,100 (-O3)|874,758,419|953,874,491|236,265,327| +|`stateless`|12,866,052,519|2,110,574,100 (-O3)|5,427,433,654|874,758,419|953,874,491|236,265,327| ## Analysis of the results @@ -221,6 +221,8 @@ Please note that: Surprisingly WASM though `wasmtime` is faster than `w2c2`. `wasmtime` approach is ~3-4 times slower than the direct approach. +Unoptimized WAMR AOT is currently in between `w2c2` and wasmtime. Running WAMR with non-zero optimization levels on RISC-V currently fails with a relocation error. https://github.com/bytecodealliance/wasm-micro-runtime/issues/4765 + # Size of binaries ``` diff --git a/go_benchmark.sh b/go_benchmark.sh index 8c9a9ab..1a8bc37 100755 --- a/go_benchmark.sh +++ b/go_benchmark.sh @@ -19,6 +19,10 @@ echo "Transpiling WASM to WASMU with wasmer..." # TODO: Cranelift is used for now because LLVM support is buggy. Once LLVM is fixed in wasmer use `--llvm` flag instead of `cranelift`; https://github.com/wasmerio/wasmer/issues/5951#issuecomment-3632904384 ./docker/docker-shell.sh /root/.wasmer/bin/wasmer compile --cranelift --target riscv64gc-unknown-linux-gnu examples/build-wasm/go/stateless.wasm -o examples/build-wasm/go/stateless-by-wasmer/src/stateless.wasmu +echo "Transpiling WASM to WAMR AOT with wamrc..." + +./platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh examples/build-wasm/go/stateless.wasm build/bin/stateless.wamr.elf + echo "Compiling C to RISCV..." OPT_LEVEL="-O0" ./platform/riscv-qemu-user/scripts/c2riscv-qemu-user.sh build/c-packages/stateless/ build/bin/stateless.riscv.O0.elf @@ -36,6 +40,7 @@ echo "" > go_benchmark_results.txt ./docker/docker-shell.sh qemu-riscv64 -plugin /libinsn.so examples/go/stateless/stateless >> go_benchmark_results.txt 2>&1 ./docker/docker-shell.sh qemu-riscv64 -plugin /libinsn.so examples/build-wasm/go/stateless-by-wasmtime/target/riscv64gc-unknown-linux-gnu/release/standalone >> go_benchmark_results.txt 2>&1 ./docker/docker-shell.sh qemu-riscv64 -plugin /libinsn.so examples/build-wasm/go/stateless-by-wasmer/target/riscv64gc-unknown-linux-gnu/release/standalone >> go_benchmark_results.txt 2>&1 +./docker/docker-shell.sh qemu-system-riscv64 -d plugin -machine virt -m 1024M -plugin /libinsn.so -kernel build/bin/stateless.wamr.elf -nographic >> go_benchmark_results.txt 2>&1 echo "Done" diff --git a/platform/riscv-wamr-qemu/main.c b/platform/riscv-wamr-qemu/main.c index 7122246..e0fbabe 100644 --- a/platform/riscv-wamr-qemu/main.c +++ b/platform/riscv-wamr-qemu/main.c @@ -6,12 +6,6 @@ extern const char wasmModuleBuffer[]; extern int wasmModuleBuffer_length; -static inline unsigned long rdinstret(void) { - unsigned long v; - asm volatile ("csrr %0, instret" : "=r"(v)); - return v; -} - int main(void) { int argc = 0; char *argv[0]; @@ -23,10 +17,6 @@ int main(void) { wasm_function_inst_t func; wasm_exec_env_t exec_env; uint32 size, stack_size = 16*1024*1024; - unsigned long instrs_start, instrs_init, instrs_load, instrs_inst, - instrs_exec, instrs_unload, instrs_end; - - instrs_start = rdinstret(); wasm_runtime_set_log_level(WASM_LOG_LEVEL_VERBOSE); @@ -35,7 +25,6 @@ int main(void) { printf("runtime init failed\n"); exit(1); } - instrs_init = rdinstret(); /* parse the WASM file from buffer and create a WASM module */ module = wasm_runtime_load(wasmModuleBuffer, wasmModuleBuffer_length, error_buf, sizeof(error_buf)); @@ -43,7 +32,6 @@ int main(void) { printf("runtime load module failed: %s\n", error_buf); exit(1); } - instrs_load = rdinstret(); /* create an instance of the WASM module (WASM linear memory is ready) */ module_inst = wasm_runtime_instantiate(module, stack_size, 0, error_buf, sizeof(error_buf)); @@ -51,24 +39,14 @@ int main(void) { printf("wasm_runtime_instantiate failed as module_inst=%p: %s\n", module_inst, error_buf); exit(1); } - instrs_inst = rdinstret(); if (!wasm_application_execute_main(module_inst, argc, argv)) { printf("error executing main\n"); printf("exception: %s\n", wasm_runtime_get_exception(module_inst)); } - instrs_exec = rdinstret(); printf("wasm_runtime_unload...\n"); wasm_runtime_unload(module); - instrs_end = instrs_unload = rdinstret(); - - printf("instructions runtime init: %lu\n", instrs_init-instrs_start); - printf("instructions runtime load: %lu\n", instrs_load-instrs_init); - printf("instructions runtime instantiate: %lu\n", instrs_inst-instrs_load); - printf("instructions runtime exec: %lu\n", instrs_exec-instrs_inst); - printf("instructions runtime unload: %lu\n", instrs_unload-instrs_exec); - printf("instructions in total: %lu\n", instrs_end-instrs_start); return 0; } diff --git a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh index d0da3a3..68c5285 100755 --- a/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh +++ b/platform/riscv-wamr-qemu/scripts/wasm2wamr-qemu.sh @@ -1,10 +1,8 @@ #!/bin/bash set -e -#set -x ## TODO : remove debug - -# c2riscv-wamr-qemu - Compile WASM to WAMR RISC-V QEMU binary -# Usage: ./platform/riscv-wamr-qemu/scripts/c2riscv-wamr-qemu.sh +# wasm2riscv-wamr-qemu - Compile WASM to WAMR RISC-V QEMU binary +# Usage: ./platform/riscv-wamr-qemu/scripts/wasm2riscv-wamr-qemu.sh SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WAMR_QEMU_DIR="$(dirname "$SCRIPT_DIR")" @@ -29,7 +27,7 @@ if [ $# -lt 2 ]; then echo "" echo "To run in QEMU:" echo " ./docker/docker-shell.sh qemu-system-riscv64 -machine virt \\" - echo " -m 1024M -icount shift=0 -plugin /libinsn.so \\" + echo " -m 1024M -d plugin -plugin /libinsn.so \\" echo " -kernel build/bin/println.riscv.elf -nographic \\" echo " -semihosting-config enable=on,target=native" echo "" @@ -114,7 +112,7 @@ PREFIX=/opt/riscv-newlib/bin/riscv64-unknown-elf- # Compiler flags (using -O0 for faster compilation of large generated files) CFLAGS=( - -march=rv64ima_zicsr + -march=rv64ima -mabi=lp64 -mcmodel=medany -specs=nosys.specs @@ -187,7 +185,7 @@ if [ $? -eq 0 ] && [ -f "$OUTPUT" ]; then echo "" echo "To run in QEMU:" echo " ./docker/docker-shell.sh qemu-system-riscv64 -machine virt \\" - echo " -m 1024M -icount shift=0 -plugin /libinsn.so \\" + echo " -m 1024M -d plugin -plugin /libinsn.so \\" echo " -kernel $OUTPUT -nographic \\" echo " -semihosting-config enable=on,target=native" echo ""