Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Michal Shalev <mshalev@nvidia.com>
Mike Dubman <miked@mellanox.com>
Mikhail Brinskii <mikhailb@nvidia.com>
Min Fang <minf@nvidia.com>
Na Zhang <zhangna@loongson.cn>
Nathan Bellalou <nbellalou@nvidia.com>
Nathan Hjelm <hjelmn@lanl.gov>
Netanel Yosephian <netanelyo@mellanox.com>
Expand Down
3 changes: 2 additions & 1 deletion src/ucm/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ is `api/ucm.h`; everything else is internal.
- `mmap/` — installation of mmap-family hooks; uses `bistro/` to patch the
loader-resolved symbols when `LD_PRELOAD` is unavailable.
- `bistro/` — per-arch binary-instrumentation patcher
(`bistro_x86_64.c`, `bistro_aarch64.c`, `bistro_ppc64.c`, `bistro_rv64.c`).
(`bistro_x86_64.c`, `bistro_aarch64.c`, `bistro_ppc64.c`, `bistro_rv64.c`,
`bistro_loongarch64.c`).
Used to redirect glibc syscalls without `dlsym`.
- `util/` — supporting helpers: `replace.c` (PLT/GOT relocation),
`reloc.c` (ELF relocation walking), `log.c`, `sys.c`, `khash_safe.h`.
Expand Down
6 changes: 4 additions & 2 deletions src/ucm/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ noinst_HEADERS = \
bistro/bistro_x86_64.h \
bistro/bistro_aarch64.h \
bistro/bistro_ppc64.h \
bistro/bistro_rv64.h
bistro/bistro_rv64.h \
bistro/bistro_loongarch64.h
Comment thread
loongson-zn marked this conversation as resolved.
Resolved

libucm_la_SOURCES = \
event/event.c \
Expand All @@ -48,7 +49,8 @@ libucm_la_SOURCES = \
bistro/bistro_x86_64.c \
bistro/bistro_aarch64.c \
bistro/bistro_ppc64.c \
bistro/bistro_rv64.c
bistro/bistro_rv64.c \
bistro/bistro_loongarch64.c

if HAVE_UCM_PTMALLOC286
libucm_la_CPPFLAGS += \
Expand Down
3 changes: 2 additions & 1 deletion src/ucm/bistro/bistro.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ ucs_status_t ucm_bistro_apply_patch(void *dst, void *patch, size_t len)
return status;
}

#if defined(__x86_64__) || defined (__aarch64__) || defined (__riscv)
#if defined(__x86_64__) || defined(__aarch64__) || defined(__riscv) || \
defined(__loongarch_lp64)
struct ucm_bistro_restore_point {
void *addr; /* address of function to restore */
size_t patch_len; /* patch length */
Expand Down
2 changes: 2 additions & 0 deletions src/ucm/bistro/bistro.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ typedef struct ucm_bistro_restore_point ucm_bistro_restore_point_t;
# include "bistro_x86_64.h"
#elif defined(__riscv)
# include "bistro_rv64.h"
#elif defined(__loongarch_lp64)
# include "bistro_loongarch64.h"
#else
# error "Unsupported architecture"
#endif
Expand Down
129 changes: 129 additions & 0 deletions src/ucm/bistro/bistro_loongarch64.c
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
Comment thread
loongson-zn marked this conversation as resolved.
Resolved
# include "config.h"
#endif

#include <ucm/bistro/bistro.h>
Comment thread
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))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: offs16/offs26 are word-scaled (offs = imm << 2), but the doc comments describe them as plain immediates and the macros neither shift nor mask _imm. Harmless today (only 0 is passed) but a trap for the next user — please document it, otherwise a future non-zero value will silently corrupt the opcode.


/**
* 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,
Comment thread
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
58 changes: 58 additions & 0 deletions src/ucm/bistro/bistro_loongarch64.h
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
3 changes: 2 additions & 1 deletion src/ucs/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ no transport or protocol logic — only foundational utilities.
## Subdirectory Map

- `algorithm/` — `crc`, `qsort_r`, `string_distance`.
- `arch/` — per-CPU primitives (`x86_64`, `aarch64`, `ppc64`, `rv64`, `generic`):
- `arch/` — per-CPU primitives (`x86_64`, `aarch64`, `ppc64`, `rv64`,
`loongarch64`, `generic`):
atomics, bitops, cycle counter, `global_opts`, optimized memcpy.
- `async/` — async event dispatch, signal/thread/eventfd/pipe backends. Drives
worker progress for higher layers.
Expand Down
8 changes: 5 additions & 3 deletions src/ucs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ libucs_la_LIBADD = $(LIBM) $(top_builddir)/src/ucm/libucm.la $(BFD_LIBS)
nobase_dist_libucs_la_HEADERS = \
arch/aarch64/bitops.h \
arch/ppc64/bitops.h \
arch/rv64/bitops.h \
arch/generic/bitops.h \
arch/x86_64/bitops.h \
arch/bitops.h \
algorithm/crc.h \
Expand Down Expand Up @@ -87,13 +87,14 @@ nobase_dist_libucs_la_HEADERS = \
arch/x86_64/atomic.h \
arch/aarch64/global_opts.h \
arch/generic/atomic.h \
arch/generic/global_opts.h \
arch/ppc64/global_opts.h \
arch/rv64/global_opts.h \
arch/global_opts.h

noinst_HEADERS = \
arch/aarch64/cpu.h \
arch/generic/cpu.h \
Comment thread
loongson-zn marked this conversation as resolved.
Resolved
arch/loongarch64/cpu.h \
arch/ppc64/cpu.h \
arch/rv64/cpu.h \
arch/x86_64/cpu.h \
Expand Down Expand Up @@ -162,10 +163,11 @@ libucs_la_SOURCES = \
algorithm/string_distance.c \
arch/aarch64/cpu.c \
arch/aarch64/global_opts.c \
arch/generic/global_opts.c \
arch/loongarch64/cpu.c \
arch/ppc64/timebase.c \
arch/ppc64/global_opts.c \
arch/rv64/cpu.c \
arch/rv64/global_opts.c \
arch/x86_64/cpu.c \
arch/x86_64/global_opts.c \
arch/cpu.c \
Expand Down
2 changes: 2 additions & 0 deletions src/ucs/arch/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
# include "generic/atomic.h"
#elif defined(__riscv)
# include "generic/atomic.h"
#elif defined(__loongarch_lp64)
# include "generic/atomic.h"
#else
# error "Unsupported architecture"
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/ucs/arch/bitops.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ BEGIN_C_DECLS
# include "ppc64/bitops.h"
#elif defined(__aarch64__)
# include "aarch64/bitops.h"
#elif defined(__riscv)
# include "rv64/bitops.h"
#elif defined(__riscv) || defined(__loongarch_lp64)
# include "generic/bitops.h"
#else
# error "Unsupported architecture"
#endif
Expand Down
26 changes: 16 additions & 10 deletions src/ucs/arch/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ const ucs_cpu_builtin_memcpy_t ucs_cpu_builtin_memcpy[UCS_CPU_VENDOR_LAST] = {
[UCS_CPU_VENDOR_NVIDIA] = {
.min = UCS_MEMUNITS_INF,
.max = UCS_MEMUNITS_INF
},
[UCS_CPU_VENDOR_GENERIC_LOONGARCH64] = {
.min = UCS_MEMUNITS_INF,
.max = UCS_MEMUNITS_INF
}
};

Expand Down Expand Up @@ -162,15 +166,16 @@ size_t ucs_cpu_get_cache_size(ucs_cpu_cache_type_t type)
const char *ucs_cpu_vendor_name()
{
static const char *cpu_vendor_names[] = {
[UCS_CPU_VENDOR_UNKNOWN] = UCS_VALUE_UNKNOWN_STR,
[UCS_CPU_VENDOR_INTEL] = "Intel",
[UCS_CPU_VENDOR_AMD] = "AMD",
[UCS_CPU_VENDOR_GENERIC_ARM] = "Generic ARM",
[UCS_CPU_VENDOR_GENERIC_PPC] = "Generic PPC",
[UCS_CPU_VENDOR_GENERIC_RV64G] = "Generic RV64G",
[UCS_CPU_VENDOR_FUJITSU_ARM] = "Fujitsu ARM",
[UCS_CPU_VENDOR_ZHAOXIN] = "Zhaoxin",
[UCS_CPU_VENDOR_NVIDIA] = "Nvidia"
[UCS_CPU_VENDOR_UNKNOWN] = UCS_VALUE_UNKNOWN_STR,
[UCS_CPU_VENDOR_INTEL] = "Intel",
[UCS_CPU_VENDOR_AMD] = "AMD",
[UCS_CPU_VENDOR_GENERIC_ARM] = "Generic ARM",
[UCS_CPU_VENDOR_GENERIC_PPC] = "Generic PPC",
[UCS_CPU_VENDOR_GENERIC_RV64G] = "Generic RV64G",
[UCS_CPU_VENDOR_FUJITSU_ARM] = "Fujitsu ARM",
[UCS_CPU_VENDOR_ZHAOXIN] = "Zhaoxin",
[UCS_CPU_VENDOR_NVIDIA] = "Nvidia",
[UCS_CPU_VENDOR_GENERIC_LOONGARCH64] = "Generic LoongArch64"
Comment thread
loongson-zn marked this conversation as resolved.
Resolved
};

return cpu_vendor_names[ucs_arch_get_cpu_vendor()];
Expand Down Expand Up @@ -202,7 +207,8 @@ const char *ucs_cpu_model_name()
[UCS_CPU_MODEL_NVIDIA_GRACE] = "Grace",
[UCS_CPU_MODEL_NVIDIA_VERA] = "Vera",
[UCS_CPU_MODEL_FUJITSU_A64FX] = "FUJITSU-A64FX",
[UCS_CPU_MODEL_FUJITSU_MONAKA] = "FUJITSU-MONAKA"
[UCS_CPU_MODEL_FUJITSU_MONAKA] = "FUJITSU-MONAKA",
[UCS_CPU_MODEL_LOONGARCH64] = "LoongArch 64-bit"
};

return cpu_model_names[ucs_arch_get_cpu_model()];
Expand Down
4 changes: 4 additions & 0 deletions src/ucs/arch/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef enum ucs_cpu_model {
UCS_CPU_MODEL_NVIDIA_VERA,
UCS_CPU_MODEL_FUJITSU_A64FX,
UCS_CPU_MODEL_FUJITSU_MONAKA,
UCS_CPU_MODEL_LOONGARCH64,
UCS_CPU_MODEL_LAST
} ucs_cpu_model_t;

Expand Down Expand Up @@ -81,6 +82,7 @@ typedef enum ucs_cpu_vendor {
UCS_CPU_VENDOR_ZHAOXIN,
UCS_CPU_VENDOR_GENERIC_RV64G,
UCS_CPU_VENDOR_NVIDIA,
UCS_CPU_VENDOR_GENERIC_LOONGARCH64,
UCS_CPU_VENDOR_LAST
} ucs_cpu_vendor_t;

Expand Down Expand Up @@ -116,6 +118,8 @@ typedef struct ucs_cpu_builtin_memcpy {
# include "aarch64/cpu.h"
#elif defined(__riscv)
# include "rv64/cpu.h"
#elif defined(__loongarch_lp64)
# include "loongarch64/cpu.h"
#else
# error "Unsupported architecture"
#endif
Expand Down
Loading