Skip to content

Commit

Permalink
Merge branch 'bpf-MIPS-infra'
Browse files Browse the repository at this point in the history
David Daney says:

====================
bpf: Changes needed (or desired) for MIPS support

This is a grab bag of changes to the bpf testing infrastructure I
developed working on MIPS eBPF JIT support.  The change to
bpf_jit_disasm is probably universally beneficial, the others are more
MIPS specific.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 14, 2017
2 parents 2fae5d0 + 4b7190e commit 4071bd8
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 14 deletions.
32 changes: 32 additions & 0 deletions lib/test_bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,30 @@ static int bpf_fill_ld_abs_vlan_push_pop(struct bpf_test *self)
return 0;
}

static int bpf_fill_jump_around_ld_abs(struct bpf_test *self)
{
unsigned int len = BPF_MAXINSNS;
struct bpf_insn *insn;
int i = 0;

insn = kmalloc_array(len, sizeof(*insn), GFP_KERNEL);
if (!insn)
return -ENOMEM;

insn[i++] = BPF_MOV64_REG(R6, R1);
insn[i++] = BPF_LD_ABS(BPF_B, 0);
insn[i] = BPF_JMP_IMM(BPF_JEQ, R0, 10, len - i - 2);
i++;
while (i < len - 1)
insn[i++] = BPF_LD_ABS(BPF_B, 1);
insn[i] = BPF_EXIT_INSN();

self->u.ptr.insns = insn;
self->u.ptr.len = len;

return 0;
}

static int __bpf_fill_stxdw(struct bpf_test *self, int size)
{
unsigned int len = BPF_MAXINSNS;
Expand Down Expand Up @@ -5044,6 +5068,14 @@ static struct bpf_test tests[] = {
{ { ETH_HLEN, 0xbef } },
.fill_helper = bpf_fill_ld_abs_vlan_push_pop,
},
{
"BPF_MAXINSNS: jump around ld_abs",
{ },
INTERNAL,
{ 10, 11 },
{ { 2, 10 } },
.fill_helper = bpf_fill_jump_around_ld_abs,
},
/*
* LD_IND / LD_ABS on fragmented SKBs
*/
Expand Down
13 changes: 13 additions & 0 deletions samples/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ clean:
$(MAKE) -C ../../ M=$(CURDIR) clean
@rm -f *~

$(obj)/syscall_nrs.s: $(src)/syscall_nrs.c
$(call if_changed_dep,cc_s_c)

$(obj)/syscall_nrs.h: $(obj)/syscall_nrs.s FORCE
$(call filechk,offsets,__SYSCALL_NRS_H__)

clean-files += syscall_nrs.h

FORCE:


# Verify LLVM compiler tools are available and bpf target is supported by llc
.PHONY: verify_cmds verify_target_bpf $(CLANG) $(LLC)

Expand All @@ -180,6 +191,8 @@ verify_target_bpf: verify_cmds

$(src)/*.c: verify_target_bpf

$(obj)/tracex5_kern.o: $(obj)/syscall_nrs.h

# asm/sysreg.h - inline assembly used by it is incompatible with llvm.
# But, there is no easy way to fix it, so just exclude it since it is
# useless for BPF samples.
Expand Down
13 changes: 13 additions & 0 deletions samples/bpf/bpf_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,19 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->pc)

#elif defined(__mips__)

#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_RET(x) ((x)->regs[31])
#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */
#define PT_REGS_RC(x) ((x)->regs[1])
#define PT_REGS_SP(x) ((x)->regs[29])
#define PT_REGS_IP(x) ((x)->cp0_epc)

#elif defined(__powerpc__)

#define PT_REGS_PARM1(x) ((x)->gpr[3])
Expand Down
12 changes: 12 additions & 0 deletions samples/bpf/syscall_nrs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <uapi/linux/unistd.h>
#include <linux/kbuild.h>

#define SYSNR(_NR) DEFINE(SYS ## _NR, _NR)

void syscall_defines(void)
{
COMMENT("Linux system call numbers.");
SYSNR(__NR_write);
SYSNR(__NR_read);
SYSNR(__NR_mmap);
}
11 changes: 8 additions & 3 deletions samples/bpf/tracex5_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <uapi/linux/bpf.h>
#include <uapi/linux/seccomp.h>
#include <uapi/linux/unistd.h>
#include "syscall_nrs.h"
#include "bpf_helpers.h"

#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F
Expand All @@ -17,7 +18,11 @@ struct bpf_map_def SEC("maps") progs = {
.type = BPF_MAP_TYPE_PROG_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(u32),
#ifdef __mips__
.max_entries = 6000, /* MIPS n64 syscalls start at 5000 */
#else
.max_entries = 1024,
#endif
};

SEC("kprobe/__seccomp_filter")
Expand All @@ -37,7 +42,7 @@ int bpf_prog1(struct pt_regs *ctx)
}

/* we jump here when syscall number == __NR_write */
PROG(__NR_write)(struct pt_regs *ctx)
PROG(SYS__NR_write)(struct pt_regs *ctx)
{
struct seccomp_data sd;

Expand All @@ -50,7 +55,7 @@ PROG(__NR_write)(struct pt_regs *ctx)
return 0;
}

PROG(__NR_read)(struct pt_regs *ctx)
PROG(SYS__NR_read)(struct pt_regs *ctx)
{
struct seccomp_data sd;

Expand All @@ -63,7 +68,7 @@ PROG(__NR_read)(struct pt_regs *ctx)
return 0;
}

PROG(__NR_mmap)(struct pt_regs *ctx)
PROG(SYS__NR_mmap)(struct pt_regs *ctx)
{
char fmt[] = "mmap\n";
bpf_trace_printk(fmt, sizeof(fmt));
Expand Down
37 changes: 26 additions & 11 deletions tools/net/bpf_jit_disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,19 @@ static void put_log_buff(char *buff)
free(buff);
}

static unsigned int get_last_jit_image(char *haystack, size_t hlen,
uint8_t *image, size_t ilen)
static uint8_t *get_last_jit_image(char *haystack, size_t hlen,
unsigned int *ilen)
{
char *ptr, *pptr, *tmp;
off_t off = 0;
int ret, flen, proglen, pass, ulen = 0;
regmatch_t pmatch[1];
unsigned long base;
regex_t regex;
uint8_t *image;

if (hlen == 0)
return 0;
return NULL;

ret = regcomp(&regex, "flen=[[:alnum:]]+ proglen=[[:digit:]]+ "
"pass=[[:digit:]]+ image=[[:xdigit:]]+", REG_EXTENDED);
Expand All @@ -194,11 +195,22 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
&flen, &proglen, &pass, &base);
if (ret != 4) {
regfree(&regex);
return 0;
return NULL;
}
if (proglen > 1000000) {
printf("proglen of %d too big, stopping\n", proglen);
return NULL;
}

image = malloc(proglen);
if (!image) {
printf("Out of memory\n");
return NULL;
}
memset(image, 0, proglen);

tmp = ptr = haystack + off;
while ((ptr = strtok(tmp, "\n")) != NULL && ulen < ilen) {
while ((ptr = strtok(tmp, "\n")) != NULL && ulen < proglen) {
tmp = NULL;
if (!strstr(ptr, "JIT code"))
continue;
Expand All @@ -208,10 +220,12 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
ptr = pptr;
do {
image[ulen++] = (uint8_t) strtoul(pptr, &pptr, 16);
if (ptr == pptr || ulen >= ilen) {
if (ptr == pptr) {
ulen--;
break;
}
if (ulen >= proglen)
break;
ptr = pptr;
} while (1);
}
Expand All @@ -222,7 +236,8 @@ static unsigned int get_last_jit_image(char *haystack, size_t hlen,
printf("%lx + <x>:\n", base);

regfree(&regex);
return ulen;
*ilen = ulen;
return image;
}

static void usage(void)
Expand All @@ -237,12 +252,12 @@ static void usage(void)
int main(int argc, char **argv)
{
unsigned int len, klen, opt, opcodes = 0;
static uint8_t image[32768];
char *kbuff, *file = NULL;
char *ofile = NULL;
int ofd;
ssize_t nr;
uint8_t *pos;
uint8_t *image = NULL;

while ((opt = getopt(argc, argv, "of:O:")) != -1) {
switch (opt) {
Expand All @@ -262,16 +277,15 @@ int main(int argc, char **argv)
}

bfd_init();
memset(image, 0, sizeof(image));

kbuff = get_log_buff(file, &klen);
if (!kbuff) {
fprintf(stderr, "Could not retrieve log buffer!\n");
return -1;
}

len = get_last_jit_image(kbuff, klen, image, sizeof(image));
if (len <= 0) {
image = get_last_jit_image(kbuff, klen, &len);
if (!image) {
fprintf(stderr, "No JIT image found!\n");
goto done;
}
Expand Down Expand Up @@ -301,5 +315,6 @@ int main(int argc, char **argv)

done:
put_log_buff(kbuff);
free(image);
return 0;
}

0 comments on commit 4071bd8

Please sign in to comment.