Repository navigation
UCS/ARCH/LOONGARCH64: Add loongarch64 support #12187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| /** | ||
| * Copyright (C) Na Zhang, 2026. ALL RIGHTS RESERVED. | ||
| * | ||
| * See file LICENSE for terms. | ||
| */ | ||
|
|
||
| #if defined(__loongarch_lp64) | ||
|
|
||
| #ifdef HAVE_CONFIG_H | ||
|
loongson-zn marked this conversation as resolved.
Resolved
|
||
| # include "config.h" | ||
| #endif | ||
|
|
||
| #include <ucm/bistro/bistro.h> | ||
|
loongson-zn marked this conversation as resolved.
Resolved
|
||
| #include <ucm/bistro/bistro_int.h> | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| /* LoongArch general-purpose register numbers used by the trampoline */ | ||
| #define UCM_BISTRO_LA_REG_ZERO 0 | ||
| #define UCM_BISTRO_LA_REG_T0 12 | ||
| #define UCM_BISTRO_LA_REG_T2 14 | ||
|
|
||
| /** | ||
| * JIRL - Add a 16-bit immediate to a source register, save the return address | ||
| * into a destination register, and jump to the source register. | ||
| * | ||
| * Encoding: opcode | offs16 | rj | rd | ||
| * | ||
| * @param[in] _regd destination register number (0-31) | ||
| * @param[in] _regj source register number (0-31) | ||
| * @param[in] _imm 16-bit branch offset, word-scaled (in units of 4-byte | ||
| * instructions; the hardware computes rj + (offs << 2)) | ||
| */ | ||
| #define UCM_BISTRO_LA_JIRL(_regd, _regj, _imm) \ | ||
| (0x4c000000 | ((_imm) << 10) | ((_regj) << 5) | (_regd)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: |
||
|
|
||
| /** | ||
| * B - unconditional branch (jump to self when the immediate is 0) | ||
| * | ||
| * Encoding: opcode | offs[15:0] | offs[25:16] | ||
| * | ||
| * @param[in] _imm 26-bit branch offset, word-scaled (in units of 4-byte | ||
| * instructions; the hardware computes pc + (offs << 2)) | ||
| */ | ||
| #define UCM_BISTRO_LA_B(_imm) \ | ||
| (0x50000000 | (((_imm) & 0xffff) << 10) | (((_imm) >> 16) & 0x3ff)) | ||
|
|
||
| /** | ||
| * PCADDU12I - Add an upper 20-bit immediate (shifted by 12) to the PC | ||
| * | ||
| * Encoding: opcode | si20 | rd | ||
| * | ||
| * @param[in] _regd destination register number (0-31) | ||
| * @param[in] _imm 20-bit immediate value | ||
| */ | ||
| #define UCM_BISTRO_LA_PCADDU12I(_regd, _imm) \ | ||
| (0x1c000000 | ((_imm) << 5) | (_regd)) | ||
|
|
||
| /** | ||
| * LD - Load a doubleword from memory using a register plus a 12-bit immediate | ||
| * | ||
| * Encoding: opcode | si12 | rj | rd | ||
| * | ||
| * @param[in] _regd destination register number (0-31) | ||
| * @param[in] _regj source register number (0-31) | ||
| * @param[in] _imm 12-bit immediate value | ||
| */ | ||
| #define UCM_BISTRO_LA_LD(_regd, _regj, _imm) \ | ||
| (0x28c00000 | ((_imm) << 10) | ((_regj) << 5) | (_regd)) | ||
|
|
||
| /** | ||
| * BREAK - trap with an immediate code, used to stop control flow | ||
| * | ||
| * @param[in] _code 15-bit code | ||
| */ | ||
| #define UCM_BISTRO_LA_BREAK(_code) \ | ||
| (0x002a0000 | ((_code) & 0x7fff)) | ||
|
|
||
| void ucm_bistro_patch_lock(void *dst) | ||
| { | ||
| static const ucm_bistro_lock_t self_jmp = { | ||
| .j = UCM_BISTRO_LA_B(0) | ||
| }; | ||
|
|
||
| ucm_bistro_modify_code(dst, &self_jmp); | ||
| } | ||
|
|
||
| ucs_status_t ucm_bistro_patch(void *func_ptr, void *hook, const char *symbol, | ||
| void **orig_func_p, | ||
| ucm_bistro_restore_point_t **rp) | ||
| { | ||
| /* | ||
| * The trampoline below computes the address of the patched instruction | ||
| * (pcaddu12i), loads the hook address stored right after the four | ||
| * instruction words (at offset 0x10), and jumps to it: | ||
| * | ||
| * pcaddu12i $t0, 0 # $t0 = address of this instruction | ||
| * ld.d $t2, $t0, 0x10 # $t2 = *(patch + 0x10) = hook | ||
| * jirl $zero, $t2, 0 # jump to hook | ||
| */ | ||
| ucm_bistro_patch_t patch = { | ||
| .pcaddu12i = UCM_BISTRO_LA_PCADDU12I(UCM_BISTRO_LA_REG_T0, 0), | ||
| .ld = UCM_BISTRO_LA_LD(UCM_BISTRO_LA_REG_T2, | ||
|
loongson-zn marked this conversation as resolved.
Resolved
|
||
| UCM_BISTRO_LA_REG_T0, 0x10), | ||
| .jirl = UCM_BISTRO_LA_JIRL(UCM_BISTRO_LA_REG_ZERO, | ||
| UCM_BISTRO_LA_REG_T2, 0), | ||
| .spare = UCM_BISTRO_LA_BREAK(0), | ||
| .address = (uintptr_t)hook | ||
| }; | ||
| ucs_status_t status; | ||
|
|
||
| if (orig_func_p != NULL) { | ||
| return UCS_ERR_UNSUPPORTED; | ||
| } | ||
|
|
||
| status = ucm_bistro_create_restore_point(func_ptr, sizeof(patch), rp); | ||
| if (UCS_STATUS_IS_ERR(status)) { | ||
| return status; | ||
| } | ||
|
|
||
| return ucm_bistro_apply_patch_atomic(func_ptr, &patch, sizeof(patch)); | ||
| } | ||
|
|
||
| ucs_status_t ucm_bistro_relocate_one(ucm_bistro_relocate_context_t *ctx) | ||
| { | ||
| return UCS_ERR_UNSUPPORTED; | ||
| } | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| /** | ||
| * Copyright (C) Na Zhang, 2026. ALL RIGHTS RESERVED. | ||
| * | ||
| * See file LICENSE for terms. | ||
| */ | ||
|
|
||
|
|
||
| #ifndef UCM_BISTRO_BISTRO_LOONGARCH64_H_ | ||
| #define UCM_BISTRO_BISTRO_LOONGARCH64_H_ | ||
|
|
||
| #include <ucs/type/status.h> | ||
| #include <ucs/sys/compiler_def.h> | ||
|
|
||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #define UCM_BISTRO_PROLOGUE | ||
| #define UCM_BISTRO_EPILOGUE | ||
|
|
||
| typedef struct ucm_bistro_patch { | ||
| uint32_t pcaddu12i; | ||
| uint32_t ld; | ||
| uint32_t jirl; | ||
| uint32_t spare; | ||
| uint64_t address; | ||
| } UCS_S_PACKED ucm_bistro_patch_t; | ||
|
|
||
|
|
||
| /** | ||
| * Set library function call hook using Binary Instrumentation | ||
| * method (BISTRO): replace function body by user defined call | ||
| * | ||
| * @param func_ptr Pointer to function to patch. | ||
| * @param hook User-defined replacement function. | ||
| * @param symbol Function name to replace. | ||
| * @param orig_func_p Unsupported on this architecture and must be NULL. | ||
| * If set to a non-NULL value, this function returns | ||
| * @ref UCS_ERR_UNSUPPORTED. | ||
| * @param rp Restore point used to restore original function. | ||
| * Optional, may be NULL. | ||
| * | ||
| * @return Error code as defined by @ref ucs_status_t | ||
| */ | ||
| ucs_status_t ucm_bistro_patch(void *func_ptr, void *hook, const char *symbol, | ||
| void **orig_func_p, | ||
| ucm_bistro_restore_point_t **rp); | ||
|
|
||
| /* Lock implementation */ | ||
| typedef struct { | ||
| uint32_t j; /* jump to self */ | ||
| } UCS_S_PACKED ucm_bistro_lock_t; | ||
|
|
||
| /** | ||
| * Helper functions to improve atomicity of function patching | ||
| */ | ||
| void ucm_bistro_patch_lock(void *dst); | ||
|
|
||
| #endif |
Uh oh!
There was an error while loading. Please reload this page.