Skip to content
Closed
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
81 changes: 81 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: bpf-ci

on:
pull_request:

concurrency:
group: ci-test-${{ github.head_ref }}
cancel-in-progress: true

jobs:
VM_Test:
runs-on: ${{ matrix.runs_on }}
name: Kernel ${{ matrix.kernel }} on ${{ matrix.runs_on[0] }} with ${{ matrix.toolchain }}
timeout-minutes: 100
strategy:
fail-fast: false
matrix:
include:
- kernel: 'LATEST'
runs_on: [ubuntu-latest, self-hosted]
arch: 'x86_64'
toolchain: 'gcc'
- kernel: 'LATEST'
runs_on: [ubuntu-latest, self-hosted]
arch: 'x86_64'
toolchain: 'llvm-16'
- kernel: 'LATEST'
runs_on: [z15, self-hosted]
arch: 's390x'
toolchain: 'gcc'
env:
KERNEL: LATEST
REPO_ROOT: ${{ github.workspace }}
REPO_PATH: ""
steps:
- uses: actions/checkout@v2
- if: ${{ github.repository == 'kernel-patches/vmtest' }}
name: Download bpf-next tree
uses: libbpf/ci/get-linux-source@master
with:
dest: '.kernel'
- if: ${{ github.repository == 'kernel-patches/vmtest' }}
name: Move linux source in place
shell: bash
run: |
rm -rf .kernel/.git
cp -rf .kernel/. .
rm -rf .kernel
- uses: libbpf/ci/patch-kernel@master
with:
patches-root: '${{ github.workspace }}/travis-ci/diffs'
repo-root: '${{ github.workspace }}'
- name: Setup build environment
uses: libbpf/ci/setup-build-env@master
- name: Build kernel image
uses: libbpf/ci/build-linux@master
with:
arch: ${{ matrix.arch }}
toolchain: ${{ matrix.toolchain }}
- name: Build selftests
uses: libbpf/ci/build-selftests@master
with:
vmlinux_btf: ${{ github.workspace }}/vmlinux
toolchain: ${{ matrix.toolchain }}
- name: Build samples
uses: libbpf/ci/build-samples@master
with:
vmlinux_btf: ${{ github.workspace }}/vmlinux
toolchain: ${{ matrix.toolchain }}
- name: Prepare rootfs
uses: libbpf/ci/prepare-rootfs@master
with:
project-name: 'libbpf'
arch: ${{ matrix.arch }}
kernel-root: '.'
- name: Run selftests
uses: libbpf/ci/run-qemu@master
with:
arch: ${{ matrix.arch}}
img: '/tmp/root.img'
vmlinuz: '${{ github.workspace }}/vmlinuz'
18 changes: 0 additions & 18 deletions README
Original file line number Diff line number Diff line change
@@ -1,18 +0,0 @@
Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``. The formatted documentation can also be read online at:

https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.
57 changes: 50 additions & 7 deletions tools/perf/tests/shell/record_offcpu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,26 @@ trap_cleanup() {
}
trap trap_cleanup exit term int

test_offcpu() {
echo "Basic off-cpu test"
test_offcpu_priv() {
echo "Checking off-cpu privilege"

if [ `id -u` != 0 ]
then
echo "Basic off-cpu test [Skipped permission]"
echo "off-cpu test [Skipped permission]"
err=2
return
fi
if perf record --off-cpu -o ${perfdata} --quiet true 2>&1 | grep BUILD_BPF_SKEL
if perf record --off-cpu -o /dev/null --quiet true 2>&1 | grep BUILD_BPF_SKEL
then
echo "Basic off-cpu test [Skipped missing BPF support]"
echo "off-cpu test [Skipped missing BPF support]"
err=2
return
fi
}

test_offcpu_basic() {
echo "Basic off-cpu test"

if ! perf record --off-cpu -e dummy -o ${perfdata} sleep 1 2> /dev/null
then
echo "Basic off-cpu test [Failed record]"
Expand All @@ -41,7 +47,7 @@ test_offcpu() {
fi
if ! perf evlist -i ${perfdata} | grep -q "offcpu-time"
then
echo "Basic off-cpu test [Failed record]"
echo "Basic off-cpu test [Failed no event]"
err=1
return
fi
Expand All @@ -54,7 +60,44 @@ test_offcpu() {
echo "Basic off-cpu test [Success]"
}

test_offcpu
test_offcpu_child() {
echo "Child task off-cpu test"

# perf bench sched messaging creates 400 processes
if ! perf record --off-cpu -e dummy -o ${perfdata} -- \
perf bench sched messaging -g 10 > /dev/null 2&>1
then
echo "Child task off-cpu test [Failed record]"
err=1
return
fi
if ! perf evlist -i ${perfdata} | grep -q "offcpu-time"
then
echo "Child task off-cpu test [Failed no event]"
err=1
return
fi
# each process waits for read and write, so it should be more than 800 events
if ! perf report -i ${perfdata} -s comm -q -n -t ';' --percent-limit=90 | \
awk -F ";" '{ if (NF > 3 && int($3) < 800) exit 1; }'
then
echo "Child task off-cpu test [Failed invalid output]"
err=1
return
fi
echo "Child task off-cpu test [Success]"
}


test_offcpu_priv

if [ $err = 0 ]; then
test_offcpu_basic
fi

if [ $err = 0 ]; then
test_offcpu_child
fi

cleanup
exit $err
53 changes: 51 additions & 2 deletions tools/perf/util/bpf_off_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
#include "util/cpumap.h"
#include "util/thread_map.h"
#include "util/cgroup.h"
#include "util/strlist.h"
#include <bpf/bpf.h>

#include "bpf_skel/off_cpu.skel.h"

#define MAX_STACKS 32
#define MAX_PROC 4096
/* we don't need actual timestamp, just want to put the samples at last */
#define OFF_CPU_TIMESTAMP (~0ull << 32)

Expand Down Expand Up @@ -78,6 +80,7 @@ static void off_cpu_start(void *arg)
u8 val = 1;

skel->bss->has_task = 1;
skel->bss->uses_tgid = 1;
fd = bpf_map__fd(skel->maps.task_filter);
pid = perf_thread_map__pid(evlist->core.threads, 0);
bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
Expand Down Expand Up @@ -124,6 +127,8 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
{
int err, fd, i;
int ncpus = 1, ntasks = 1, ncgrps = 1;
struct strlist *pid_slist = NULL;
struct str_node *pos;

if (off_cpu_config(evlist) < 0) {
pr_err("Failed to config off-cpu BPF event\n");
Expand All @@ -142,9 +147,34 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus);
}

if (target__has_task(target)) {
if (target->pid) {
pid_slist = strlist__new(target->pid, NULL);
if (!pid_slist) {
pr_err("Failed to create a strlist for pid\n");
return -1;
}

ntasks = 0;
strlist__for_each_entry(pos, pid_slist) {
char *end_ptr;
int pid = strtol(pos->s, &end_ptr, 10);

if (pid == INT_MIN || pid == INT_MAX ||
(*end_ptr != '\0' && *end_ptr != ','))
continue;

ntasks++;
}

if (ntasks < MAX_PROC)
ntasks = MAX_PROC;

bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
} else if (target__has_task(target)) {
ntasks = perf_thread_map__nr(evlist->core.threads);
bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
} else if (target__none(target)) {
bpf_map__set_max_entries(skel->maps.task_filter, MAX_PROC);
}

if (evlist__first(evlist)->cgrp) {
Expand Down Expand Up @@ -184,7 +214,26 @@ int off_cpu_prepare(struct evlist *evlist, struct target *target,
}
}

if (target__has_task(target)) {
if (target->pid) {
u8 val = 1;

skel->bss->has_task = 1;
skel->bss->uses_tgid = 1;
fd = bpf_map__fd(skel->maps.task_filter);

strlist__for_each_entry(pos, pid_slist) {
char *end_ptr;
u32 tgid;
int pid = strtol(pos->s, &end_ptr, 10);

if (pid == INT_MIN || pid == INT_MAX ||
(*end_ptr != '\0' && *end_ptr != ','))
continue;

tgid = pid;
bpf_map_update_elem(fd, &tgid, &val, BPF_ANY);
}
} else if (target__has_task(target)) {
u32 pid;
u8 val = 1;

Expand Down
38 changes: 37 additions & 1 deletion tools/perf/util/bpf_skel/off_cpu.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#define TASK_INTERRUPTIBLE 0x0001
#define TASK_UNINTERRUPTIBLE 0x0002

/* create a new thread */
#define CLONE_THREAD 0x10000

#define MAX_STACKS 32
#define MAX_ENTRIES 102400

Expand Down Expand Up @@ -85,6 +88,7 @@ int enabled = 0;
int has_cpu = 0;
int has_task = 0;
int has_cgroup = 0;
int uses_tgid = 0;

const volatile bool has_prev_state = false;
const volatile bool needs_cgroup = false;
Expand Down Expand Up @@ -144,7 +148,12 @@ static inline int can_record(struct task_struct *t, int state)

if (has_task) {
__u8 *ok;
__u32 pid = t->pid;
__u32 pid;

if (uses_tgid)
pid = t->tgid;
else
pid = t->pid;

ok = bpf_map_lookup_elem(&task_filter, &pid);
if (!ok)
Expand Down Expand Up @@ -214,6 +223,33 @@ static int off_cpu_stat(u64 *ctx, struct task_struct *prev,
return 0;
}

SEC("tp_btf/task_newtask")
int on_newtask(u64 *ctx)
{
struct task_struct *task;
u64 clone_flags;
u32 pid;
u8 val = 1;

if (!uses_tgid)
return 0;

task = (struct task_struct *)bpf_get_current_task();

pid = BPF_CORE_READ(task, tgid);
if (!bpf_map_lookup_elem(&task_filter, &pid))
return 0;

task = (struct task_struct *)ctx[0];
clone_flags = ctx[1];

pid = task->tgid;
if (!(clone_flags & CLONE_THREAD))
bpf_map_update_elem(&task_filter, &pid, &val, BPF_NOEXIST);

return 0;
}

SEC("tp_btf/sched_switch")
int on_switch(u64 *ctx)
{
Expand Down
Loading