diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index 7ae283d7c10302..1535b7a387f788 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -161,6 +161,8 @@ else() message(FATAL_ERROR "Unsupported platform. OS: ${CMAKE_SYSTEM_NAME}, arch: ${TARGET_ARCH_NAME}") endif() -if(TARGET_ARCH_NAME MATCHES "^(x86|x64|s390x|armv6|loongarch64|riscv64|ppc64le)$") +if(TARGET_ARCH_NAME MATCHES "^(x86|x64|s390x|armv6|loongarch64|ppc64le)$") set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) +elseif (TARGET_ARCH_NAME STREQUAL "riscv64") + set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 1) endif() diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index b5db55688e43a9..eec103af880f11 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -3,7 +3,7 @@ #include "createdump.h" -#if defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) +#if defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) || defined(__riscv) long g_pageSize = 0; #endif @@ -19,7 +19,7 @@ CreateDump(const CreateDumpOptions& options) bool result = false; // Initialize PAGE_SIZE -#if defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) +#if defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) || defined(__riscv) g_pageSize = sysconf(_SC_PAGESIZE); #endif TRACE("PAGE_SIZE %d\n", PAGE_SIZE); diff --git a/src/coreclr/debug/createdump/datatarget.cpp b/src/coreclr/debug/createdump/datatarget.cpp index 7ef154e034c8e2..0bf0ed23c66c5c 100644 --- a/src/coreclr/debug/createdump/datatarget.cpp +++ b/src/coreclr/debug/createdump/datatarget.cpp @@ -77,6 +77,8 @@ DumpDataTarget::GetMachineType( *machine = IMAGE_FILE_MACHINE_I386; #elif HOST_LOONGARCH64 *machine = IMAGE_FILE_MACHINE_LOONGARCH64; +#elif HOST_RISCV64 + *machine = IMAGE_FILE_MACHINE_RISCV64; #else #error Unsupported architecture #endif @@ -87,7 +89,7 @@ HRESULT STDMETHODCALLTYPE DumpDataTarget::GetPointerSize( /* [out] */ ULONG32 *size) { -#if defined(HOST_AMD64) || defined(HOST_ARM64) || defined(HOST_LOONGARCH64) +#if defined(HOST_AMD64) || defined(HOST_ARM64) || defined(HOST_LOONGARCH64) || defined(HOST_RISCV64) *size = 8; #elif defined(HOST_ARM) || defined(HOST_X86) *size = 4; diff --git a/src/coreclr/debug/createdump/dumpwriterelf.h b/src/coreclr/debug/createdump/dumpwriterelf.h index 425d0b9214c3e1..bfc5ae15c147a1 100644 --- a/src/coreclr/debug/createdump/dumpwriterelf.h +++ b/src/coreclr/debug/createdump/dumpwriterelf.h @@ -23,6 +23,8 @@ #define ELF_ARCH EM_ARM #elif defined(__loongarch64) #define ELF_ARCH EM_LOONGARCH +#elif defined(__riscv) +#define ELF_ARCH EM_RISCV #endif #define PH_HDR_CANARY 0xFFFF diff --git a/src/coreclr/debug/createdump/memoryregion.h b/src/coreclr/debug/createdump/memoryregion.h index f4c115d539b476..e7b8f31a0b2692 100644 --- a/src/coreclr/debug/createdump/memoryregion.h +++ b/src/coreclr/debug/createdump/memoryregion.h @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if !defined(PAGE_SIZE) && (defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)) +#if !defined(PAGE_SIZE) && (defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)) || defined(__riscv) extern long g_pageSize; #define PAGE_SIZE g_pageSize #endif diff --git a/src/coreclr/debug/createdump/threadinfo.h b/src/coreclr/debug/createdump/threadinfo.h index 4600dccb50911e..0945233b9f6b4f 100644 --- a/src/coreclr/debug/createdump/threadinfo.h +++ b/src/coreclr/debug/createdump/threadinfo.h @@ -20,6 +20,14 @@ class CrashInfo; #define MCREG_Pc(mc) ((mc).pc) #endif +#if defined(__riscv) +// See src/coreclr/pal/src/include/pal/context.h +#define MCREG_Ra(mc) ((mc).ra) +#define MCREG_Fp(mc) ((mc).s0) +#define MCREG_Sp(mc) ((mc).sp) +#define MCREG_Pc(mc) ((mc).pc) +#endif + #define FPREG_ErrorOffset(fpregs) *(DWORD*)&((fpregs).rip) #define FPREG_ErrorSelector(fpregs) *(((WORD*)&((fpregs).rip)) + 2) #define FPREG_DataOffset(fpregs) *(DWORD*)&((fpregs).rdp) @@ -30,6 +38,12 @@ class CrashInfo; #elif defined(__loongarch64) // struct user_regs_struct {} defined `/usr/include/loongarch64-linux-gnu/sys/user.h` +struct user_fpregs_struct +{ + unsigned long long fpregs[32]; + unsigned long fpscr; +} __attribute__((__packed__)); +#elif defined(__riscv) struct user_fpregs_struct { unsigned long long fpregs[32]; @@ -154,6 +168,10 @@ class ThreadInfo inline const uint64_t GetInstructionPointer() const { return m_gpRegisters.ARM_pc; } inline const uint64_t GetStackPointer() const { return m_gpRegisters.ARM_sp; } inline const uint64_t GetFramePointer() const { return m_gpRegisters.ARM_fp; } +#elif defined(__riscv) + inline const uint64_t GetInstructionPointer() const { return MCREG_Pc(m_gpRegisters); } + inline const uint64_t GetStackPointer() const { return MCREG_Sp(m_gpRegisters); } + inline const uint64_t GetFramePointer() const { return MCREG_Fp(m_gpRegisters); } #endif #endif // __APPLE__ bool IsCrashThread() const; diff --git a/src/coreclr/debug/createdump/threadinfounix.cpp b/src/coreclr/debug/createdump/threadinfounix.cpp index c9ccc7f37d9a67..ca75a6128fee9e 100644 --- a/src/coreclr/debug/createdump/threadinfounix.cpp +++ b/src/coreclr/debug/createdump/threadinfounix.cpp @@ -59,6 +59,8 @@ ThreadInfo::Initialize() TRACE("Thread %04x RIP %016llx RSP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.rip, (unsigned long long)m_gpRegisters.rsp); #elif defined(__loongarch64) TRACE("Thread %04x PC %016llx SP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.pc, (unsigned long long)m_gpRegisters.gpr[3]); +#elif defined(__riscv) + TRACE("Thread %04x PC %016llx SP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.pc, (unsigned long long)m_gpRegisters.sp); #else #error "Unsupported architecture" #endif @@ -243,6 +245,8 @@ ThreadInfo::GetThreadContext(uint32_t flags, CONTEXT* context) const memcpy(context->F, m_fpRegisters.fpregs, sizeof(context->F)); context->Fcsr = m_fpRegisters.fpscr; } +#elif defined(__riscv) + _ASSERTE(!"TODO RISCV64 NYI"); #else #error Platform not supported #endif diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index a69dfdabb2d41c..aa0c739eeac395 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -5450,6 +5450,8 @@ ClrDataAccess::Initialize(void) CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_ARM64; #elif defined(TARGET_LOONGARCH64) CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; + #elif defined(TARGET_RISCV64) + CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_RISCV64; #else #error Unknown Processor. #endif diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index d89aa05795ffab..ca33ce1b6f4010 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -559,6 +559,18 @@ ClrDataAccess::GetRegisterName(int regNum, unsigned int count, _Inout_updates_z_ W("S6"), W("S7"), W("K0"), W("K1"), W("GP"), W("SP"), W("FP"), W("RA") }; +#elif defined(TARGET_RISCV64) + static const WCHAR *regs[] = + { + W("R0"), W("RA"), W("SP"), W("GP"), + W("TP"), W("T0"), W("T1"), W("T2"), + W("FP"), W("S1"), W("A0"), W("A1"), + W("A2"), W("A3"), W("A4"), W("A5"), + W("A6"), W("A7"), W("S2"), W("S3"), + W("S4"), W("S5"), W("S6"), W("S7"), + W("S8"), W("S9"), W("S10"), W("S11"), + W("T3"), W("T4"), W("T5"), W("T6") + }; #endif // Caller frame registers are encoded as "-(reg+1)". diff --git a/src/coreclr/debug/di/CMakeLists.txt b/src/coreclr/debug/di/CMakeLists.txt index 9d84f90b1a5c6a..b5f6872b8f690a 100644 --- a/src/coreclr/debug/di/CMakeLists.txt +++ b/src/coreclr/debug/di/CMakeLists.txt @@ -66,7 +66,7 @@ if(CLR_CMAKE_HOST_WIN32) endif() elseif(CLR_CMAKE_HOST_UNIX) - if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64) + if(CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64 OR CLR_CMAKE_TARGET_ARCH_RISCV64) set(CORDBDI_SOURCES_ASM_FILE ${ARCH_SOURCES_DIR}/floatconversion.S ) diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index d62659291ec7e1..15fae1581e2bff 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -4872,6 +4872,8 @@ int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) _ASSERTE(!"Invalid opcode!"); return -1; +#elif defined(TARGET_RISCV64) + return MAX_INSTRUCTION_LENGTH; #else #error Platform not implemented #endif diff --git a/src/coreclr/debug/di/platformspecific.cpp b/src/coreclr/debug/di/platformspecific.cpp index 2dbdbd2a407056..cd690dccc2fd25 100644 --- a/src/coreclr/debug/di/platformspecific.cpp +++ b/src/coreclr/debug/di/platformspecific.cpp @@ -36,6 +36,9 @@ #elif TARGET_LOONGARCH64 #include "loongarch64/cordbregisterset.cpp" #include "loongarch64/primitives.cpp" +#elif TARGET_RISCV64 +#include "riscv64/cordbregisterset.cpp" +#include "riscv64/primitives.cpp" #else #error Unsupported platform #endif diff --git a/src/coreclr/debug/di/riscv64/cordbregisterset.cpp b/src/coreclr/debug/di/riscv64/cordbregisterset.cpp new file mode 100644 index 00000000000000..7a80fd91dee26f --- /dev/null +++ b/src/coreclr/debug/di/riscv64/cordbregisterset.cpp @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: CordbRegisterSet.cpp +// + +// +//***************************************************************************** +#include "primitives.h" + + +HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG64* pAvailable) +{ + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pAvailable, ULONG64 *); + + *pAvailable = SETBITULONG64(REGISTER_RISCV64_PC) + | SETBITULONG64(REGISTER_RISCV64_RA) + | SETBITULONG64(REGISTER_RISCV64_SP) + | SETBITULONG64(REGISTER_RISCV64_GP) + | SETBITULONG64(REGISTER_RISCV64_TP) + | SETBITULONG64(REGISTER_RISCV64_T0) + | SETBITULONG64(REGISTER_RISCV64_T1) + | SETBITULONG64(REGISTER_RISCV64_T2) + | SETBITULONG64(REGISTER_RISCV64_FP) + | SETBITULONG64(REGISTER_RISCV64_S1) + | SETBITULONG64(REGISTER_RISCV64_A0) + | SETBITULONG64(REGISTER_RISCV64_A1) + | SETBITULONG64(REGISTER_RISCV64_A2) + | SETBITULONG64(REGISTER_RISCV64_A3) + | SETBITULONG64(REGISTER_RISCV64_A4) + | SETBITULONG64(REGISTER_RISCV64_A5) + | SETBITULONG64(REGISTER_RISCV64_A6) + | SETBITULONG64(REGISTER_RISCV64_A7) + | SETBITULONG64(REGISTER_RISCV64_S2) + | SETBITULONG64(REGISTER_RISCV64_S3) + | SETBITULONG64(REGISTER_RISCV64_S4) + | SETBITULONG64(REGISTER_RISCV64_S5) + | SETBITULONG64(REGISTER_RISCV64_S6) + | SETBITULONG64(REGISTER_RISCV64_S7) + | SETBITULONG64(REGISTER_RISCV64_S8) + | SETBITULONG64(REGISTER_RISCV64_S9) + | SETBITULONG64(REGISTER_RISCV64_S10) + | SETBITULONG64(REGISTER_RISCV64_S11) + | SETBITULONG64(REGISTER_RISCV64_T3) + | SETBITULONG64(REGISTER_RISCV64_T4) + | SETBITULONG64(REGISTER_RISCV64_T5) + | SETBITULONG64(REGISTER_RISCV64_T6) + | SETBITULONG64(REGISTER_RISCV64_F0) + | SETBITULONG64(REGISTER_RISCV64_F1) + | SETBITULONG64(REGISTER_RISCV64_F2) + | SETBITULONG64(REGISTER_RISCV64_F3) + | SETBITULONG64(REGISTER_RISCV64_F4) + | SETBITULONG64(REGISTER_RISCV64_F5) + | SETBITULONG64(REGISTER_RISCV64_F6) + | SETBITULONG64(REGISTER_RISCV64_F7) + | SETBITULONG64(REGISTER_RISCV64_F8) + | SETBITULONG64(REGISTER_RISCV64_F9) + | SETBITULONG64(REGISTER_RISCV64_F10) + | SETBITULONG64(REGISTER_RISCV64_F11) + | SETBITULONG64(REGISTER_RISCV64_F12) + | SETBITULONG64(REGISTER_RISCV64_F13) + | SETBITULONG64(REGISTER_RISCV64_F14) + | SETBITULONG64(REGISTER_RISCV64_F15) + | SETBITULONG64(REGISTER_RISCV64_F16) + | SETBITULONG64(REGISTER_RISCV64_F17) + | SETBITULONG64(REGISTER_RISCV64_F18) + | SETBITULONG64(REGISTER_RISCV64_F19) + | SETBITULONG64(REGISTER_RISCV64_F20) + | SETBITULONG64(REGISTER_RISCV64_F21) + | SETBITULONG64(REGISTER_RISCV64_F22) + | SETBITULONG64(REGISTER_RISCV64_F23) + | SETBITULONG64(REGISTER_RISCV64_F24) + | SETBITULONG64(REGISTER_RISCV64_F25) + | SETBITULONG64(REGISTER_RISCV64_F26) + | SETBITULONG64(REGISTER_RISCV64_F27) + | SETBITULONG64(REGISTER_RISCV64_F28) + | SETBITULONG64(REGISTER_RISCV64_F29) + | SETBITULONG64(REGISTER_RISCV64_F30) + | SETBITULONG64(REGISTER_RISCV64_F31); + + return S_OK; +} + +HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount, + CORDB_REGISTER regBuffer[]) +{ + _ASSERTE(!"RISCV64:NYI"); + return S_OK; +} + + +HRESULT CordbRegisterSet::GetRegistersAvailable(ULONG32 regCount, + BYTE pAvailable[]) +{ + _ASSERTE(!"RISCV64:NYI"); + return S_OK; +} + + +HRESULT CordbRegisterSet::GetRegisters(ULONG32 maskCount, BYTE mask[], + ULONG32 regCount, CORDB_REGISTER regBuffer[]) +{ + _ASSERTE(!"RISCV64:NYI"); + return S_OK; +} + + +// This is just a convenience function to convert a regdisplay into a Context. +// Since a context has more info than a regdisplay, the conversion isn't perfect +// and the context can't be fully accurate. +void CordbRegisterSet::InternalCopyRDToContext(DT_CONTEXT *pInputContext) +{ + _ASSERTE(!"RISCV64:NYI"); +} diff --git a/src/coreclr/debug/di/riscv64/floatconversion.S b/src/coreclr/debug/di/riscv64/floatconversion.S new file mode 100644 index 00000000000000..138db0bc9dd243 --- /dev/null +++ b/src/coreclr/debug/di/riscv64/floatconversion.S @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + +// Arguments +// input: (in A0) the address of the ULONGLONG to be converted to a double +// output: the double corresponding to the ULONGLONG input value +LEAF_ENTRY FPFillR8, .TEXT + fld fa0, 0(a0) + ret +LEAF_END FPFillR8, .TEXT diff --git a/src/coreclr/pal/src/arch/riscv64/activationhandlerwrapper.S b/src/coreclr/debug/di/riscv64/primitives.cpp similarity index 57% rename from src/coreclr/pal/src/arch/riscv64/activationhandlerwrapper.S rename to src/coreclr/debug/di/riscv64/primitives.cpp index a7cd5b6c4d2403..97b053a8d3e9c6 100644 --- a/src/coreclr/pal/src/arch/riscv64/activationhandlerwrapper.S +++ b/src/coreclr/debug/di/riscv64/primitives.cpp @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#include "unixasmmacros.inc" -#include "asmconstants.h" +// -#error "TODO-RISCV64: missing implementation" +#include "../../shared/riscv64/primitives.cpp" diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 075ed936fed530..5a2ea695ebc84c 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -8331,6 +8331,9 @@ HRESULT CordbJITILFrame::GetNativeVariable(CordbType *type, #elif defined(TARGET_LOONGARCH64) hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_LOONGARCH64_F0, type, ppValue); +#elif defined(TARGET_RISCV64) + hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_RISCV64_F0, + type, ppValue); #else #error Platform not implemented #endif // TARGET_ARM @ARMTODO @@ -8769,6 +8772,8 @@ HRESULT CordbJITILFrame::GetReturnValueForType(CordbType *pType, ICorDebugValue const CorDebugRegister floatRegister = REGISTER_ARM_D0; #elif defined(TARGET_LOONGARCH64) const CorDebugRegister floatRegister = REGISTER_LOONGARCH64_F0; +#elif defined(TARGET_RISCV64) + const CorDebugRegister floatRegister = REGISTER_RISCV64_F0; #endif #if defined(TARGET_X86) @@ -8783,6 +8788,8 @@ HRESULT CordbJITILFrame::GetReturnValueForType(CordbType *pType, ICorDebugValue const CorDebugRegister ptrHighWordRegister = REGISTER_ARM_R1; #elif defined(TARGET_LOONGARCH64) const CorDebugRegister ptrRegister = REGISTER_LOONGARCH64_A0; +#elif defined(TARGET_RISCV64) + const CorDebugRegister ptrRegister = REGISTER_RISCV64_A0; #endif CorElementType corReturnType = pType->GetElementType(); diff --git a/src/coreclr/debug/di/shimremotedatatarget.cpp b/src/coreclr/debug/di/shimremotedatatarget.cpp index 1a5fb8562a6be3..674d325560ff52 100644 --- a/src/coreclr/debug/di/shimremotedatatarget.cpp +++ b/src/coreclr/debug/di/shimremotedatatarget.cpp @@ -232,6 +232,8 @@ ShimRemoteDataTarget::GetPlatform( *pPlatform = CORDB_PLATFORM_POSIX_ARM64; #elif defined(TARGET_LOONGARCH64) *pPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; + #elif defined(TARGET_RISCV64) + *pPlatform = CORDB_PLATFORM_POSIX_RISCV64; #else #error Unknown Processor. #endif diff --git a/src/coreclr/debug/ee/riscv64/dbghelpers.S b/src/coreclr/debug/ee/riscv64/dbghelpers.S index 3515f38c8120d7..71b584d7aa6566 100644 --- a/src/coreclr/debug/ee/riscv64/dbghelpers.S +++ b/src/coreclr/debug/ee/riscv64/dbghelpers.S @@ -4,4 +4,40 @@ #include "asmconstants.h" #include "unixasmmacros.inc" -#error "TODO-RISCV64: missing implementation" +// +// hijacking stub used to perform a func-eval, see Debugger::FuncEvalSetup() for use. +// +// on entry: +// a0 : pointer to DebuggerEval object +// + +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix + // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if + // you change the prolog you will also need to update the personality routine. + + // push arg to the stack so our personality routine can find it + // push lr to get good stacktrace in debugger + PROLOG_SAVE_REG_PAIR_INDEXED fp, ra, -32 + sd a0, 16(sp) + + // FuncEvalHijackWorker returns the address we should jump to. + call C_FUNC(FuncEvalHijackWorker) + + EPILOG_STACK_FREE 32 + EPILOG_BRANCH_REG a0 +NESTED_END FuncEvalHijack + +// This is the general purpose hijacking stub. The DacDbi Hijack primitive will +// set up the stack and then set the IP here, and so this just makes the call. +NESTED_ENTRY ExceptionHijack, _TEXT, UnhandledExceptionHandlerUnix + // make the call + call C_FUNC(ExceptionHijackWorker) + + // effective NOP to terminate unwind ??? + nop + + // *** should never get here *** + EMIT_BREAKPOINT +// exported label so the debugger knows where the end of this function is +NESTED_END ExceptionHijack, _TEXT diff --git a/src/coreclr/debug/ee/riscv64/primitives.cpp b/src/coreclr/debug/ee/riscv64/primitives.cpp index c4b50b4c66ef08..ef4735a9d3e1bb 100644 --- a/src/coreclr/debug/ee/riscv64/primitives.cpp +++ b/src/coreclr/debug/ee/riscv64/primitives.cpp @@ -7,4 +7,8 @@ #include "threads.h" #include "../../shared/riscv64/primitives.cpp" -#error "TODO-RISCV64: missing implementation" +void CopyREGDISPLAY(REGDISPLAY* pDst, REGDISPLAY* pSrc) +{ + CONTEXT tmp; + CopyRegDisplay(pSrc, pDst, &tmp); +} diff --git a/src/coreclr/debug/ee/riscv64/walker.cpp b/src/coreclr/debug/ee/riscv64/walker.cpp index c428cd8f3dbd23..4bf789d5f5c6ce 100644 --- a/src/coreclr/debug/ee/riscv64/walker.cpp +++ b/src/coreclr/debug/ee/riscv64/walker.cpp @@ -14,6 +14,6 @@ #ifdef TARGET_RISCV64 -#error "TODO-RISCV64: missing implementation" +// #error "TODO-RISCV64: missing implementation" #endif diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index f40eae3c6a4276..76b228b6ebf1bc 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -1895,6 +1895,13 @@ C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); #endif +#elif defined(TARGET_RISCV64) +#define DBG_TARGET_REGNUM_SP 2 +#define DBG_TARGET_REGNUM_AMBIENT_SP 34 +#ifdef TARGET_RISCV64 +C_ASSERT(DBG_TARGET_REGNUM_SP == ICorDebugInfo::REGNUM_SP); +C_ASSERT(DBG_TARGET_REGNUM_AMBIENT_SP == ICorDebugInfo::REGNUM_AMBIENT_SP); +#endif #else #error Target registers are not defined for this platform #endif diff --git a/src/coreclr/debug/inc/dbgtargetcontext.h b/src/coreclr/debug/inc/dbgtargetcontext.h index 403039e24d6a56..dc3b853014dee2 100644 --- a/src/coreclr/debug/inc/dbgtargetcontext.h +++ b/src/coreclr/debug/inc/dbgtargetcontext.h @@ -50,6 +50,8 @@ #define DTCONTEXT_IS_ARM64 #elif defined (TARGET_LOONGARCH64) #define DTCONTEXT_IS_LOONGARCH64 +#elif defined (TARGET_RISCV64) +#define DTCONTEXT_IS_RISCV64 #endif #if defined(DTCONTEXT_IS_X86) @@ -293,6 +295,7 @@ typedef struct DECLSPEC_ALIGN(16) { #define DT_ARM_MAX_BREAKPOINTS 8 #define DT_ARM_MAX_WATCHPOINTS 1 + typedef struct { ULONGLONG Low; LONGLONG High; @@ -513,6 +516,71 @@ typedef DECLSPEC_ALIGN(16) struct { ULONGLONG F[32]; } DT_CONTEXT; +#elif defined(DTCONTEXT_IS_RISCV64) +#define DT_CONTEXT_RISCV64 0x01000000L + +#define DT_CONTEXT_CONTROL (DT_CONTEXT_RISCV64 | 0x1L) +#define DT_CONTEXT_INTEGER (DT_CONTEXT_RISCV64 | 0x2L) +#define DT_CONTEXT_FLOATING_POINT (DT_CONTEXT_RISCV64 | 0x4L) +#define DT_CONTEXT_DEBUG_REGISTERS (DT_CONTEXT_RISCV64 | 0x8L) + +#define DT_CONTEXT_FULL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT) +#define DT_CONTEXT_ALL (DT_CONTEXT_CONTROL | DT_CONTEXT_INTEGER | DT_CONTEXT_FLOATING_POINT | DT_CONTEXT_DEBUG_REGISTERS) + +#define DT_RISCV64_MAX_BREAKPOINTS 8 +#define DT_RISCV64_MAX_WATCHPOINTS 2 + +typedef DECLSPEC_ALIGN(16) struct { + // + // Control flags. + // + + /* +0x000 */ DWORD ContextFlags; + + // + // Integer registers + // + DWORD64 ZR; + DWORD64 RA; + DWORD64 SP; + DWORD64 GP; + DWORD64 TP; + DWORD64 T0; + DWORD64 T1; + DWORD64 T2; + DWORD64 FP; + DWORD64 S1; + DWORD64 A0; + DWORD64 A1; + DWORD64 A2; + DWORD64 A3; + DWORD64 A4; + DWORD64 A5; + DWORD64 A6; + DWORD64 A7; + DWORD64 S2; + DWORD64 S3; + DWORD64 S4; + DWORD64 S5; + DWORD64 S6; + DWORD64 S7; + DWORD64 S8; + DWORD64 S9; + DWORD64 S10; + DWORD64 S11; + DWORD64 T3; + DWORD64 T4; + DWORD64 T5; + DWORD64 T6; + DWORD64 PC; + + // + // Floating Point Registers + // + ULONGLONG F[32]; +} DT_CONTEXT; + + #else #error Unsupported platform #endif diff --git a/src/coreclr/debug/inc/riscv64/primitives.h b/src/coreclr/debug/inc/riscv64/primitives.h new file mode 100644 index 00000000000000..0ce355aec5950c --- /dev/null +++ b/src/coreclr/debug/inc/riscv64/primitives.h @@ -0,0 +1,261 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//***************************************************************************** +// File: primitives.h +// + +// +// Platform-specific debugger primitives +// +//***************************************************************************** + +#ifndef PRIMITIVES_H_ +#define PRIMITIVES_H_ + +typedef const BYTE CORDB_ADDRESS_TYPE; +typedef DPTR(CORDB_ADDRESS_TYPE) PTR_CORDB_ADDRESS_TYPE; + +// TODO-RISCV64-CQ: Update when it supports c and other extensions +#define MAX_INSTRUCTION_LENGTH 4 + +// Given a return address retrieved during stackwalk, +// this is the offset by which it should be decremented to land at the call instruction. +#define STACKWALK_CONTROLPC_ADJUST_OFFSET 4 + +#define PRD_TYPE LONG +#define CORDbg_BREAK_INSTRUCTION_SIZE 4 +#define CORDbg_BREAK_INSTRUCTION (LONG)0x00100073 + +inline CORDB_ADDRESS GetPatchEndAddr(CORDB_ADDRESS patchAddr) +{ + LIMITED_METHOD_DAC_CONTRACT; + return patchAddr + CORDbg_BREAK_INSTRUCTION_SIZE; +} + +#define InitializePRDToBreakInst(_pPRD) *(_pPRD) = CORDbg_BREAK_INSTRUCTION +#define PRDIsBreakInst(_pPRD) (*(_pPRD) == CORDbg_BREAK_INSTRUCTION) + + +#define CORDbgGetInstructionEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \ + CORDbgGetInstructionExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr))); + +#define CORDbgSetInstructionEx(_buffer, _requestedAddr, _patchAddr, _opcode, _dummy2) \ + CORDbgSetInstructionExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr)), (_opcode)); + +#define CORDbgInsertBreakpointEx(_buffer, _requestedAddr, _patchAddr, _dummy1, _dummy2) \ + CORDbgInsertBreakpointExImpl((CORDB_ADDRESS_TYPE *)((_buffer) + (_patchAddr) - (_requestedAddr))); + + +constexpr CorDebugRegister g_JITToCorDbgReg[] = +{ + REGISTER_RISCV64_X0, // TODO-RISCV64-CQ: Add X0 to access DbgReg in correct order + REGISTER_RISCV64_RA, + REGISTER_RISCV64_SP, + REGISTER_RISCV64_GP, + REGISTER_RISCV64_TP, + REGISTER_RISCV64_T0, + REGISTER_RISCV64_T1, + REGISTER_RISCV64_T2, + REGISTER_RISCV64_FP, + REGISTER_RISCV64_S1, + REGISTER_RISCV64_A0, + REGISTER_RISCV64_A1, + REGISTER_RISCV64_A2, + REGISTER_RISCV64_A3, + REGISTER_RISCV64_A4, + REGISTER_RISCV64_A5, + REGISTER_RISCV64_A6, + REGISTER_RISCV64_A7, + REGISTER_RISCV64_S2, + REGISTER_RISCV64_S3, + REGISTER_RISCV64_S4, + REGISTER_RISCV64_S5, + REGISTER_RISCV64_S6, + REGISTER_RISCV64_S7, + REGISTER_RISCV64_S8, + REGISTER_RISCV64_S9, + REGISTER_RISCV64_S10, + REGISTER_RISCV64_S11, + REGISTER_RISCV64_T3, + REGISTER_RISCV64_T4, + REGISTER_RISCV64_T5, + REGISTER_RISCV64_T6, + REGISTER_RISCV64_PC +}; + +inline void CORDbgSetIP(DT_CONTEXT *context, LPVOID ip) { + LIMITED_METHOD_CONTRACT; + + context->PC = (DWORD64)ip; +} + +inline LPVOID CORDbgGetSP(const DT_CONTEXT * context) { + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->SP); +} + +inline void CORDbgSetSP(DT_CONTEXT *context, LPVOID esp) { + LIMITED_METHOD_CONTRACT; + + context->SP = (DWORD64)esp; +} + +inline LPVOID CORDbgGetFP(const DT_CONTEXT * context) { + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->FP); +} + +inline void CORDbgSetFP(DT_CONTEXT *context, LPVOID fp) { + LIMITED_METHOD_CONTRACT; + + context->FP = (DWORD64)fp; +} + + +inline BOOL CompareControlRegisters(const DT_CONTEXT * pCtx1, const DT_CONTEXT * pCtx2) +{ + LIMITED_METHOD_DAC_CONTRACT; + + // TODO-RISCV64: Sort out frame registers + + if ((pCtx1->PC == pCtx2->PC) && + (pCtx1->SP == pCtx2->SP) && + (pCtx1->FP == pCtx2->FP)) + { + return TRUE; + } + + return FALSE; +} + +inline void CORDbgSetInstruction(CORDB_ADDRESS_TYPE* address, + PRD_TYPE instruction) +{ + // In a DAC build, this function assumes the input is an host address. + LIMITED_METHOD_DAC_CONTRACT; + + ULONGLONG ptraddr = dac_cast(address); + *(PRD_TYPE *)ptraddr = instruction; + FlushInstructionCache(GetCurrentProcess(), + address, + sizeof(PRD_TYPE)); +} + +inline PRD_TYPE CORDbgGetInstruction(UNALIGNED CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + ULONGLONG ptraddr = dac_cast(address); + return *(PRD_TYPE *)ptraddr; +} + +// +// Mapping from ICorDebugInfo register numbers to CorDebugRegister +// numbers. Note: this must match the order in corinfo.h. +// +inline CorDebugRegister ConvertRegNumToCorDebugRegister(ICorDebugInfo::RegNum reg) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(reg >= 0); + _ASSERTE(static_cast(reg) < ARRAY_SIZE(g_JITToCorDbgReg)); + return g_JITToCorDbgReg[reg]; +} + +inline LPVOID CORDbgGetIP(DT_CONTEXT *context) +{ + LIMITED_METHOD_CONTRACT; + + return (LPVOID)(size_t)(context->PC); +} + +inline void CORDbgSetInstructionExImpl(CORDB_ADDRESS_TYPE* address, + PRD_TYPE instruction) +{ + LIMITED_METHOD_DAC_CONTRACT; + + *(PRD_TYPE *)address = instruction; + FlushInstructionCache(GetCurrentProcess(), + address, + sizeof(PRD_TYPE)); +} + +inline PRD_TYPE CORDbgGetInstructionExImpl(UNALIGNED CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + return *(PRD_TYPE *)address; +} + +inline void CORDbgInsertBreakpoint(UNALIGNED CORDB_ADDRESS_TYPE *address) +{ + LIMITED_METHOD_CONTRACT; + + CORDbgSetInstruction(address, CORDbg_BREAK_INSTRUCTION); +} + +inline void CORDbgInsertBreakpointExImpl(UNALIGNED CORDB_ADDRESS_TYPE *address) +{ + LIMITED_METHOD_CONTRACT; + + CORDbgSetInstruction(address, CORDbg_BREAK_INSTRUCTION); +} + +// After a breakpoint exception, the CPU points to _after_ the break instruction. +// Adjust the IP so that it points at the break instruction. This lets us patch that +// opcode and re-execute what was underneath the bp. +inline void CORDbgAdjustPCForBreakInstruction(DT_CONTEXT* pContext) +{ + LIMITED_METHOD_CONTRACT; + + // RISCV64 appears to leave the PC at the start of the breakpoint. + return; +} + +inline bool AddressIsBreakpoint(CORDB_ADDRESS_TYPE* address) +{ + LIMITED_METHOD_CONTRACT; + + return CORDbgGetInstruction(address) == CORDbg_BREAK_INSTRUCTION; +} + +inline void SetSSFlag(DT_CONTEXT *pContext) +{ + // TODO-RISCV64: RISCV64 doesn't support cpsr. + _ASSERTE(!"unimplemented on RISCV64 yet"); +} + +inline void UnsetSSFlag(DT_CONTEXT *pContext) +{ + // TODO-RISCV64: RISCV64 doesn't support cpsr. + _ASSERTE(!"unimplemented on RISCV64 yet"); +} + +inline bool IsSSFlagEnabled(DT_CONTEXT * pContext) +{ + // TODO-RISCV64: RISCV64 doesn't support cpsr. + _ASSERTE(!"unimplemented on RISCV64 yet"); + return false; +} + + +inline bool PRDIsEqual(PRD_TYPE p1, PRD_TYPE p2) +{ + return p1 == p2; +} + +inline void InitializePRD(PRD_TYPE *p1) +{ + *p1 = 0; +} + +inline bool PRDIsEmpty(PRD_TYPE p1) +{ + LIMITED_METHOD_CONTRACT; + + return p1 == 0; +} + +#endif // PRIMITIVES_H_ diff --git a/src/coreclr/debug/shared/riscv64/primitives.cpp b/src/coreclr/debug/shared/riscv64/primitives.cpp index 50eae7be8a7ea8..112f76f5d6d257 100644 --- a/src/coreclr/debug/shared/riscv64/primitives.cpp +++ b/src/coreclr/debug/shared/riscv64/primitives.cpp @@ -12,4 +12,17 @@ #include "primitives.h" -#error "TODO-RISCV64: missing implementation" +// CopyThreadContext() does an intelligent copy from pSrc to pDst, +// respecting the ContextFlags of both contexts. +// +void CORDbgCopyThreadContext(DT_CONTEXT* pDst, const DT_CONTEXT* pSrc) +{ + _ASSERTE(!"RISCV64:NYI"); +} + +#if defined(ALLOW_VMPTR_ACCESS) || !defined(RIGHT_SIDE_COMPILE) +void SetDebuggerREGDISPLAYFromREGDISPLAY(DebuggerREGDISPLAY* pDRD, REGDISPLAY* pRD) +{ + _ASSERTE(!"RISCV64:NYI"); +} +#endif // ALLOW_VMPTR_ACCESS || !RIGHT_SIDE_COMPILE diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 37053c772215d8..f96c671165c6f9 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2236,10 +2236,8 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { #elif defined(HOST_RISCV64) -#error "TODO-RISCV64: review this when src/coreclr/pal/src/arch/riscv64/asmconstants.h is ported" - // Please refer to src/coreclr/pal/src/arch/riscv64/asmconstants.h -#define CONTEXT_RISCV64 0x04000000L +#define CONTEXT_RISCV64 0x01000000L #define CONTEXT_CONTROL (CONTEXT_RISCV64 | 0x1) #define CONTEXT_INTEGER (CONTEXT_RISCV64 | 0x2) @@ -2286,6 +2284,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { // // Integer registers. // + DWORD64 R0; DWORD64 Ra; DWORD64 Sp; DWORD64 Gp; @@ -2293,7 +2292,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { DWORD64 T0; DWORD64 T1; DWORD64 T2; - DWORD64 S0; + DWORD64 Fp; DWORD64 S1; DWORD64 A0; DWORD64 A1; @@ -2333,20 +2332,7 @@ typedef struct DECLSPEC_ALIGN(16) _CONTEXT { typedef struct _KNONVOLATILE_CONTEXT_POINTERS { - PDWORD64 Ra; - PDWORD64 Tp; - PDWORD64 T0; - PDWORD64 T1; - PDWORD64 S0; PDWORD64 S1; - PDWORD64 A0; - PDWORD64 A1; - PDWORD64 A2; - PDWORD64 A3; - PDWORD64 A4; - PDWORD64 A5; - PDWORD64 A6; - PDWORD64 A7; PDWORD64 S2; PDWORD64 S3; PDWORD64 S4; @@ -2357,31 +2343,23 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { PDWORD64 S9; PDWORD64 S10; PDWORD64 S11; - PDWORD64 T3; - PDWORD64 T4; - PDWORD64 T5; - PDWORD64 T6; - - PDWORD64 FS0; - PDWORD64 FS1; - PDWORD64 FA0; - PDWORD64 FA1; - PDWORD64 FA2; - PDWORD64 FA3; - PDWORD64 FA4; - PDWORD64 FA5; - PDWORD64 FA6; - PDWORD64 FA7; - PDWORD64 FS2; - PDWORD64 FS3; - PDWORD64 FS4; - PDWORD64 FS5; - PDWORD64 FS6; - PDWORD64 FS7; - PDWORD64 FS8; - PDWORD64 FS9; - PDWORD64 FS10; - PDWORD64 FS11; + PDWORD64 Fp; + PDWORD64 Gp; + PDWORD64 Tp; + PDWORD64 Ra; + + PDWORD64 F8; + PDWORD64 F9; + PDWORD64 F18; + PDWORD64 F19; + PDWORD64 F20; + PDWORD64 F21; + PDWORD64 F22; + PDWORD64 F23; + PDWORD64 F24; + PDWORD64 F25; + PDWORD64 F26; + PDWORD64 F27; } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; #elif defined(HOST_S390X) @@ -3849,7 +3827,8 @@ YieldProcessor() #elif defined(HOST_LOONGARCH64) __asm__ volatile( "dbar 0; \n"); #elif defined(HOST_RISCV64) - __asm__ __volatile__( "wfi"); + // TODO-RISCV64-CQ: When Zihintpause is supported, replace with `pause` instruction. + __asm__ __volatile__(".word 0x0100000f"); #else return; #endif diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 2cf95e40721ab2..17680e2a3e9f10 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -244,6 +244,7 @@ typedef struct _IMAGE_FILE_HEADER { #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian #define IMAGE_FILE_MACHINE_CEE 0xC0EE #define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 // LOONGARCH64. +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISCV64 // // Directory format. @@ -1020,6 +1021,12 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_LOONGARCH64_PC 0x0003 #define IMAGE_REL_LOONGARCH64_JIR 0x0004 +// +// RISCV64 relocation types +// +#define IMAGE_REL_RISCV64_PC 0x0003 +#define IMAGE_REL_RISCV64_JALR 0x0004 + // // CEF relocation types. // diff --git a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc index 683ae88415a907..11b90d6891ef3c 100644 --- a/src/coreclr/pal/inc/unixasmmacrosriscv64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosriscv64.inc @@ -1,42 +1,325 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#error "TODO-RISCV64: review this; missing many macros for VM" - .macro NESTED_ENTRY Name, Section, Handler - LEAF_ENTRY \Name, \Section - .ifnc \Handler, NoHandler - .personality C_FUNC(\Handler) - .endif + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1c, C_FUNC(\Handler) // 0x1c == DW_EH_PE_pcrel | DW_EH_PE_sdata8 + .endif .endm .macro NESTED_END Name, Section - LEAF_END \Name, \Section + LEAF_END \Name, \Section .endm .macro PATCH_LABEL Name - .global C_FUNC(\Name) + .global C_FUNC(\Name) C_FUNC(\Name): .endm .macro LEAF_ENTRY Name, Section - .global C_FUNC(\Name) - .type \Name, %function + .global C_FUNC(\Name) + .type \Name, %function C_FUNC(\Name): - .cfi_startproc + .cfi_startproc .endm .macro LEAF_END Name, Section - .size \Name, .-\Name - .cfi_endproc + .size \Name, .-\Name + .cfi_endproc .endm .macro LEAF_END_MARKED Name, Section C_FUNC(\Name\()_End): - .global C_FUNC(\Name\()_End) - LEAF_END \Name, \Section + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section + // make sure this symbol gets its own address + nop +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + lla \HelperReg, \Name +.endm + +.macro PROLOG_STACK_ALLOC Size + addi sp, sp, -\Size +.endm + +.macro EPILOG_STACK_FREE Size + addi sp, sp, \Size + .cfi_def_cfa sp,-\Size +.endm + +.macro EPILOG_STACK_RESTORE + ori sp, fp, 0 + .cfi_restore sp +.endm + +.macro PROLOG_SAVE_REG reg, ofs + sd \reg, \ofs(sp) + .cfi_rel_offset \reg, \ofs +.endm + +.macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs, __def_cfa_save=0 + sd \reg1, \ofs(sp) + sd \reg2, (\ofs+8)(sp) + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg1, \ofs + 8 + .if (\__def_cfa_save == 1) + addi fp, sp, 0 + .cfi_def_cfa_register fp + .endif +.endm + +.macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ssize, __def_cfa_save=1 + addi sp, sp, -\ssize + + sd \reg1, 0(sp) + sd \reg2, 8(sp) + + .cfi_adjust_cfa_offset -\ssize + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 + .if (\__def_cfa_save == 1) + addi fp, sp, 0 + .cfi_def_cfa_register fp + .endif +.endm + +.macro EPILOG_RESTORE_REG reg, ofs + ld \reg, (\ofs)(sp) + .cfi_restore \reg + .cfi_def_cfa_register sp +.endm + +.macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs + ld \reg2, (\ofs+8)(sp) + ld \reg1, (\ofs)(sp) + .cfi_restore \reg2 + .cfi_restore \reg1 +.endm + +.macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ssize + ld \reg2, 8(sp) + ld \reg1, 0(sp) + .cfi_restore \reg2 + .cfi_restore \reg1 + + addi sp, sp, \ssize + .cfi_def_cfa sp,-\ssize +.endm + +.macro EPILOG_RETURN + ret .endm .macro EMIT_BREAKPOINT - ebreak + ebreak +.endm + +.macro EPILOG_BRANCH Target + j \Target +.endm + +.macro EPILOG_BRANCH_REG reg + jr \reg +.endm + +//----------------------------------------------------------------------------- +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// base address to be passed in $reg +// + +// Reserve 64 bytes of memory before calling SAVE_CALLEESAVED_REGISTERS +.macro SAVE_CALLEESAVED_REGISTERS reg, ofs + PROLOG_SAVE_REG_PAIR s1, s2, \ofs + 16 + PROLOG_SAVE_REG_PAIR s3, s4, \ofs + 32 + PROLOG_SAVE_REG_PAIR s5, s6, \ofs + 48 + PROLOG_SAVE_REG_PAIR s7, s8, \ofs + 64 + PROLOG_SAVE_REG_PAIR s9, s10, \ofs + 80 + PROLOG_SAVE_REG_PAIR s11, tp \ofs + 96 + PROLOG_SAVE_REG gp, \ofs + 112 +.endm + +// Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS +.macro SAVE_ARGUMENT_REGISTERS reg, ofs + sd a0, (\ofs)(\reg) + sd a1, (\ofs + 8)(\reg) + sd a2, (\ofs + 16)(\reg) + sd a3, (\ofs + 24)(\reg) + sd a4, (\ofs + 32)(\reg) + sd a5, (\ofs + 40)(\reg) + sd a6, (\ofs + 48)(\reg) + sd a7, (\ofs + 56)(\reg) +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs + fsd fa0, (\ofs)(\reg) + fsd fa1, (\ofs + 8)(\reg) + fsd fa2, (\ofs + 16)(\reg) + fsd fa3, (\ofs + 24)(\reg) + fsd fa4, (\ofs + 32)(\reg) + fsd fa5, (\ofs + 40)(\reg) + fsd fa6, (\ofs + 48)(\reg) + fsd fa7, (\ofs + 56)(\reg) +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_CALLEESAVED_REGISTERS +.macro SAVE_FLOAT_CALLEESAVED_REGISTERS reg, ofs +// TODO RISCV NYI + sw ra, 0(zero) +.endm + +.macro RESTORE_CALLEESAVED_REGISTERS reg, ofs + EPILOG_RESTORE_REG gp \ofs + 112 + EPILOG_RESTORE_REG_PAIR s11, tp \ofs + 96 + EPILOG_RESTORE_REG_PAIR s9, s10, \ofs + 80 + EPILOG_RESTORE_REG_PAIR s7, s8, \ofs + 64 + EPILOG_RESTORE_REG_PAIR s5, s6, \ofs + 48 + EPILOG_RESTORE_REG_PAIR s3, s4, \ofs + 32 + EPILOG_RESTORE_REG_PAIR s1, s2, \ofs + 16 +.endm + +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs + ld a0, (\ofs)(\reg) + ld a1, (\ofs + 8)(\reg) + ld a2, (\ofs + 16)(\reg) + ld a3, (\ofs + 24)(\reg) + ld a4, (\ofs + 32)(\reg) + ld a5, (\ofs + 40)(\reg) + ld a6, (\ofs + 48)(\reg) + ld a7, (\ofs + 56)(\reg) +.endm + +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs + fld fa0, (\ofs)(\reg) + fld fa1, (\ofs + 8)(\reg) + fld fa2, (\ofs + 16)(\reg) + fld fa3, (\ofs + 24)(\reg) + fld fa4, (\ofs + 32)(\reg) + fld fa5, (\ofs + 40)(\reg) + fld fa6, (\ofs + 48)(\reg) + fld fa7, (\ofs + 56)(\reg) +.endm + +.macro RESTORE_FLOAT_CALLEESAVED_REGISTERS reg, ofs +// TODO RISCV NYI + sw ra, 0(zero) +.endm + +//----------------------------------------------------------------------------- +// Define the prolog for a TransitionBlock-based method. This macro should be called first in the method and +// comprises the entire prolog.The locals must be 8 byte aligned +// +// Save_argument_registers: +// GPR_a7 +// GPR_a6 +// GPR_a5 +// GPR_a4 +// GPR_a3 +// GPR_a2 +// GPR_a1 +// GPR_a0 +// +// General Registers: +// GPR_tp +// GPR_s8 +// GPR_s7 +// GPR_s6 +// GPR_s5 +// GPR_s4 +// GPR_s3 +// GPR_s2 +// GPR_s1 +// GPR_s0 +// GPR_ra +// GPR_fp +// +// Float Point: +// FPR_f27 / fs11 +// FPR_f26 / fs10 +// FPR_f25 / fs9 +// FPR_f24 / fs8 +// FPR_f23 / fs7 +// FPR_f22 / fs6 +// FPR_f21 / fs5 +// FPR_f20 / fs4 +// FPR_f19 / fs3 +// FPR_f18 / fs2 +// FPR_f9 / fs1 +// FPR_f8 / fs0 +// Extra: +// +.macro PROLOG_WITH_TRANSITION_BLOCK extraParameters = 0, extraLocals = 0, SaveFPRegs = 1 + __PWTB_SaveFPArgs = \SaveFPRegs + + __PWTB_FloatArgumentRegisters = \extraLocals + + .if ((__PWTB_FloatArgumentRegisters % 16) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + + .if (__PWTB_SaveFPArgs == 1) + __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters + .endif + + + __PWTB_CalleeSavedRegisters = __PWTB_TransitionBlock + __PWTB_ArgumentRegisters = __PWTB_TransitionBlock + 120 + + // Including fp, ra, s1-s11, tp, gp, and (a0-a7)arguments. (1+1+11+1+1)*8 + 8*8. + __PWTB_StackAlloc = __PWTB_TransitionBlock + 120 + 64 + PROLOG_STACK_ALLOC __PWTB_StackAlloc + PROLOG_SAVE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters, 1 + + // First, Spill argument registers. + SAVE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + + // Then, Spill callee saved registers. sp=r2. + SAVE_CALLEESAVED_REGISTERS sp, __PWTB_CalleeSavedRegisters + + // saving is f10-17. + .if (__PWTB_SaveFPArgs == 1) + SAVE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters + .endif + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN +// TODO RISCV NYI + sw ra, 0(zero) +.endm + + +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters + .endif + + RESTORE_CALLEESAVED_REGISTERS sp, __PWTB_CalleeSavedRegisters + + RESTORE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + + EPILOG_RESTORE_REG_PAIR fp, ra, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc +.endm + +// ------------------------------------------------------------------ +// Macro to generate Redirection Stubs +// +// $reason : reason for redirection +// Eg. GCThreadControl +// NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame. +// This function is used by both the personality routine and the debugger to retrieve the original CONTEXT. +.macro GenerateRedirectedHandledJITCaseStub reason +// TODO RISCV NYI + sw ra, 0(zero) .endm diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index fa4b434eccf554..83a7968f1a9bca 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -1476,7 +1476,8 @@ enum CorDebugPlatform CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) , - CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) + CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) , + CORDB_PLATFORM_POSIX_RISCV64 = ( CORDB_PLATFORM_POSIX_LOONGARCH64 + 1 ) } CorDebugPlatform; @@ -9256,7 +9257,72 @@ enum CorDebugRegister REGISTER_LOONGARCH64_F28 = ( REGISTER_LOONGARCH64_F27 + 1 ) , REGISTER_LOONGARCH64_F29 = ( REGISTER_LOONGARCH64_F28 + 1 ) , REGISTER_LOONGARCH64_F30 = ( REGISTER_LOONGARCH64_F29 + 1 ) , - REGISTER_LOONGARCH64_F31 = ( REGISTER_LOONGARCH64_F30 + 1 ) + REGISTER_LOONGARCH64_F31 = ( REGISTER_LOONGARCH64_F30 + 1 ), + REGISTER_RISCV64_PC = 0, + REGISTER_RISCV64_RA = ( REGISTER_RISCV64_PC + 1), + REGISTER_RISCV64_SP = ( REGISTER_RISCV64_RA + 1), + REGISTER_RISCV64_GP = ( REGISTER_RISCV64_SP + 1), + REGISTER_RISCV64_TP = ( REGISTER_RISCV64_GP + 1 ), + REGISTER_RISCV64_T0 = ( REGISTER_RISCV64_TP + 1 ), + REGISTER_RISCV64_T1 = ( REGISTER_RISCV64_T0 + 1 ), + REGISTER_RISCV64_T2 = ( REGISTER_RISCV64_T1 + 1 ), + REGISTER_RISCV64_FP = ( REGISTER_RISCV64_T2 + 1 ), + REGISTER_RISCV64_S1 = ( REGISTER_RISCV64_FP + 1 ), + REGISTER_RISCV64_A0 = ( REGISTER_RISCV64_S1 + 1 ), + REGISTER_RISCV64_A1 = ( REGISTER_RISCV64_A0 + 1 ), + REGISTER_RISCV64_A2 = ( REGISTER_RISCV64_A1 + 1 ), + REGISTER_RISCV64_A3 = ( REGISTER_RISCV64_A2 + 1 ), + REGISTER_RISCV64_A4 = ( REGISTER_RISCV64_A3 + 1 ), + REGISTER_RISCV64_A5 = ( REGISTER_RISCV64_A4 + 1 ), + REGISTER_RISCV64_A6 = ( REGISTER_RISCV64_A5 + 1 ), + REGISTER_RISCV64_A7 = ( REGISTER_RISCV64_A6 + 1 ), + REGISTER_RISCV64_S2 = ( REGISTER_RISCV64_A7 + 1 ), + REGISTER_RISCV64_S3 = ( REGISTER_RISCV64_S2 + 1 ), + REGISTER_RISCV64_S4 = ( REGISTER_RISCV64_S3 + 1 ), + REGISTER_RISCV64_S5 = ( REGISTER_RISCV64_S4 + 1 ), + REGISTER_RISCV64_S6 = ( REGISTER_RISCV64_S5 + 1 ), + REGISTER_RISCV64_S7 = ( REGISTER_RISCV64_S6 + 1 ), + REGISTER_RISCV64_S8 = ( REGISTER_RISCV64_S7 + 1 ), + REGISTER_RISCV64_S9 = ( REGISTER_RISCV64_S8 + 1 ), + REGISTER_RISCV64_S10 = ( REGISTER_RISCV64_S9 + 1 ), + REGISTER_RISCV64_S11 = ( REGISTER_RISCV64_S10 + 1 ), + REGISTER_RISCV64_T3 = ( REGISTER_RISCV64_S11 + 1 ), + REGISTER_RISCV64_T4 = ( REGISTER_RISCV64_T3 + 1 ), + REGISTER_RISCV64_T5 = ( REGISTER_RISCV64_T4 + 1 ), + REGISTER_RISCV64_T6 = ( REGISTER_RISCV64_T5 + 1 ), + REGISTER_RISCV64_F0 = ( REGISTER_RISCV64_T6 + 1 ), + REGISTER_RISCV64_F1 = ( REGISTER_RISCV64_F0 + 1 ), + REGISTER_RISCV64_F2 = ( REGISTER_RISCV64_F1 + 1 ), + REGISTER_RISCV64_F3 = ( REGISTER_RISCV64_F2 + 1 ), + REGISTER_RISCV64_F4 = ( REGISTER_RISCV64_F3 + 1 ), + REGISTER_RISCV64_F5 = ( REGISTER_RISCV64_F4 + 1 ), + REGISTER_RISCV64_F6 = ( REGISTER_RISCV64_F5 + 1 ), + REGISTER_RISCV64_F7 = ( REGISTER_RISCV64_F6 + 1 ), + REGISTER_RISCV64_F8 = ( REGISTER_RISCV64_F7 + 1 ), + REGISTER_RISCV64_F9 = ( REGISTER_RISCV64_F8 + 1 ), + REGISTER_RISCV64_F10 = ( REGISTER_RISCV64_F9 + 1 ), + REGISTER_RISCV64_F11 = ( REGISTER_RISCV64_F10 + 1 ), + REGISTER_RISCV64_F12 = ( REGISTER_RISCV64_F11 + 1 ), + REGISTER_RISCV64_F13 = ( REGISTER_RISCV64_F12 + 1 ), + REGISTER_RISCV64_F14 = ( REGISTER_RISCV64_F13 + 1 ), + REGISTER_RISCV64_F15 = ( REGISTER_RISCV64_F14 + 1 ), + REGISTER_RISCV64_F16 = ( REGISTER_RISCV64_F15 + 1 ), + REGISTER_RISCV64_F17 = ( REGISTER_RISCV64_F16 + 1 ), + REGISTER_RISCV64_F18 = ( REGISTER_RISCV64_F17 + 1 ), + REGISTER_RISCV64_F19 = ( REGISTER_RISCV64_F18 + 1 ), + REGISTER_RISCV64_F20 = ( REGISTER_RISCV64_F19 + 1 ), + REGISTER_RISCV64_F21 = ( REGISTER_RISCV64_F20 + 1 ), + REGISTER_RISCV64_F22 = ( REGISTER_RISCV64_F21 + 1 ), + REGISTER_RISCV64_F23 = ( REGISTER_RISCV64_F22 + 1 ), + REGISTER_RISCV64_F24 = ( REGISTER_RISCV64_F23 + 1 ), + REGISTER_RISCV64_F25 = ( REGISTER_RISCV64_F24 + 1 ), + REGISTER_RISCV64_F26 = ( REGISTER_RISCV64_F25 + 1 ), + REGISTER_RISCV64_F27 = ( REGISTER_RISCV64_F26 + 1 ), + REGISTER_RISCV64_F28 = ( REGISTER_RISCV64_F27 + 1 ), + REGISTER_RISCV64_F29 = ( REGISTER_RISCV64_F28 + 1 ), + REGISTER_RISCV64_F30 = ( REGISTER_RISCV64_F29 + 1 ), + REGISTER_RISCV64_F31 = ( REGISTER_RISCV64_F30 + 1 ), + REGISTER_RISCV64_X0 = ( REGISTER_RISCV64_F31 + 1 ), // TODO-RISCV64-CQ: Add X0 for an use in debug. Need to check. } CorDebugRegister; diff --git a/src/coreclr/pal/src/arch/riscv64/asmconstants.h b/src/coreclr/pal/src/arch/riscv64/asmconstants.h index 015ac39c13fc9f..97ae37f0c3ac52 100644 --- a/src/coreclr/pal/src/arch/riscv64/asmconstants.h +++ b/src/coreclr/pal/src/arch/riscv64/asmconstants.h @@ -7,9 +7,7 @@ // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-dwarf.adoc // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-cc.adoc -#error "TODO-RISCV64: review this when other files are ported in this directory" - -#define CONTEXT_RISCV64 0x04000000L +#define CONTEXT_RISCV64 0x01000000L #define CONTEXT_CONTROL_BIT (0) #define CONTEXT_INTEGER_BIT (1) @@ -23,51 +21,84 @@ #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) -#define SIZEOF_RISCV64_INTR 8 +#define SIZEOF_RISCV64_GPR 8 #define SIZEOF_RISCV64_FPR 8 -#define CONTEXT_X0 0 // hardwired zero -#define CONTEXT_X1 CONTEXT_X0 + SIZEOF_RISCV64_INTR -#define CONTEXT_X2 CONTEXT_X1 + SIZEOF_RISCV64_INTR -#define CONTEXT_X3 CONTEXT_X2 + SIZEOF_RISCV64_INTR -#define CONTEXT_X4 CONTEXT_X3 + SIZEOF_RISCV64_INTR -#define CONTEXT_X5 CONTEXT_X4 + SIZEOF_RISCV64_INTR -#define CONTEXT_X6 CONTEXT_X5 + SIZEOF_RISCV64_INTR -#define CONTEXT_X7 CONTEXT_X6 + SIZEOF_RISCV64_INTR -#define CONTEXT_X8 CONTEXT_X7 + SIZEOF_RISCV64_INTR -#define CONTEXT_X9 CONTEXT_X8 + SIZEOF_RISCV64_INTR -#define CONTEXT_X10 CONTEXT_X9 + SIZEOF_RISCV64_INTR -#define CONTEXT_X11 CONTEXT_X10 + SIZEOF_RISCV64_INTR -#define CONTEXT_X12 CONTEXT_X11 + SIZEOF_RISCV64_INTR -#define CONTEXT_X13 CONTEXT_X12 + SIZEOF_RISCV64_INTR -#define CONTEXT_X14 CONTEXT_X13 + SIZEOF_RISCV64_INTR -#define CONTEXT_X15 CONTEXT_X14 + SIZEOF_RISCV64_INTR -#define CONTEXT_X16 CONTEXT_X15 + SIZEOF_RISCV64_INTR -#define CONTEXT_X17 CONTEXT_X16 + SIZEOF_RISCV64_INTR -#define CONTEXT_X18 CONTEXT_X17 + SIZEOF_RISCV64_INTR -#define CONTEXT_X19 CONTEXT_X18 + SIZEOF_RISCV64_INTR -#define CONTEXT_X20 CONTEXT_X19 + SIZEOF_RISCV64_INTR -#define CONTEXT_X21 CONTEXT_X20 + SIZEOF_RISCV64_INTR -#define CONTEXT_X22 CONTEXT_X21 + SIZEOF_RISCV64_INTR -#define CONTEXT_X23 CONTEXT_X22 + SIZEOF_RISCV64_INTR -#define CONTEXT_X24 CONTEXT_X23 + SIZEOF_RISCV64_INTR -#define CONTEXT_X25 CONTEXT_X24 + SIZEOF_RISCV64_INTR -#define CONTEXT_X26 CONTEXT_X25 + SIZEOF_RISCV64_INTR -#define CONTEXT_X27 CONTEXT_X26 + SIZEOF_RISCV64_INTR -#define CONTEXT_X28 CONTEXT_X27 + SIZEOF_RISCV64_INTR -#define CONTEXT_X29 CONTEXT_X28 + SIZEOF_RISCV64_INTR -#define CONTEXT_X30 CONTEXT_X29 + SIZEOF_RISCV64_INTR -#define CONTEXT_X31 CONTEXT_X30 + SIZEOF_RISCV64_INTR +#define CONTEXT_ContextFlags 0 +#define CONTEXT_X0 CONTEXT_ContextFlags + SIZEOF_RISCV64_GPR // hardwired zero +#define CONTEXT_X1 CONTEXT_X0 + SIZEOF_RISCV64_GPR +#define CONTEXT_X2 CONTEXT_X1 + SIZEOF_RISCV64_GPR +#define CONTEXT_X3 CONTEXT_X2 + SIZEOF_RISCV64_GPR +#define CONTEXT_X4 CONTEXT_X3 + SIZEOF_RISCV64_GPR +#define CONTEXT_X5 CONTEXT_X4 + SIZEOF_RISCV64_GPR +#define CONTEXT_X6 CONTEXT_X5 + SIZEOF_RISCV64_GPR +#define CONTEXT_X7 CONTEXT_X6 + SIZEOF_RISCV64_GPR +#define CONTEXT_X8 CONTEXT_X7 + SIZEOF_RISCV64_GPR +#define CONTEXT_X9 CONTEXT_X8 + SIZEOF_RISCV64_GPR +#define CONTEXT_X10 CONTEXT_X9 + SIZEOF_RISCV64_GPR +#define CONTEXT_X11 CONTEXT_X10 + SIZEOF_RISCV64_GPR +#define CONTEXT_X12 CONTEXT_X11 + SIZEOF_RISCV64_GPR +#define CONTEXT_X13 CONTEXT_X12 + SIZEOF_RISCV64_GPR +#define CONTEXT_X14 CONTEXT_X13 + SIZEOF_RISCV64_GPR +#define CONTEXT_X15 CONTEXT_X14 + SIZEOF_RISCV64_GPR +#define CONTEXT_X16 CONTEXT_X15 + SIZEOF_RISCV64_GPR +#define CONTEXT_X17 CONTEXT_X16 + SIZEOF_RISCV64_GPR +#define CONTEXT_X18 CONTEXT_X17 + SIZEOF_RISCV64_GPR +#define CONTEXT_X19 CONTEXT_X18 + SIZEOF_RISCV64_GPR +#define CONTEXT_X20 CONTEXT_X19 + SIZEOF_RISCV64_GPR +#define CONTEXT_X21 CONTEXT_X20 + SIZEOF_RISCV64_GPR +#define CONTEXT_X22 CONTEXT_X21 + SIZEOF_RISCV64_GPR +#define CONTEXT_X23 CONTEXT_X22 + SIZEOF_RISCV64_GPR +#define CONTEXT_X24 CONTEXT_X23 + SIZEOF_RISCV64_GPR +#define CONTEXT_X25 CONTEXT_X24 + SIZEOF_RISCV64_GPR +#define CONTEXT_X26 CONTEXT_X25 + SIZEOF_RISCV64_GPR +#define CONTEXT_X27 CONTEXT_X26 + SIZEOF_RISCV64_GPR +#define CONTEXT_X28 CONTEXT_X27 + SIZEOF_RISCV64_GPR +#define CONTEXT_X29 CONTEXT_X28 + SIZEOF_RISCV64_GPR +#define CONTEXT_X30 CONTEXT_X29 + SIZEOF_RISCV64_GPR +#define CONTEXT_X31 CONTEXT_X30 + SIZEOF_RISCV64_GPR -#define CONTEXT_Pc CONTEXT_X31 + SIZEOF_RISCV64_INTR -#define CONTEXT_FPU_OFFSET CONTEXT_Pc + SIZEOF_RISCV64_INTR +#define CONTEXT_Pc CONTEXT_X31 + SIZEOF_RISCV64_GPR +#define CONTEXT_FPU_OFFSET CONTEXT_Pc + SIZEOF_RISCV64_GPR +#define CONTEXT_Ra CONTEXT_X1 #define CONTEXT_Sp CONTEXT_X2 +#define CONTEXT_Gp CONTEXT_X3 #define CONTEXT_Tp CONTEXT_X4 #define CONTEXT_Fp CONTEXT_X8 +#define CONTEXT_S0 CONTEXT_X8 +#define CONTEXT_S1 CONTEXT_X9 +#define CONTEXT_S2 CONTEXT_X18 +#define CONTEXT_S3 CONTEXT_X19 +#define CONTEXT_S4 CONTEXT_X20 +#define CONTEXT_S5 CONTEXT_X21 +#define CONTEXT_S6 CONTEXT_X22 +#define CONTEXT_S7 CONTEXT_X23 +#define CONTEXT_S8 CONTEXT_X24 +#define CONTEXT_S9 CONTEXT_X25 +#define CONTEXT_S10 CONTEXT_X26 +#define CONTEXT_S11 CONTEXT_X27 + +#define CONTEXT_A0 CONTEXT_X10 +#define CONTEXT_A1 CONTEXT_X11 +#define CONTEXT_A2 CONTEXT_X12 +#define CONTEXT_A3 CONTEXT_X13 +#define CONTEXT_A4 CONTEXT_X14 +#define CONTEXT_A5 CONTEXT_X15 +#define CONTEXT_A6 CONTEXT_X16 +#define CONTEXT_A7 CONTEXT_X17 + +#define CONTEXT_T0 CONTEXT_X5 +#define CONTEXT_T1 CONTEXT_X6 +#define CONTEXT_T2 CONTEXT_X7 +#define CONTEXT_T3 CONTEXT_X28 +#define CONTEXT_T4 CONTEXT_X29 +#define CONTEXT_T5 CONTEXT_X30 +#define CONTEXT_T6 CONTEXT_X31 + #define CONTEXT_F0 0 -#define CONTEXT_F1 CONTEXT_F1 + SIZEOF_RISCV64_FPR -#define CONTEXT_F2 CONTEXT_F2 + SIZEOF_RISCV64_FPR +#define CONTEXT_F1 CONTEXT_F0 + SIZEOF_RISCV64_FPR +#define CONTEXT_F2 CONTEXT_F1 + SIZEOF_RISCV64_FPR #define CONTEXT_F3 CONTEXT_F2 + SIZEOF_RISCV64_FPR #define CONTEXT_F4 CONTEXT_F3 + SIZEOF_RISCV64_FPR #define CONTEXT_F5 CONTEXT_F4 + SIZEOF_RISCV64_FPR diff --git a/src/coreclr/pal/src/arch/riscv64/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/riscv64/callsignalhandlerwrapper.S index a7cd5b6c4d2403..f286c9e5c66c93 100644 --- a/src/coreclr/pal/src/arch/riscv64/callsignalhandlerwrapper.S +++ b/src/coreclr/pal/src/arch/riscv64/callsignalhandlerwrapper.S @@ -4,4 +4,33 @@ #include "unixasmmacros.inc" #include "asmconstants.h" -#error "TODO-RISCV64: missing implementation" +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .dword LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler +__StackAllocationSize = (128 + 8 + 8 + \Alignment) // red zone + fp + ra + alignment + PROLOG_STACK_ALLOC __StackAllocationSize + .cfi_adjust_cfa_offset __StackAllocationSize + + PROLOG_SAVE_REG_PAIR fp, ra, 0 + + call signal_handler_worker + +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + EPILOG_RESTORE_REG_PAIR fp, ra, 0 + EPILOG_STACK_FREE __StackAllocationSize + .cfi_adjust_cfa_offset -__StackAllocationSize + ret + +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/src/coreclr/pal/src/arch/riscv64/context2.S b/src/coreclr/pal/src/arch/riscv64/context2.S index 8e3a01ac4f608a..653b60d7ecbdeb 100644 --- a/src/coreclr/pal/src/arch/riscv64/context2.S +++ b/src/coreclr/pal/src/arch/riscv64/context2.S @@ -9,4 +9,238 @@ #include "unixasmmacros.inc" #include "asmconstants.h" -#error "TODO-RISCV64: missing implementation" +// Incoming: +// a0: Context* +// a1: Exception* +// +LEAF_ENTRY RtlRestoreContext, _TEXT +#ifdef HAS_ASAN +#pragma error("TODO-RISCV64-CQ: unimplemented on RISCV64 yet") +#endif + + mv t4, a0 + lw t1, CONTEXT_ContextFlags(t4) + andi t1, t1, 0x1 << CONTEXT_FLOATING_POINT_BIT + beqz t1, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + + //64-bits FPR. + addi t0, t4, CONTEXT_FPU_OFFSET + + fld f0, (CONTEXT_F0)(t0) + fld f1, (CONTEXT_F1)(t0) + fld f2, (CONTEXT_F2)(t0) + fld f3, (CONTEXT_F3)(t0) + fld f4, (CONTEXT_F4)(t0) + fld f5, (CONTEXT_F5)(t0) + fld f6, (CONTEXT_F6)(t0) + fld f7, (CONTEXT_F7)(t0) + fld f8, (CONTEXT_F8)(t0) + fld f9, (CONTEXT_F9)(t0) + fld f10, (CONTEXT_F10)(t0) + fld f11, (CONTEXT_F11)(t0) + fld f12, (CONTEXT_F12)(t0) + fld f13, (CONTEXT_F13)(t0) + fld f14, (CONTEXT_F14)(t0) + fld f15, (CONTEXT_F15)(t0) + fld f16, (CONTEXT_F16)(t0) + fld f17, (CONTEXT_F17)(t0) + fld f18, (CONTEXT_F18)(t0) + fld f19, (CONTEXT_F19)(t0) + fld f20, (CONTEXT_F20)(t0) + fld f21, (CONTEXT_F21)(t0) + fld f22, (CONTEXT_F22)(t0) + fld f23, (CONTEXT_F23)(t0) + fld f24, (CONTEXT_F24)(t0) + fld f25, (CONTEXT_F25)(t0) + fld f26, (CONTEXT_F26)(t0) + fld f27, (CONTEXT_F27)(t0) + fld f28, (CONTEXT_F28)(t0) + fld f29, (CONTEXT_F29)(t0) + fld f30, (CONTEXT_F30)(t0) + fld f31, (CONTEXT_F31)(t0) + + lw t1, (CONTEXT_FLOAT_CONTROL_OFFSET)(t0) + fscsr x0, t1 + +LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): + + lw t1, CONTEXT_ContextFlags(t4) + andi t1, t1, 0x1 << CONTEXT_INTEGER_BIT + beqz t1, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + + ld tp, (CONTEXT_Tp)(a0) + ld gp, (CONTEXT_Gp)(a0) + ld a1, (CONTEXT_A1)(a0) + ld a2, (CONTEXT_A2)(a0) + ld a3, (CONTEXT_A3)(a0) + ld a4, (CONTEXT_A4)(a0) + ld a5, (CONTEXT_A5)(a0) + ld a6, (CONTEXT_A6)(a0) + ld a7, (CONTEXT_A7)(a0) + ld t0, (CONTEXT_T0)(a0) + ld t1, (CONTEXT_T1)(a0) + ld t2, (CONTEXT_T2)(a0) + ld t3, (CONTEXT_T3)(a0) + ld t5, (CONTEXT_T5)(a0) + ld t6, (CONTEXT_T6)(a0) + + ld s1, (CONTEXT_S1)(a0) + ld s2, (CONTEXT_S2)(a0) + ld s3, (CONTEXT_S3)(a0) + ld s4, (CONTEXT_S4)(a0) + ld s5, (CONTEXT_S5)(a0) + ld s6, (CONTEXT_S6)(a0) + ld s7, (CONTEXT_S7)(a0) + ld s8, (CONTEXT_S8)(a0) + ld s9, (CONTEXT_S9)(a0) + ld s10, (CONTEXT_S10)(a0) + ld s11, (CONTEXT_S11)(a0) + + ld a0, (CONTEXT_A0)(a0) + +LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): + + lw t1, CONTEXT_ContextFlags(t4) + andi t1, t1, 0x1 << CONTEXT_CONTROL_BIT + beqz t1, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + + ld ra, (CONTEXT_Ra)(t4) + ld fp, (CONTEXT_Fp)(t4) + ld sp, (CONTEXT_Sp)(t4) + ld t1, (CONTEXT_Pc)(t4) // Since we cannot control $pc directly, we're going to corrupt t1 + ld t4, (CONTEXT_T4)(t4) + jr t1 + +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + ld t4, (CONTEXT_T4)(t4) + ret +LEAF_END RtlRestoreContext, _TEXT + +// Incoming: +// a0: Context* + +LEAF_ENTRY RtlCaptureContext, _TEXT + PROLOG_STACK_ALLOC 16 + .cfi_adjust_cfa_offset 16 + sd t1, 0(sp) + li t1, CONTEXT_FULL + sw t1, CONTEXT_ContextFlags(a0) + ld t1, 0(sp) + EPILOG_STACK_FREE 16 + .cfi_adjust_cfa_offset -16 + tail CONTEXT_CaptureContext +LEAF_END RtlCaptureContext, _TEXT + +// Incoming: +// a0: Context* +// + +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + PROLOG_STACK_ALLOC 24 + .cfi_adjust_cfa_offset 24 + sd t0, 0(sp) + sd t1, 8(sp) + sd t3, 16(sp) + + lw t1, CONTEXT_ContextFlags(a0) + li t0, CONTEXT_CONTROL + and t3, t1, t0 + bne t3, t0, LOCAL_LABEL(Done_CONTEXT_CONTROL) + + addi t0, sp, 24 + sd fp, CONTEXT_Fp(a0) + sd t0, CONTEXT_Sp(a0) + sd ra, CONTEXT_Ra(a0) + sd ra, CONTEXT_Pc(a0) + +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + li t0, CONTEXT_INTEGER + and t3, t1, t0 + bne t3, t0, LOCAL_LABEL(Done_CONTEXT_INTEGER) + + ld t0, 0(sp) + ld t1, 8(sp) + ld t3, 16(sp) + + sd tp, (CONTEXT_Tp)(a0) + sd gp, (CONTEXT_Gp)(a0) + sd a0, (CONTEXT_A0)(a0) + sd a1, (CONTEXT_A1)(a0) + sd a2, (CONTEXT_A2)(a0) + sd a3, (CONTEXT_A3)(a0) + sd a4, (CONTEXT_A4)(a0) + sd a5, (CONTEXT_A5)(a0) + sd a6, (CONTEXT_A6)(a0) + sd a7, (CONTEXT_A7)(a0) + sd t0, (CONTEXT_T0)(a0) + sd t1, (CONTEXT_T1)(a0) + sd t2, (CONTEXT_T2)(a0) + sd t3, (CONTEXT_T3)(a0) + sd t4, (CONTEXT_T4)(a0) + sd t5, (CONTEXT_T5)(a0) + sd t6, (CONTEXT_T6)(a0) + + sd s1, (CONTEXT_S1)(a0) + sd s2, (CONTEXT_S2)(a0) + sd s3, (CONTEXT_S3)(a0) + sd s4, (CONTEXT_S4)(a0) + sd s5, (CONTEXT_S5)(a0) + sd s6, (CONTEXT_S6)(a0) + sd s7, (CONTEXT_S7)(a0) + sd s8, (CONTEXT_S8)(a0) + sd s9, (CONTEXT_S9)(a0) + sd s10, (CONTEXT_S10)(a0) + sd s11, (CONTEXT_S11)(a0) + +LOCAL_LABEL(Done_CONTEXT_INTEGER): + lw t1, CONTEXT_ContextFlags(a0) + + li t0, CONTEXT_FLOATING_POINT + and t3, t1, t0 + bne t3, t0, LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + + addi a0, a0, CONTEXT_FPU_OFFSET + + fsd f0, (CONTEXT_F0)(a0) + fsd f1, (CONTEXT_F1)(a0) + fsd f2, (CONTEXT_F2)(a0) + fsd f3, (CONTEXT_F3)(a0) + fsd f4, (CONTEXT_F4)(a0) + fsd f5, (CONTEXT_F5)(a0) + fsd f6, (CONTEXT_F6)(a0) + fsd f7, (CONTEXT_F7)(a0) + fsd f8, (CONTEXT_F8)(a0) + fsd f9, (CONTEXT_F9)(a0) + fsd f10, (CONTEXT_F10)(a0) + fsd f11, (CONTEXT_F11)(a0) + fsd f12, (CONTEXT_F12)(a0) + fsd f13, (CONTEXT_F13)(a0) + fsd f14, (CONTEXT_F14)(a0) + fsd f15, (CONTEXT_F15)(a0) + fsd f16, (CONTEXT_F16)(a0) + fsd f17, (CONTEXT_F17)(a0) + fsd f18, (CONTEXT_F18)(a0) + fsd f19, (CONTEXT_F19)(a0) + fsd f20, (CONTEXT_F20)(a0) + fsd f21, (CONTEXT_F21)(a0) + fsd f22, (CONTEXT_F22)(a0) + fsd f23, (CONTEXT_F23)(a0) + fsd f24, (CONTEXT_F24)(a0) + fsd f25, (CONTEXT_F25)(a0) + fsd f26, (CONTEXT_F26)(a0) + fsd f27, (CONTEXT_F27)(a0) + fsd f28, (CONTEXT_F28)(a0) + fsd f29, (CONTEXT_F29)(a0) + fsd f30, (CONTEXT_F30)(a0) + fsd f31, (CONTEXT_F31)(a0) + + frcsr t0 + sd t0, (CONTEXT_FLOAT_CONTROL_OFFSET)(a0) + +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + EPILOG_STACK_FREE 24 + .cfi_adjust_cfa_offset -24 + ret +LEAF_END CONTEXT_CaptureContext, _TEXT diff --git a/src/coreclr/pal/src/arch/riscv64/dispatchexceptionwrapper.S b/src/coreclr/pal/src/arch/riscv64/dispatchexceptionwrapper.S index 41f5e08472dfff..3ebace416d14a1 100644 --- a/src/coreclr/pal/src/arch/riscv64/dispatchexceptionwrapper.S +++ b/src/coreclr/pal/src/arch/riscv64/dispatchexceptionwrapper.S @@ -10,4 +10,4 @@ #include "unixasmmacros.inc" -#error "TODO-RISCV64: missing implementation" +// #error "TODO-RISCV64: missing implementation" diff --git a/src/coreclr/pal/src/arch/riscv64/exceptionhelper.S b/src/coreclr/pal/src/arch/riscv64/exceptionhelper.S index a7cd5b6c4d2403..8fc3c1bef3c623 100644 --- a/src/coreclr/pal/src/arch/riscv64/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/riscv64/exceptionhelper.S @@ -4,4 +4,45 @@ #include "unixasmmacros.inc" #include "asmconstants.h" -#error "TODO-RISCV64: missing implementation" +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and RA from the passed in context. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT +#ifdef HAS_ASAN +#pragma error("TODO-RISCV64-CQ: unimplemented on RISCV64 yet") +#endif + addi sp, sp, -16 + .cfi_adjust_cfa_offset 16 + + // Save the FP & RA to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + sd fp, 0(sp) + sd ra, 8(sp) + .cfi_rel_offset fp, 0 + .cfi_rel_offset ra, 8 + + ld tp, CONTEXT_Tp(a0) + ld gp, CONTEXT_Gp(a0) + ld s1, CONTEXT_S1(a0) + ld s2, CONTEXT_S2(a0) + ld s3, CONTEXT_S3(a0) + ld s4, CONTEXT_S4(a0) + ld s5, CONTEXT_S5(a0) + ld s6, CONTEXT_S6(a0) + ld s7, CONTEXT_S7(a0) + ld s8, CONTEXT_S8(a0) + ld s9, CONTEXT_S9(a0) + ld s10, CONTEXT_S10(a0) + ld s11, CONTEXT_S11(a0) + ld ra, CONTEXT_Ra(a0) + + ld fp, CONTEXT_Fp(a0) + ld sp, CONTEXT_Sp(a0) + + // The PAL_SEHException pointer + addi a0, a1, 0 + j ThrowExceptionHelper +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/arch/riscv64/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/riscv64/signalhandlerhelper.cpp index a4ce803b47afdb..1ad1d7b0d041c5 100644 --- a/src/coreclr/pal/src/arch/riscv64/signalhandlerhelper.cpp +++ b/src/coreclr/pal/src/arch/riscv64/signalhandlerhelper.cpp @@ -26,5 +26,48 @@ Parameters : --*/ void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) { -#error "TODO-RISCV64: missing implementation" + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + _ASSERTE(IS_ALIGNED(faultSp, 8)); + + if (customSp == 0) + { + // preserve 128 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 128, 16); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 16)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + } + + // preserve 128 bytes long red zone and align stack pointer + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + // pushed RA + *--sp = (size_t)MCREG_Pc(ucontext->uc_mcontext); + // pushed frame pointer + *--sp = (size_t)MCREG_Fp(ucontext->uc_mcontext); + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + context2.Sp = (size_t)sp; + context2.Fp = (size_t)sp; + context2.Ra = fakeFrameReturnAddress; + context2.Pc = (size_t)signal_handler_worker; + context2.A0 = code; + context2.A1 = (size_t)siginfo; + context2.A2 = (size_t)context; + context2.A3 = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); } diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index 22c72eeb709f08..0a6aba1fa3fc05 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -124,7 +124,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size #define PRId PRId32 #define PRIA "08" #define PRIxA PRIA PRIx -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) || defined(TARGET_RISCV64) #define PRIx PRIx64 #define PRIu PRIu64 #define PRId PRId64 @@ -1895,6 +1895,22 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_PPC64_R29, (SIZE_T **)&contextPointers->R29); GetContextPointer(cursor, unwContext, UNW_PPC64_R30, (SIZE_T **)&contextPointers->R30); GetContextPointer(cursor, unwContext, UNW_PPC64_R31, (SIZE_T **)&contextPointers->R31); +#elif defined(TARGET_RISCV64) + GetContextPointer(cursor, unwContext, UNW_RISCV_X1, (SIZE_T **)&contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_RISCV_X3, (SIZE_T **)&contextPointers->Gp); + GetContextPointer(cursor, unwContext, UNW_RISCV_X4, (SIZE_T **)&contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_RISCV_X8, (SIZE_T **)&contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_RISCV_X9, (SIZE_T **)&contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_RISCV_X18, (SIZE_T **)&contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_RISCV_X19, (SIZE_T **)&contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_RISCV_X20, (SIZE_T **)&contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_RISCV_X21, (SIZE_T **)&contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_RISCV_X22, (SIZE_T **)&contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_RISCV_X23, (SIZE_T **)&contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_RISCV_X24, (SIZE_T **)&contextPointers->S8); + GetContextPointer(cursor, unwContext, UNW_RISCV_X25, (SIZE_T **)&contextPointers->S9); + GetContextPointer(cursor, unwContext, UNW_RISCV_X26, (SIZE_T **)&contextPointers->S10); + GetContextPointer(cursor, unwContext, UNW_RISCV_X27, (SIZE_T **)&contextPointers->S11); #else #error unsupported architecture #endif @@ -2003,6 +2019,25 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_PPC64_R28, (unw_word_t *) &winContext->R28); unw_get_reg(cursor, UNW_PPC64_R29, (unw_word_t *) &winContext->R29); unw_get_reg(cursor, UNW_PPC64_R30, (unw_word_t *) &winContext->R30); +#elif defined(TARGET_RISCV64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_RISCV_X1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_RISCV_X3, (unw_word_t *) &winContext->Gp); + unw_get_reg(cursor, UNW_RISCV_X4, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_RISCV_X8, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_RISCV_X9, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_RISCV_X18, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_RISCV_X19, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_RISCV_X20, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_RISCV_X21, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_RISCV_X22, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_RISCV_X23, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_RISCV_X24, (unw_word_t *) &winContext->S8); + unw_get_reg(cursor, UNW_RISCV_X25, (unw_word_t *) &winContext->S9); + unw_get_reg(cursor, UNW_RISCV_X26, (unw_word_t *) &winContext->S10); + unw_get_reg(cursor, UNW_RISCV_X27, (unw_word_t *) &winContext->S11); + TRACE("sp %p gp %p fp %p tp %p ra %p\n", winContext->Sp, winContext->Gp, winContext->Fp, winContext->Tp, winContext->Ra); #else #error unsupported architecture #endif @@ -2138,6 +2173,23 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_PPC64_R30: *valp = (unw_word_t)winContext->R30; break; case UNW_PPC64_R31: *valp = (unw_word_t)winContext->R31; break; case UNW_PPC64_NIP: *valp = (unw_word_t)winContext->Nip; break; +#elif defined(TARGET_RISCV64) + case UNW_RISCV_X1: *valp = (unw_word_t)winContext->Ra; break; + case UNW_RISCV_X3: *valp = (unw_word_t)winContext->Gp; break; + case UNW_RISCV_X4: *valp = (unw_word_t)winContext->Tp; break; + case UNW_RISCV_X8: *valp = (unw_word_t)winContext->Fp; break; + case UNW_RISCV_X9: *valp = (unw_word_t)winContext->S1; break; + case UNW_RISCV_X18: *valp = (unw_word_t)winContext->S2; break; + case UNW_RISCV_X19: *valp = (unw_word_t)winContext->S3; break; + case UNW_RISCV_X20: *valp = (unw_word_t)winContext->S4; break; + case UNW_RISCV_X21: *valp = (unw_word_t)winContext->S5; break; + case UNW_RISCV_X22: *valp = (unw_word_t)winContext->S6; break; + case UNW_RISCV_X23: *valp = (unw_word_t)winContext->S7; break; + case UNW_RISCV_X24: *valp = (unw_word_t)winContext->S8; break; + case UNW_RISCV_X25: *valp = (unw_word_t)winContext->S9; break; + case UNW_RISCV_X26: *valp = (unw_word_t)winContext->S10; break; + case UNW_RISCV_X27: *valp = (unw_word_t)winContext->S11; break; + case UNW_RISCV_PC: *valp = (unw_word_t)winContext->Pc; break; #else #error unsupported architecture #endif diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 1a9773f3a8579f..8afe1ffb3db6fa 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -154,18 +154,15 @@ enum ASSIGN_REG(S8) #elif (defined(HOST_UNIX) && defined(HOST_RISCV64)) -#error "TODO-RISCV64: review this" - // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-cc.adoc #define ASSIGN_UNWIND_REGS \ ASSIGN_REG(Ra) \ ASSIGN_REG(Sp) \ - ASSIGN_REG(Sp) \ ASSIGN_REG(Gp) \ ASSIGN_REG(Tp) \ ASSIGN_REG(Pc) \ - ASSIGN_REG(S0) \ + ASSIGN_REG(Fp) \ ASSIGN_REG(S1) \ ASSIGN_REG(S2) \ ASSIGN_REG(S3) \ @@ -473,27 +470,15 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); #elif (defined(HOST_UNIX) && defined(HOST_RISCV64)) -#error "TODO-RISCV64: review this" - // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-cc.adoc unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); - unw_get_reg(cursor, UNW_RISCV_X1, (unw_word_t *) &winContext->Ra); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_RISCV_X1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_RISCV_X3, (unw_word_t *) &winContext->Gp); unw_get_reg(cursor, UNW_RISCV_X4, (unw_word_t *) &winContext->Tp); - unw_get_reg(cursor, UNW_RISCV_X5, (unw_word_t *) &winContext->T0); - unw_get_reg(cursor, UNW_RISCV_X6, (unw_word_t *) &winContext->T1); - unw_get_reg(cursor, UNW_RISCV_X7, (unw_word_t *) &winContext->T2); - unw_get_reg(cursor, UNW_RISCV_X8, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_RISCV_X8, (unw_word_t *) &winContext->Fp); unw_get_reg(cursor, UNW_RISCV_X9, (unw_word_t *) &winContext->S1); - unw_get_reg(cursor, UNW_RISCV_X10, (unw_word_t *) &winContext->A0); - unw_get_reg(cursor, UNW_RISCV_X11, (unw_word_t *) &winContext->A1); - unw_get_reg(cursor, UNW_RISCV_X12, (unw_word_t *) &winContext->A2); - unw_get_reg(cursor, UNW_RISCV_X13, (unw_word_t *) &winContext->A3); - unw_get_reg(cursor, UNW_RISCV_X14, (unw_word_t *) &winContext->A4); - unw_get_reg(cursor, UNW_RISCV_X15, (unw_word_t *) &winContext->A5); - unw_get_reg(cursor, UNW_RISCV_X16, (unw_word_t *) &winContext->A6); - unw_get_reg(cursor, UNW_RISCV_X17, (unw_word_t *) &winContext->A7); unw_get_reg(cursor, UNW_RISCV_X18, (unw_word_t *) &winContext->S2); unw_get_reg(cursor, UNW_RISCV_X19, (unw_word_t *) &winContext->S3); unw_get_reg(cursor, UNW_RISCV_X20, (unw_word_t *) &winContext->S4); @@ -504,10 +489,6 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_RISCV_X25, (unw_word_t *) &winContext->S9); unw_get_reg(cursor, UNW_RISCV_X26, (unw_word_t *) &winContext->S10); unw_get_reg(cursor, UNW_RISCV_X27, (unw_word_t *) &winContext->S11); - unw_get_reg(cursor, UNW_RISCV_X28, (unw_word_t *) &winContext->T3); - unw_get_reg(cursor, UNW_RISCV_X29, (unw_word_t *) &winContext->T4); - unw_get_reg(cursor, UNW_RISCV_X30, (unw_word_t *) &winContext->T5); - unw_get_reg(cursor, UNW_RISCV_X31, (unw_word_t *) &winContext->T6); #elif (defined(HOST_UNIX) && defined(HOST_POWERPC64)) unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->R31); unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Nip); @@ -627,24 +608,13 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, (SIZE_T **)&contextPointers->S7); GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, (SIZE_T **)&contextPointers->S8); #elif (defined(HOST_UNIX) && defined(HOST_RISCV64)) -#error "TODO-RISCV64: review this" - // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-cc.adoc GetContextPointer(cursor, unwContext, UNW_RISCV_X1, (SIZE_T **)&contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_RISCV_X3, (SIZE_T **)&contextPointers->Gp); GetContextPointer(cursor, unwContext, UNW_RISCV_X4, (SIZE_T **)&contextPointers->Tp); - GetContextPointer(cursor, unwContext, UNW_RISCV_X5, (SIZE_T **)&contextPointers->T0); - GetContextPointer(cursor, unwContext, UNW_RISCV_X7, (SIZE_T **)&contextPointers->T1); - GetContextPointer(cursor, unwContext, UNW_RISCV_X8, (SIZE_T **)&contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_RISCV_X8, (SIZE_T **)&contextPointers->Fp); GetContextPointer(cursor, unwContext, UNW_RISCV_X9, (SIZE_T **)&contextPointers->S1); - GetContextPointer(cursor, unwContext, UNW_RISCV_X10, (SIZE_T **)&contextPointers->A0); - GetContextPointer(cursor, unwContext, UNW_RISCV_X11, (SIZE_T **)&contextPointers->A1); - GetContextPointer(cursor, unwContext, UNW_RISCV_X12, (SIZE_T **)&contextPointers->A2); - GetContextPointer(cursor, unwContext, UNW_RISCV_X13, (SIZE_T **)&contextPointers->A3); - GetContextPointer(cursor, unwContext, UNW_RISCV_X14, (SIZE_T **)&contextPointers->A4); - GetContextPointer(cursor, unwContext, UNW_RISCV_X15, (SIZE_T **)&contextPointers->A5); - GetContextPointer(cursor, unwContext, UNW_RISCV_X16, (SIZE_T **)&contextPointers->A6); - GetContextPointer(cursor, unwContext, UNW_RISCV_X17, (SIZE_T **)&contextPointers->A7); GetContextPointer(cursor, unwContext, UNW_RISCV_X18, (SIZE_T **)&contextPointers->S2); GetContextPointer(cursor, unwContext, UNW_RISCV_X19, (SIZE_T **)&contextPointers->S3); GetContextPointer(cursor, unwContext, UNW_RISCV_X20, (SIZE_T **)&contextPointers->S4); @@ -655,10 +625,6 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_RISCV_X25, (SIZE_T **)&contextPointers->S9); GetContextPointer(cursor, unwContext, UNW_RISCV_X26, (SIZE_T **)&contextPointers->S10); GetContextPointer(cursor, unwContext, UNW_RISCV_X27, (SIZE_T **)&contextPointers->S11); - GetContextPointer(cursor, unwContext, UNW_RISCV_X28, (SIZE_T **)&contextPointers->T3); - GetContextPointer(cursor, unwContext, UNW_RISCV_X29, (SIZE_T **)&contextPointers->T4); - GetContextPointer(cursor, unwContext, UNW_RISCV_X30, (SIZE_T **)&contextPointers->T5); - GetContextPointer(cursor, unwContext, UNW_RISCV_X31, (SIZE_T **)&contextPointers->T6); #elif (defined(HOST_UNIX) && defined(HOST_POWERPC64)) GetContextPointer(cursor, unwContext, UNW_PPC64_R14, (SIZE_T **)&contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_PPC64_R15, (SIZE_T **)&contextPointers->R15); diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h index 2c860c2b7fac07..011860c904d369 100644 --- a/src/coreclr/pal/src/include/pal/context.h +++ b/src/coreclr/pal/src/include/pal/context.h @@ -161,7 +161,6 @@ bool Xstate_IsAvx512Supported(); #define MCREG_Pc(mc) ((mc).__pc) #elif defined(HOST_RISCV64) -#error "TODO-RISCV64: review this" #define MCREG_Ra(mc) ((mc).__gregs[1]) #define MCREG_Sp(mc) ((mc).__gregs[2]) @@ -170,7 +169,7 @@ bool Xstate_IsAvx512Supported(); #define MCREG_T0(mc) ((mc).__gregs[5]) #define MCREG_T1(mc) ((mc).__gregs[6]) #define MCREG_T2(mc) ((mc).__gregs[7]) -#define MCREG_S0(mc) ((mc).__gregs[8]) +#define MCREG_Fp(mc) ((mc).__gregs[8]) #define MCREG_S1(mc) ((mc).__gregs[9]) #define MCREG_A0(mc) ((mc).__gregs[10]) #define MCREG_A1(mc) ((mc).__gregs[11]) @@ -196,7 +195,7 @@ bool Xstate_IsAvx512Supported(); #define MCREG_T6(mc) ((mc).__gregs[31]) #define MCREG_Pc(mc) ((mc).__gregs[0]) -#else // HOST_LOONGARCH64 +#else // !HOST_LOONGARCH64 && !HOST_RISCV64 #define MCREG_Rbx(mc) ((mc).__gregs[_REG_RBX]) #define MCREG_Rcx(mc) ((mc).__gregs[_REG_RCX]) @@ -1292,8 +1291,6 @@ inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) return pContext->R11; #elif defined(HOST_POWERPC64) return pContext->R31; -#elif defined(HOST_RISCV64) - return pContext->S0; #else return pContext->Fp; #endif diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 0b0229548984c1..65f13be1333f0c 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -199,23 +199,20 @@ typedef int __ptrace_request; #elif defined(HOST_RISCV64) -#error "TODO-RISCV64: review this" - // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/2d865a2964fe06bfc569ab00c74e152b582ed764/riscv-cc.adoc #define ASSIGN_CONTROL_REGS \ ASSIGN_REG(Ra) \ ASSIGN_REG(Sp) \ - ASSIGN_REG(Sp) \ - ASSIGN_REG(Gp) \ - ASSIGN_REG(Tp) \ + ASSIGN_REG(Fp) \ ASSIGN_REG(Pc) #define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(Gp) \ + ASSIGN_REG(Tp) \ ASSIGN_REG(T0) \ ASSIGN_REG(T1) \ ASSIGN_REG(T2) \ - ASSIGN_REG(S0) \ ASSIGN_REG(S1) \ ASSIGN_REG(A0) \ ASSIGN_REG(A1) \ @@ -744,7 +741,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) } #elif defined(HOST_RISCV64) native->uc_mcontext.__fpregs.__d.__fcsr = lpContext->Fcsr; - for (int i = 0; i < 64; i++) + for (int i = 0; i < 32; i++) { native->uc_mcontext.__fpregs.__d.__f[i] = lpContext->F[i]; } @@ -938,7 +935,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex } #elif defined(HOST_RISCV64) lpContext->Fcsr = native->uc_mcontext.__fpregs.__d.__fcsr; - for (int i = 0; i < 64; i++) + for (int i = 0; i < 32; i++) { lpContext->F[i] = native->uc_mcontext.__fpregs.__d.__f[i]; }