Skip to content

Commit

Permalink
bcc: Add basic and usdt support for LoongArch
Browse files Browse the repository at this point in the history
The basic support for LoongArch has been merged into the upstream Linux
kernel since 5.19-rc1 on June 5, 2022, the kernel ABI definitions have
settled down.

In order to run the bcc scripts on LoongArch, add basic and usdt support.

Here is the LoongArch documention:
https://www.kernel.org/doc/html/latest/loongarch/index.html

Co-developed-by: Youling Tang <[email protected]>
Signed-off-by: Youling Tang <[email protected]>
Signed-off-by: Tiezhu Yang <[email protected]>
  • Loading branch information
Tiezhu Yang authored and yonghong-song committed Jul 22, 2022
1 parent dca2d00 commit cb23ebb
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 4 deletions.
4 changes: 3 additions & 1 deletion libbpf-tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ CFLAGS := -g -O2 -Wall
BPFCFLAGS := -g -O2 -Wall
INSTALL ?= install
prefix ?= /usr/local
ARCH := $(shell uname -m | sed 's/x86_64/x86/' | sed 's/aarch64/arm64/' | sed 's/ppc64le/powerpc/' | sed 's/mips.*/mips/' | sed 's/riscv64/riscv/')
ARCH := $(shell uname -m | sed 's/x86_64/x86/' | sed 's/aarch64/arm64/' \
| sed 's/ppc64le/powerpc/' | sed 's/mips.*/mips/' \
| sed 's/riscv64/riscv/' | sed 's/loongarch.*/loongarch/')
BTFHUB_ARCHIVE ?= $(abspath btfhub-archive)

ifeq ($(wildcard $(ARCH)/),)
Expand Down
17 changes: 17 additions & 0 deletions src/cc/export/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,9 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#elif defined(__TARGET_ARCH_riscv64)
#define bpf_target_riscv64
#define bpf_target_defined
#elif defined(__TARGET_ARCH_loongarch)
#define bpf_target_loongarch
#define bpf_target_defined
#else
#undef bpf_target_defined
#endif
Expand All @@ -1302,6 +1305,8 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define bpf_target_mips
#elif defined(__riscv) && (__riscv_xlen == 64)
#define bpf_target_riscv64
#elif defined(__loongarch__)
#define bpf_target_loongarch
#endif
#endif

Expand Down Expand Up @@ -1376,6 +1381,18 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_RC(x) (__PT_REGS_CAST(x)->a0)
#define PT_REGS_SP(x) (__PT_REGS_CAST(x)->sp)
#define PT_REGS_IP(x) (__PT_REGS_CAST(x)->pc)
#elif defined(bpf_target_loongarch)
#define PT_REGS_PARM1(x) ((x)->regs[4])
#define PT_REGS_PARM2(x) ((x)->regs[5])
#define PT_REGS_PARM3(x) ((x)->regs[6])
#define PT_REGS_PARM4(x) ((x)->regs[7])
#define PT_REGS_PARM5(x) ((x)->regs[8])
#define PT_REGS_PARM6(x) ((x)->regs[9])
#define PT_REGS_RET(x) ((x)->regs[1])
#define PT_REGS_FP(x) ((x)->regs[22]) /* Works only with CONFIG_FRAME_POINTER */
#define PT_REGS_RC(x) ((x)->regs[4])
#define PT_REGS_SP(x) ((x)->regs[3])
#define PT_REGS_IP(x) ((x)->csr_era)
#else
#error "bcc does not support this platform yet"
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/cc/frontends/clang/arch_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef enum {
BCC_ARCH_ARM64,
BCC_ARCH_MIPS,
BCC_ARCH_RISCV64,
BCC_ARCH_LOONGARCH,
BCC_ARCH_X86
} bcc_arch_t;

Expand All @@ -49,6 +50,8 @@ static void *run_arch_callback(arch_callback_t fn, bool for_syscall = false)
return fn(BCC_ARCH_MIPS, for_syscall);
#elif defined(__riscv) && (__riscv_xlen == 64)
return fn(BCC_ARCH_RISCV64, for_syscall);
#elif defined(__loongarch__)
return fn(BCC_ARCH_LOONGARCH, for_syscall);
#else
return fn(BCC_ARCH_X86, for_syscall);
#endif
Expand All @@ -69,6 +72,8 @@ static void *run_arch_callback(arch_callback_t fn, bool for_syscall = false)
return fn(BCC_ARCH_MIPS, for_syscall);
} else if (!strcmp(archenv, "riscv64")) {
return fn(BCC_ARCH_RISCV64, for_syscall);
} else if (!strcmp(archenv, "loongarch")) {
return fn(BCC_ARCH_LOONGARCH, for_syscall);
} else {
return fn(BCC_ARCH_X86, for_syscall);
}
Expand Down
7 changes: 7 additions & 0 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const char *calling_conv_regs_mips[] = {"regs[4]", "regs[5]", "regs[6]",
const char *calling_conv_regs_riscv64[] = {"a0", "a1", "a2",
"a3", "a4", "a5"};

const char *calling_conv_regs_loongarch[] = {"regs[4]", "regs[5]", "regs[6]",
"regs[7]", "regs[8]", "regs[9]"};


void *get_call_conv_cb(bcc_arch_t arch, bool for_syscall)
{
const char **ret;
Expand All @@ -84,6 +88,9 @@ void *get_call_conv_cb(bcc_arch_t arch, bool for_syscall)
case BCC_ARCH_RISCV64:
ret = calling_conv_regs_riscv64;
break;
case BCC_ARCH_LOONGARCH:
ret = calling_conv_regs_loongarch;
break;
default:
if (for_syscall)
ret = calling_conv_syscall_regs_x86;
Expand Down
4 changes: 3 additions & 1 deletion src/cc/frontends/clang/kbuild_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
//uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ -e s/sun4u/sparc64/ -e s/arm.*/arm/
// -e s/sa110/arm/ -e s/s390x/s390/ -e s/parisc64/parisc/
// -e s/ppc.*/powerpc/ -e s/mips.*/mips/ -e s/sh[234].*/sh/
// -e s/aarch64.*/arm64/
// -e s/aarch64.*/arm64/ -e s/loongarch.*/loongarch/

string arch;
const char *archenv = getenv("ARCH");
Expand Down Expand Up @@ -68,6 +68,8 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
arch = "mips";
} else if (!arch.compare(0, 5, "riscv")) {
arch = "riscv";
} else if (!arch.compare(0, 9, "loongarch")) {
arch = "loongarch";
} else if (!arch.compare(0, 2, "sh")) {
arch = "sh";
}
Expand Down
3 changes: 3 additions & 0 deletions src/cc/frontends/clang/loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ void *get_clang_target_cb(bcc_arch_t arch, bool for_syscall)
case BCC_ARCH_RISCV64:
ret = "riscv64-unknown-linux-gnu";
break;
case BCC_ARCH_LOONGARCH:
ret = "loongarch64-unknown-linux-gnu";
break;
default:
ret = "x86_64-unknown-linux-gnu";
}
Expand Down
12 changes: 12 additions & 0 deletions src/cc/usdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Argument {

friend class ArgumentParser;
friend class ArgumentParser_aarch64;
friend class ArgumentParser_loongarch64;
friend class ArgumentParser_powerpc64;
friend class ArgumentParser_s390x;
friend class ArgumentParser_x64;
Expand Down Expand Up @@ -134,6 +135,17 @@ class ArgumentParser_aarch64 : public ArgumentParser {
ArgumentParser_aarch64(const char *arg) : ArgumentParser(arg) {}
};

class ArgumentParser_loongarch64 : public ArgumentParser {
private:
bool parse_register(ssize_t pos, ssize_t &new_pos, std::string &reg_name);
bool parse_size(ssize_t pos, ssize_t &new_pos, optional<int> *arg_size);
bool parse_mem(ssize_t pos, ssize_t &new_pos, Argument *dest);

public:
bool parse(Argument *dest);
ArgumentParser_loongarch64(const char *arg) : ArgumentParser(arg) {}
};

class ArgumentParser_powerpc64 : public ArgumentParser {
public:
bool parse(Argument *dest);
Expand Down
2 changes: 2 additions & 0 deletions src/cc/usdt/usdt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Location::Location(uint64_t addr, const std::string &bin_path, const char *arg_f

#ifdef __aarch64__
ArgumentParser_aarch64 parser(arg_fmt);
#elif __loongarch64
ArgumentParser_loongarch64 parser(arg_fmt);
#elif __powerpc64__
ArgumentParser_powerpc64 parser(arg_fmt);
#elif __s390x__
Expand Down
115 changes: 115 additions & 0 deletions src/cc/usdt/usdt_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,121 @@ bool ArgumentParser_aarch64::parse(Argument *dest) {
return true;
}

bool ArgumentParser_loongarch64::parse_register(ssize_t pos, ssize_t &new_pos,
std::string &reg_name) {
if (arg_[pos] == '$' && arg_[pos + 1] == 'r') {
optional<int> reg_num;
new_pos = parse_number(pos + 2, &reg_num);
if (new_pos == pos + 2 || *reg_num < 0 || *reg_num > 31)
return error_return(pos + 2, pos + 2);

if (*reg_num == 3) {
reg_name = "sp";
} else {
reg_name = "regs[" + std::to_string(reg_num.value()) + "]";
}
return true;
} else if (arg_[pos] == 's' && arg_[pos + 1] == 'p') {
reg_name = "sp";
new_pos = pos + 2;
return true;
} else {
return error_return(pos, pos);
}
}

bool ArgumentParser_loongarch64::parse_size(ssize_t pos, ssize_t &new_pos,
optional<int> *arg_size) {
int abs_arg_size;

new_pos = parse_number(pos, arg_size);
if (new_pos == pos)
return error_return(pos, pos);

abs_arg_size = abs(arg_size->value());
if (abs_arg_size != 1 && abs_arg_size != 2 && abs_arg_size != 4 &&
abs_arg_size != 8)
return error_return(pos, pos);
return true;
}

bool ArgumentParser_loongarch64::parse_mem(ssize_t pos, ssize_t &new_pos,
Argument *dest) {
std::string base_reg_name, index_reg_name;

if (parse_register(pos, new_pos, base_reg_name) == false)
return false;
dest->base_register_name_ = base_reg_name;

if (arg_[new_pos] == ',') {
pos = new_pos + 1;
new_pos = parse_number(pos, &dest->deref_offset_);
if (new_pos == pos) {
// offset isn't a number, so it should be a reg,
// which looks like: -1@[$r0, $r1], rather than -1@[$r0, 24]
skip_whitespace_from(pos);
pos = cur_pos_;
if (parse_register(pos, new_pos, index_reg_name) == false)
return error_return(pos, pos);
dest->index_register_name_ = index_reg_name;
dest->scale_ = 1;
dest->deref_offset_ = 0;
}
}
if (arg_[new_pos] != ']')
return error_return(new_pos, new_pos);
new_pos++;
return true;
}

bool ArgumentParser_loongarch64::parse(Argument *dest) {
if (done())
return false;

// Support the following argument patterns:
// [-]<size>@<value>, [-]<size>@<reg>, [-]<size>@[<reg>], or
// [-]<size>@[<reg>,<offset>]
// [-]<size>@[<reg>,<index_reg>]
ssize_t cur_pos = cur_pos_, new_pos;
optional<int> arg_size;

// Parse [-]<size>
if (parse_size(cur_pos, new_pos, &arg_size) == false)
return false;
dest->arg_size_ = arg_size;

// Make sure '@' present
if (arg_[new_pos] != '@')
return error_return(new_pos, new_pos);
cur_pos = new_pos + 1;

if (arg_[cur_pos] == '$' || arg_[cur_pos] == 's') {
// Parse ...@<reg>
std::string reg_name;
if (parse_register(cur_pos, new_pos, reg_name) == false)
return false;

cur_pos_ = new_pos;
dest->base_register_name_ = reg_name;
} else if (arg_[cur_pos] == '[') {
// Parse ...@[<reg>], ...@[<reg,<offset>] and ...@[<reg>,<index_reg>]
if (parse_mem(cur_pos + 1, new_pos, dest) == false)
return false;
cur_pos_ = new_pos;
} else {
// Parse ...@<value>
optional<long long> val;
new_pos = parse_number(cur_pos, &val);
if (cur_pos == new_pos)
return error_return(cur_pos, cur_pos);
cur_pos_ = new_pos;
dest->constant_ = val;
}

skip_whitespace_from(cur_pos_);
return true;
}

bool ArgumentParser_powerpc64::parse(Argument *dest) {
if (done())
return false;
Expand Down
16 changes: 14 additions & 2 deletions tests/cc/test_usdt_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,16 @@ static void verify_register(USDT::ArgumentParser &parser, int arg_size,
}

/* supported arches only */
#if defined(__aarch64__) || defined(__powerpc64__) || \
defined(__s390x__) || defined(__x86_64__)
#if defined(__aarch64__) || defined(__loongarch64) || \
defined(__powerpc64__) || defined(__s390x__) || \
defined(__x86_64__)

TEST_CASE("test usdt argument parsing", "[usdt]") {
SECTION("parse failure") {
#ifdef __aarch64__
USDT::ArgumentParser_aarch64 parser("4@[x32,200]");
#elif __loongarch64
USDT::ArgumentParser_loongarch64 parser("4@[$r32,200]");
#elif __powerpc64__
USDT::ArgumentParser_powerpc64 parser("4@-12(42)");
#elif __s390x__
Expand All @@ -86,6 +89,15 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
verify_register(parser, -4, "regs[30]", -40);
verify_register(parser, -4, "sp", -40);
verify_register(parser, 8, "sp", 120);
#elif __loongarch64
USDT::ArgumentParser_loongarch64 parser(
"-1@$r0 4@5 8@[$r12] -4@[$r30,-40] -4@[$r3,-40] 8@[sp, 120]");
verify_register(parser, -1, "regs[0]");
verify_register(parser, 4, 5);
verify_register(parser, 8, "regs[12]", 0);
verify_register(parser, -4, "regs[30]", -40);
verify_register(parser, -4, "sp", -40);
verify_register(parser, 8, "sp", 120);
#elif __powerpc64__
USDT::ArgumentParser_powerpc64 parser(
"-4@0 8@%r0 8@i0 4@0(%r0) -2@0(0) "
Expand Down

0 comments on commit cb23ebb

Please sign in to comment.