dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

Missing risc-v implementations in mono mini #74071

Open am11 opened 2 years ago

am11 commented 2 years ago

To make dotnet(1) work with -p:RuntimeFlavor=mono on linux-riscv64 desktop, there are ~50 functions that need implementation in the following files:

src/mono/mono/mini/exceptions-riscv.c
src/mono/mono/mini/mini-riscv.c
src/mono/mono/mini/tramp-riscv.c

We can skip the _dyn_ APIs: git grep mono_arch_.*dyn ':/src/mono/*riscv*'.

To cross-compile:

# on Ubuntu amd64 - with curl, jq and docker installed

$ tag="$(curl -sSL "https://raw.githubusercontent.com/dotnet/versions/main/build-info/docker/image-info.dotnet-dotnet-buildtools-prereqs-docker-main.json" |\
    jq -r '.repos[] | .images[] | .platforms [] | select(.dockerfile | contains("riscv64")).simpleTags[0]' | tail -1)"

$ URN="mcr.microsoft.com/dotnet-buildtools/prereqs:$tag"

$ cd runtime
$ docker run -e ROOTFS_DIR=/crossrootfs/riscv64 -v$(pwd):/runtime $URN \
      /runtime/build.sh mono+libs+host -cross -arch riscv64
# this should succeed

Then copy artifacts/bin to riscv64 VM (e.g. this setup: https://gist.github.com/marrrk/b1014564826449dc23cecb3b8a01a5f2) and run some assembly to see the crash due to missing implementation:

$ runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/dotnet console22/bin/Debug/net7.0/console22.dll
* Assertion: should not be reached at /runtime/src/mono/mono/mini/mini-riscv.c:454

=================================================================
    Native Crash Reporting
=================================================================
Got a SIGABRT while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
    Native stacktrace:
=================================================================
    0xffffff96397be2 - Unknown

=================================================================
    External Debugger Dump:
=================================================================
[New LWP 321]
[New LWP 322]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/riscv64-linux-gnu/libthread_db.so.1".
0x00ffffff96816bf0 in __GI___wait4 (pid=<optimized out>, stat_loc=0xfffffff8f05fbc, options=<optimized out>, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
30  ../sysdeps/unix/sysv/linux/wait4.c: No such file or directory.
  Id   Target Id                                       Frame 
* 1    Thread 0xffffff96790010 (LWP 320) "dotnet"      0x00ffffff96816bf0 in __GI___wait4 (pid=<optimized out>, stat_loc=0xfffffff8f05fbc, options=<optimized out>, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
  2    Thread 0xffffff957ff130 (LWP 321) "SGen worker" 0x00ffffff96b24e74 in __futex_abstimed_wait_common64 (futex_word=futex_word@entry=0xffffff96490680 <work_cond+40>, expected=<optimized out>, clockid=<optimized out>, abstime=abstime@entry=0x0, private=<optimized out>, cancel=cancel@entry=true) at ../sysdeps/nptl/futex-internal.c:74
  3    Thread 0xffffff95ec7130 (LWP 322) "dotnet"      0x00ffffff968317da in __GI___poll (fds=0xffffff8c003d60, nfds=1, timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:41

Thread 3 (Thread 0xffffff95ec7130 (LWP 322) "dotnet"):
#0  0x00ffffff968317da in __GI___poll (fds=0xffffff8c003d60, nfds=1, timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:41
#1  0x00ffffff96469b84 in ipc_poll_fds (fds=0xffffff8c003d60, nfds=1, timeout=4294967295) at /runtime/src/native/eventpipe/ds-ipc-pal-socket.c:470
#2  0x00ffffff964698f6 in ds_ipc_poll (poll_handles_data=0xffffff8c003550, poll_handles_data_len=1, timeout_ms=4294967295, callback=0xffffff964667f4 <server_warning_callback>) at /runtime/src/native/eventpipe/ds-ipc-pal-socket.c:1096
#3  0x00ffffff96462c2a in ds_ipc_stream_factory_get_next_available_stream (callback=0xffffff964667f4 <server_warning_callback>) at /runtime/src/native/eventpipe/ds-ipc.c:395
#4  0x00ffffff96460de2 in server_thread (data=0xaaaaaae9a9a100) at /runtime/src/native/eventpipe/ds-server.c:127
#5  0x00ffffff9646676a in ep_rt_thread_mono_start_func (data=0xaaaaaae9a9a100) at /runtime/src/mono/mono/mini/../eventpipe/ep-rt-mono.h:1341
#6  0x00ffffff96b1b5fa in start_thread (arg=<optimized out>) at pthread_create.c:481
#7  0x00ffffff968380b2 in __thread_start () at ../sysdeps/unix/sysv/linux/riscv/clone.S:82

Thread 2 (Thread 0xffffff957ff130 (LWP 321) "SGen worker"):
#0  0x00ffffff96b24e74 in __futex_abstimed_wait_common64 (futex_word=futex_word@entry=0xffffff96490680 <work_cond+40>, expected=<optimized out>, clockid=<optimized out>, abstime=abstime@entry=0x0, private=<optimized out>, cancel=cancel@entry=true) at ../sysdeps/nptl/futex-internal.c:74
#1  0x00ffffff96b24e8a in __GI___futex_abstimed_wait_cancelable64 (futex_word=futex_word@entry=0xffffff96490680 <work_cond+40>, expected=expected@entry=0, clockid=clockid@entry=0, abstime=abstime@entry=0x0, private=private@entry=0) at ../sysdeps/nptl/futex-internal.c:123
#2  0x00ffffff96b2024a in __pthread_cond_wait_common (abstime=0x0, clockid=0, mutex=0xffffff96490630 <lock>, cond=0xffffff96490658 <work_cond>) at pthread_cond_wait.c:504
#3  __pthread_cond_wait (cond=0xffffff96490658 <work_cond>, mutex=0xffffff96490630 <lock>) at pthread_cond_wait.c:619
#4  0x00ffffff9624024e in mono_os_cond_wait (cond=0xffffff96490658 <work_cond>, mutex=0xffffff96490630 <lock>) at /runtime/src/mono/mono/mini/../../mono/utils/mono-os-mutex.h:219
#5  0x00ffffff96240cb0 in get_work (worker_index=0, work_context=0xffffff957fe830, do_idle=0xffffff957fe824, job=0xffffff957fe818) at /runtime/src/mono/mono/sgen/sgen-thread-pool.c:167
#6  0x00ffffff9623fdf2 in thread_func (data=0x0) at /runtime/src/mono/mono/sgen/sgen-thread-pool.c:198
#7  0x00ffffff96b1b5fa in start_thread (arg=<optimized out>) at pthread_create.c:481
#8  0x00ffffff968380b2 in __thread_start () at ../sysdeps/unix/sysv/linux/riscv/clone.S:82

Thread 1 (Thread 0xffffff96790010 (LWP 320) "dotnet"):
#0  0x00ffffff96816bf0 in __GI___wait4 (pid=<optimized out>, stat_loc=0xfffffff8f05fbc, options=<optimized out>, usage=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1  0x00ffffff96397ea4 in dump_native_stacktrace (signal=0xffffff96040cb2 "SIGABRT", mctx=0xfffffff8f06b50) at /runtime/src/mono/mono/mini/mini-posix.c:843
#2  0x00ffffff96397b4a in sampling_thread_func (unused=0xffffff96040cb2) at /runtime/src/mono/mono/mini/mini-posix.c:870
#3  0x00ffffff96346928 in mono_handle_native_crash (signal=0xffffff96040cb2 "SIGABRT", mctx=0xfffffff8f06b50, info=0xfffffff8f06e90) at /runtime/src/mono/mono/mini/mini-exceptions.c:3000
#4  0x00ffffff96397396 in sigabrt_signal_handler (_dummy=6, _info=0xfffffff8f06e90, context=0xfffffff8f06f10) at /runtime/src/mono/mono/mini/mini-posix.c:225
#5  <signal handler called>
#6  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
#7  0x00ffffff967b463c in __GI_abort () at abort.c:79
#8  0x00ffffff963f5c2e in monoeg_assert_abort () at /runtime/src/mono/mono/eglib/goutput.c:57
#9  0x00ffffff961ac9ae in mono_log_write_logfile (log_domain=0x0, level=G_LOG_LEVEL_ERROR, hdr=0, message=0xaaaaaae9a9fad0 "* Assertion: should not be reached at /runtime/src/mono/mono/mini/mini-riscv.c:454\n") at /runtime/src/mono/mono/utils/mono-log-common.c:146
#10 0x00ffffff961a9834 in structured_log_adapter (log_domain=0x0, log_level=G_LOG_LEVEL_ERROR, message=0xaaaaaae9a9fad0 "* Assertion: should not be reached at /runtime/src/mono/mono/mini/mini-riscv.c:454\n", user_data=0x0) at /runtime/src/mono/mono/utils/mono-logger.c:461
#11 0x00ffffff963f62ba in monoeg_g_logstr (log_domain=0x0, log_level=G_LOG_LEVEL_ERROR, msg=0xaaaaaae9a9fad0 "* Assertion: should not be reached at /runtime/src/mono/mono/mini/mini-riscv.c:454\n") at /runtime/src/mono/mono/eglib/goutput.c:151
#12 0x00ffffff963f5f34 in monoeg_g_logv_nofree (log_domain=0x0, log_level=G_LOG_LEVEL_ERROR, format=0xffffff96057de9 "* Assertion: should not be reached at %s:%d\n", args=0xfffffff8f07728) at /runtime/src/mono/mono/eglib/goutput.c:166
#13 0x00ffffff963f6022 in monoeg_assertion_message (format=0xffffff96057de9 "* Assertion: should not be reached at %s:%d\n") at /runtime/src/mono/mono/eglib/goutput.c:207
#14 0x00ffffff963f60aa in mono_assertion_message_unreachable (file=0xffffff9603cf3f "/runtime/src/mono/mono/mini/mini-riscv.c", line=454) at /runtime/src/mono/mono/eglib/goutput.c:234
#15 0x00ffffff9639533e in mono_arch_create_vars (cfg=0xaaaaaae9aa0c00) at /runtime/src/mono/mono/mini/mini-riscv.c:454
#16 0x00ffffff9625aa7c in mono_compile_create_vars (cfg=0xaaaaaae9aa0c00) at /runtime/src/mono/mono/mini/mini.c:1947
#17 0x00ffffff96258ea4 in mini_method_compile (method=0xaaaaaae9a9e788, opts=370223615, flags=JIT_FLAG_RUN_CCTORS, parts=0, aot_method_index=-1) at /runtime/src/mono/mono/mini/mini.c:3469
#18 0x00ffffff9625d548 in mono_jit_compile_method_inner (method=0xaaaaaae9a9e788, opt=374417919, error=0xfffffff8f086d0) at /runtime/src/mono/mono/mini/mini.c:4109
#19 0x00ffffff9626a026 in mono_jit_compile_method_with_opt (method=0xaaaaaae9a9e788, opt=374417919, jit_only=1, error=0xfffffff8f086d0) at /runtime/src/mono/mono/mini/mini-runtime.c:2707
#20 0x00ffffff96269906 in jit_compile_method_with_opt_cb (arg=0xfffffff8f08220) at /runtime/src/mono/mono/mini/mini-runtime.c:2762
#21 0x00ffffff962634c0 in jit_compile_method_with_opt (params=0xfffffff8f08220) at /runtime/src/mono/mono/mini/mini-runtime.c:2778
#22 0x00ffffff96263550 in mono_jit_compile_method_jit_only (method=0xaaaaaae9a9e788, error=0xfffffff8f086d0) at /runtime/src/mono/mono/mini/mini-runtime.c:2816
#23 0x00ffffff96265fde in mono_jit_runtime_invoke (method=0xaaaaaae9a9e788, obj=0xffffff95800048, params=0xfffffff8f08440, exc=0x0, error=0xfffffff8f086d0) at /runtime/src/mono/mono/mini/mini-runtime.c:3402
#24 0x00ffffff96121138 in do_runtime_invoke (method=0xaaaaaae9a9e788, obj=0xffffff95800048, params=0xfffffff8f08440, exc=0x0, error=0xfffffff8f086d0) at /runtime/src/mono/mono/metadata/object.c:2415
#25 0x00ffffff9611c430 in mono_runtime_invoke_checked (method=0xaaaaaae9a9e788, obj=0xffffff95800048, params=0xfffffff8f08440, error=0xfffffff8f086d0) at /runtime/src/mono/mono/metadata/object.c:2583
#26 0x00ffffff9611c4aa in mono_runtime_invoke_handle_void (method=0xaaaaaae9a9e788, obj=..., params=0xfffffff8f08440, error=0xfffffff8f086d0) at /runtime/src/mono/mono/metadata/object.c:2595
#27 0x00ffffff960b76fe in create_exception_two_strings (klass=0xaaaaaae9a9df68, a1=..., a2=..., error=0xfffffff8f086d0) at /runtime/src/mono/mono/metadata/exception.c:176
#28 0x00ffffff960b7416 in mono_exception_from_name_two_strings_checked (image=0xaaaaaae9a24450, name_space=0xffffff9603b75d "System", name=0xffffff96043f50 "OutOfMemoryException", a1=..., a2=..., error=0xfffffff8f086d0) at /runtime/src/mono/mono/metadata/exception.c:236
#29 0x00ffffff96083b1e in create_domain_objects (domain=0xaaaaaae9a20250) at /runtime/src/mono/mono/metadata/appdomain.c:192
#30 0x00ffffff96083352 in mono_runtime_init_checked (domain=0xaaaaaae9a20250, start_cb=0xffffff96268b00 <mono_thread_start_cb>, attach_cb=0xffffff96268b62 <mono_thread_attach_cb>, error=0xfffffff8f089c8) at /runtime/src/mono/mono/metadata/appdomain.c:288
#31 0x00ffffff962655c8 in mini_init (filename=0xaaaaaae99e6dd0 "/root/console22/bin/Debug/net7.0/console22.dll") at /runtime/src/mono/mono/mini/mini-runtime.c:4722
#32 0x00ffffff96303d26 in mono_main (argc=2, argv=0xaaaaaae9a0a920) at /runtime/src/mono/mono/mini/driver.c:2547
#33 0x00ffffff9639407c in monovm_execute_assembly (argc=0, argv=0x0, managedAssemblyPath=0xaaaaaae99e6dd0 "/root/console22/bin/Debug/net7.0/console22.dll", exitCode=0xfffffff8f08f04) at /runtime/src/mono/mono/mini/monovm.c:268
#34 0x00ffffff9625298c in coreclr_execute_assembly (hostHandle=0xcebadc92f2ece00, domainId=16777215, argc=0, argv=0x0, managedAssemblyPath=0xaaaaaae99e6dd0 "/root/console22/bin/Debug/net7.0/console22.dll", exitCode=0xfffffff8f08f04) at /runtime/src/mono/mono/mini/main-core.c:81
#35 0x00ffffff966b16c0 in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/shared/Microsoft.NETCore.App/7.0.0/libhostpolicy.so
#36 0x00ffffff966c8146 in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/shared/Microsoft.NETCore.App/7.0.0/libhostpolicy.so
#37 0x00ffffff966c8310 in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/shared/Microsoft.NETCore.App/7.0.0/libhostpolicy.so
#38 0x00ffffff966c8d30 in corehost_main () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/shared/Microsoft.NETCore.App/7.0.0/libhostpolicy.so
#39 0x00ffffff9674b63a in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/host/fxr/7.0.0/libhostfxr.so
#40 0x00ffffff9674ae8a in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/host/fxr/7.0.0/libhostfxr.so
#41 0x00ffffff967485fc in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/host/fxr/7.0.0/libhostfxr.so
#42 0x00ffffff96747af2 in ?? () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/host/fxr/7.0.0/libhostfxr.so
#43 0x00ffffff967421a4 in hostfxr_main_startupinfo () from /root/runtime/artifacts/bin/testhost/net7.0-Linux-Debug-riscv64/host/fxr/7.0.0/libhostfxr.so
#44 0x00aaaaaabb0856c2 in ?? ()
#45 0x00aaaaaabb0859c4 in ?? ()
#46 0x00ffffff967b4808 in __libc_start_main (main=0xaaaaaabb085910, argc=<optimized out>, argv=0xfffffff8f09ba8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=<optimized out>) at libc-start.c:332
#47 0x00aaaaaabb07af88 in ?? ()
[Inferior 1 (process 320) detached]

=================================================================
    Basic Fault Address Reporting
=================================================================
Memory around native instruction pointer (0xffffff967c3c54):0xffffff967c3c44  93 08 70 08 09 45 ba 85 01 46 a1 46 73 00 00 00  ..p..E...F.Fs...
0xffffff967c3c54  b2 66 03 37 03 00 63 90 e6 02 f2 60 3e 85 15 61  .f.7..c....`>..a
0xffffff967c3c64  82 80 97 96 0d 00 83 b6 26 98 3b 05 a0 40 fd 57  ........&.;..@.W
0xffffff967c3c74  92 96 88 c2 f1 b7 ef e0 f7 76 63 45 05 00 3b 05  .........vcE..;.

=================================================================
    Managed Stacktrace:
=================================================================
      at <unknown> <0xffffffff>
* Assertion: should not be reached at /runtime/src/mono/mono/mini/exceptions-riscv.c:209
am11 commented 2 years ago

cc @alexrp, @vargaz

teo-tsirpanis commented 2 years ago

We need an arch-riscv label.

SamMonoRT commented 2 years ago

cc @lambdageek @directhex

lambdageek commented 2 years ago

Related to https://github.com/dotnet/runtime/issues/36748

am11 commented 2 years ago

Sorry @alexp, I meant to copy @alexrp :slightly_smiling_face:

alexrp commented 2 years ago

there are ~50 functions that need implementation

You're basically looking at doing a Mini JIT port. What is implemented is just enough to make the backend compile, along with some supporting functionality like codegen macros and hardware feature detection. All the hard stuff hasn't actually been done yet. It's a substantial undertaking that, realistically, would probably require a company willing to fund full-time development.

If you just want something semi-functional but not fast, running with the interpreter might be an option.

archanox commented 2 years ago

Would an interpreted RISC-V implementation be accepted upstream @alexrp?

alexrp commented 2 years ago

I have no say on such matters. All I can tell you is that Mono's interpreter is fully productized and supported, while CoreCLR's is just used for bringup on new platforms and isn't really meant to be fully compliant/usable. So I would expect that RISC-V patches for Mono's interpreter are welcome at least.