File riscv.patch of Package mono-core
From 2921130fa84b24287e6144d015b7010902cb18c2 Mon Sep 17 00:00:00 2001
From: Bernhard Urban-Forster <lewurm@gmail.com>
Date: Fri, 31 Jul 2020 01:20:45 +0200
Subject: [PATCH] [RISCV] Build fixes and simple exception handling (#20184)
* [riscv] add ELF machine definition
* [riscv] add mono_arch_get_cie_program to fix the build
* [interp] remove unused pointer
* [riscv] add offsets for MonoContext members
* [riscv] add pattern to nop_stub, so it is easier to spot in the debugger what caused the hang
* [riscv] minimal exception handling support
---
mono/metadata/object-offsets.h | 3 +
mono/mini/exceptions-riscv.c | 116 ++++++++++++++++++++++++++++----
mono/mini/interp/interp.c | 3 -
mono/mini/mini-riscv.c | 10 +++
mono/mini/mini-runtime.c | 2 +
mono/utils/freebsd-elf_common.h | 1 +
6 files changed, 119 insertions(+), 16 deletions(-)
Index: mono-6.12.0.107/mono/metadata/object-offsets.h
===================================================================
--- mono-6.12.0.107.orig/mono/metadata/object-offsets.h
+++ mono-6.12.0.107/mono/metadata/object-offsets.h
@@ -233,6 +233,9 @@ DECL_OFFSET(DynCallArgs, fpregs)
DECL_OFFSET(DynCallArgs, n_stackargs)
DECL_OFFSET(DynCallArgs, n_fpargs)
DECL_OFFSET(DynCallArgs, n_fpret)
+#elif defined(TARGET_RISCV)
+DECL_OFFSET(MonoContext, gregs)
+DECL_OFFSET(MonoContext, fregs)
#endif
// Shared architecture offfsets
Index: mono-6.12.0.107/mono/mini/exceptions-riscv.c
===================================================================
--- mono-6.12.0.107.orig/mono/mini/exceptions-riscv.c
+++ mono-6.12.0.107/mono/mini/exceptions-riscv.c
@@ -13,14 +13,15 @@
#ifndef DISABLE_JIT
static gpointer
-nop_stub (void)
+nop_stub (unsigned int pattern)
{
guint8 *code, *start;
start = code = mono_global_codeman_reserve (0x50);
- /* nop */
- riscv_addi (code, RISCV_X0, RISCV_X0, 0);
+ /* hang in debugger */
+ riscv_addi (code, RISCV_X0, RISCV_X0, pattern);
+ riscv_ebreak (code);
mono_arch_flush_icache (start, code - start);
@@ -30,43 +31,76 @@ nop_stub (void)
gpointer
mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
{
- *info = NULL;
- return nop_stub ();
+ guint8 *start, *code;
+ MonoJumpInfo *ji = NULL;
+ GSList *unwind_ops = NULL;
+ int i, ctx_reg, size;
+
+ size = 512;
+ code = start = mono_global_codeman_reserve (size);
+
+ riscv_addi (code, RISCV_T0, RISCV_A0, 0);
+ ctx_reg = RISCV_T0;
+
+ /* Restore fregs */
+ for (i = 0; i < RISCV_N_FREGS; ++i)
+ riscv_flw (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * sizeof (double)));
+
+ /* Restore gregs */
+ for (i = 0; i < RISCV_N_FREGS; ++i) {
+ if (i == ctx_reg)
+ continue;
+ riscv_ld (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, gregs) + (i * sizeof (double)));
+ }
+
+ riscv_ld (code, ctx_reg, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, gregs) + (RISCV_ZERO * sizeof (double)));
+ riscv_jalr (code, RISCV_ZERO, ctx_reg, 0);
+ /* Not reached */
+ riscv_ebreak (code);
+
+ g_assert ((code - start) < size);
+ mono_arch_flush_icache (start, code - start);
+ MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
+
+ if (info)
+ *info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
+
+ return start;
}
gpointer
mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
{
*info = NULL;
- return nop_stub ();
+ return nop_stub (0x37);
}
gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
*info = NULL;
- return nop_stub ();
+ return nop_stub (0x77);
}
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
{
*info = NULL;
- return nop_stub ();
+ return nop_stub (0x88);
}
gpointer
mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
{
*info = NULL;
- return nop_stub ();
+ return nop_stub (0x99);
}
gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
*info = NULL;
- return nop_stub ();
+ return nop_stub (0xaa);
}
#else
@@ -126,7 +160,63 @@ mono_arch_unwind_frame (MonoDomain *doma
MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf,
host_mgreg_t **save_locations, StackFrameInfo *frame)
{
- NOT_IMPLEMENTED;
+ gpointer ip = MONO_CONTEXT_GET_IP (ctx);
+
+ memset (frame, 0, sizeof (StackFrameInfo));
+ frame->ji = ji;
+
+ *new_ctx = *ctx;
+
+ if (ji != NULL) {
+ NOT_IMPLEMENTED;
+ host_mgreg_t regs [MONO_MAX_IREGS + 12 + 1];
+ guint8 *cfa;
+ guint32 unwind_info_len;
+ guint8 *unwind_info;
+
+
+ if (ji->is_trampoline)
+ frame->type = FRAME_TYPE_TRAMPOLINE;
+ else
+ frame->type = FRAME_TYPE_MANAGED;
+
+ unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
+
+ memcpy (regs, &new_ctx->gregs, sizeof (host_mgreg_t) * 32);
+
+ /* f8..f9 & f18..f27 are callee saved */
+ for (int i = 0; i < 2; i++)
+ (regs + MONO_MAX_IREGS) [i] = *((host_mgreg_t*)&new_ctx->fregs [RISCV_F8 + i]);
+ for (int i = 0; i < 10; i++)
+ (regs + MONO_MAX_IREGS) [i] = *((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]);
+
+ gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8*)ji->code_start,
+ (guint8*)ji->code_start + ji->code_size,
+ (guint8*)ip, NULL, regs, MONO_MAX_IREGS + 8,
+ save_locations, MONO_MAX_IREGS, (guint8**)&cfa);
+
+ if (!success)
+ return FALSE;
+
+ memcpy (&new_ctx->gregs, regs, sizeof (host_mgreg_t) * 32);
+ for (int i = 0; i < 2; i++)
+ *((host_mgreg_t*)&new_ctx->fregs [RISCV_F8 + i]) = (regs + MONO_MAX_IREGS) [i];
+ for (int i = 0; i < 10; i++)
+ *((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]) = (regs + MONO_MAX_IREGS) [i];
+
+ new_ctx->gregs [RISCV_SP] = (host_mgreg_t)(gsize)cfa;
+
+ if (*lmf)
+ NOT_IMPLEMENTED;
+
+ /* we substract 1, so that the IP points into the call instruction */
+ new_ctx->gregs [RISCV_ZERO]--;
+
+ return TRUE;
+ } else if (*lmf) {
+ NOT_IMPLEMENTED;
+ }
+
return FALSE;
}
@@ -178,11 +268,11 @@ mono_arch_setup_resume_sighandler_ctx (M
void
mono_arch_undo_ip_adjustment (MonoContext *context)
{
- NOT_IMPLEMENTED;
+ context->gregs[RISCV_ZERO]++;
}
void
mono_arch_do_ip_adjustment (MonoContext *context)
{
- g_assert_not_reached ();
+ context->gregs[RISCV_ZERO]--;
}
Index: mono-6.12.0.107/mono/mini/mini-riscv.c
===================================================================
--- mono-6.12.0.107.orig/mono/mini/mini-riscv.c
+++ mono-6.12.0.107/mono/mini/mini-riscv.c
@@ -239,6 +239,16 @@ mono_arch_find_static_call_vtable (host_
return (MonoVTable *) regs [MONO_ARCH_VTABLE_REG];
}
+GSList*
+mono_arch_get_cie_program (void)
+{
+ GSList *l = NULL;
+
+ mono_add_unwind_op_def_cfa (l, (guint8*)NULL, (guint8*)NULL, RISCV_SP, 0);
+
+ return l;
+}
+
host_mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
Index: mono-6.12.0.107/mono/utils/freebsd-elf_common.h
===================================================================
--- mono-6.12.0.107.orig/mono/utils/freebsd-elf_common.h
+++ mono-6.12.0.107/mono/utils/freebsd-elf_common.h
@@ -169,6 +169,7 @@ typedef struct {
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_RISCV 243 /* RISC-V. */
/* Non-standard or deprecated. */
#define EM_486 6 /* Intel i486. */