forked from linuxkerneltravel/lmp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dc18e16
commit b1e72fb
Showing
4 changed files
with
749 additions
and
0 deletions.
There are no files selected for viewing
155 changes: 155 additions & 0 deletions
155
eBPF_Supermarket/CPU_Subsystem/cpu_watcher/temp_sys/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# Copyright 2023 The LMP Authors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
# author: [email protected] | ||
# | ||
# compile the current folder code | ||
|
||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) | ||
OUTPUT := .output | ||
CLANG ?= clang | ||
LIBBPF_SRC := $(abspath ../../libbpf/src) | ||
BPFTOOL_SRC := $(abspath ../../bpftool/src) | ||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) | ||
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) | ||
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool | ||
LIBBLAZESYM_SRC := $(abspath ../../blazesym/) | ||
LIBBLAZESYM_INC := $(abspath $(LIBBLAZESYM_SRC)/include) | ||
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a) | ||
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ | ||
| sed 's/arm.*/arm/' \ | ||
| sed 's/aarch64/arm64/' \ | ||
| sed 's/ppc64le/powerpc/' \ | ||
| sed 's/mips.*/mips/' \ | ||
| sed 's/riscv64/riscv/' \ | ||
| sed 's/loongarch64/loongarch/') | ||
VMLINUX := ../../vmlinux/$(ARCH)/vmlinux.h | ||
# Use our own libbpf API headers and Linux UAPI headers distributed with | ||
# libbpf to avoid dependency on system-wide headers, which could be missing or | ||
# outdated | ||
INCLUDES := -I$(OUTPUT) -I../../../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC) | ||
CFLAGS := -g -Wall | ||
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) | ||
|
||
APPS = sys | ||
|
||
CARGO ?= $(shell which cargo) | ||
ifeq ($(strip $(CARGO)),) | ||
BZS_APPS := | ||
else | ||
BZS_APPS := profile | ||
APPS += $(BZS_APPS) | ||
# Required by libblazesym | ||
ALL_LDFLAGS += -lrt -ldl -lpthread -lm | ||
endif | ||
|
||
# Get Clang's default includes on this system. We'll explicitly add these dirs | ||
# to the includes list when compiling with `-target bpf` because otherwise some | ||
# architecture-specific dirs will be "missing" on some architectures/distros - | ||
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, | ||
# sys/cdefs.h etc. might be missing. | ||
# | ||
# Use '-idirafter': Don't interfere with include mechanics except where the | ||
# build would have failed anyways. | ||
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \ | ||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') | ||
|
||
ifeq ($(V),1) | ||
Q = | ||
msg = | ||
else | ||
Q = @ | ||
msg = @printf ' %-8s %s%s\n' \ | ||
"$(1)" \ | ||
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ | ||
"$(if $(3), $(3))"; | ||
MAKEFLAGS += --no-print-directory | ||
endif | ||
|
||
define allow-override | ||
$(if $(or $(findstring environment,$(origin $(1))),\ | ||
$(findstring command line,$(origin $(1)))),,\ | ||
$(eval $(1) = $(2))) | ||
endef | ||
|
||
$(call allow-override,CC,$(CROSS_COMPILE)cc) | ||
$(call allow-override,LD,$(CROSS_COMPILE)ld) | ||
|
||
.PHONY: all | ||
all: $(APPS) | ||
|
||
.PHONY: clean | ||
clean: | ||
$(call msg,CLEAN) | ||
$(Q)rm -rf $(OUTPUT) $(APPS) | ||
|
||
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): | ||
$(call msg,MKDIR,$@) | ||
$(Q)mkdir -p $@ | ||
|
||
# Build libbpf | ||
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf | ||
$(call msg,LIB,$@) | ||
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ | ||
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ | ||
INCLUDEDIR= LIBDIR= UAPIDIR= \ | ||
install | ||
|
||
# Build bpftool | ||
$(BPFTOOL): | $(BPFTOOL_OUTPUT) | ||
$(call msg,BPFTOOL,$@) | ||
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap | ||
|
||
|
||
$(LIBBLAZESYM_SRC)/target/release/libblazesym.a:: | ||
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --release | ||
|
||
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) | ||
$(call msg,LIB, $@) | ||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ | ||
|
||
# Build BPF code | ||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,BPF,$@) | ||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ | ||
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ | ||
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) | ||
|
||
# Generate BPF skeletons | ||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) | ||
$(call msg,GEN-SKEL,$@) | ||
$(Q)$(BPFTOOL) gen skeleton $< > $@ | ||
|
||
# Build user-space code | ||
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h | ||
|
||
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) | ||
$(call msg,CC,$@) | ||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ | ||
|
||
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_OBJ) | ||
|
||
$(BZS_APPS): $(LIBBLAZESYM_OBJ) | ||
|
||
# Build application binary | ||
$(APPS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT) | ||
$(call msg,BINARY,$@) | ||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ | ||
|
||
# delete failed targets | ||
.DELETE_ON_ERROR: | ||
|
||
# keep intermediate (.skel.h, .bpf.o, etc) targets | ||
.SECONDARY: |
181 changes: 181 additions & 0 deletions
181
eBPF_Supermarket/CPU_Subsystem/cpu_watcher/temp_sys/sys.bpf.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_core_read.h> | ||
#include <bpf/bpf_tracing.h> | ||
//#include <linux/arch/x86/include/asm/ptrace.h> | ||
//#include <asm/ptrace.h> | ||
//#include <linux/sched.h> | ||
#include "sys.h" | ||
|
||
char LICENSE[] SEC("license") = "Dual BSD/GPL"; | ||
|
||
const volatile long long unsigned int forks_addr = 0; | ||
#define PF_IDLE 0x00000002 /* I am an IDLE thread */ | ||
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ | ||
|
||
//环形缓冲区; | ||
struct { | ||
__uint(type, BPF_MAP_TYPE_RINGBUF); | ||
__uint(max_entries, 256 * 1024); | ||
} rb SEC(".maps"); | ||
BPF_ARRAY(start,int,u64,1); | ||
// 计数表格,第0项为所统计fork数,第1项为进程切换数, | ||
BPF_ARRAY(countMap,int,u64,3); | ||
// 记录开始的时间 | ||
BPF_ARRAY(procStartTime,pid_t,u64,4096); | ||
// 储存运行队列rq的全局变量 | ||
BPF_ARRAY(rq_map,u32,struct rq,1); | ||
BPF_PERCPU_ARRAY(runqlen, u32, int,1); | ||
/*记录软中断开始时间*/ | ||
BPF_PERCPU_ARRAY(softirqCpuEnterTime, u32, u64,4096); | ||
/*软中断结束时间*/ | ||
BPF_ARRAY(softirqLastTime,u32,u64,1); | ||
// 记录开始的时间 | ||
BPF_PERCPU_HASH(irq_cpu_enter_start, u32, u64,8192); | ||
//记录上次中断时间 | ||
BPF_ARRAY(irq_Last_time,u32,u64,1); | ||
// 储存cpu进入空闲的起始时间 | ||
BPF_ARRAY(idleStart,u32,u64,128); | ||
// 储存cpu进入空闲的持续时间 | ||
BPF_ARRAY(idleLastTime,u32,u64,1); | ||
BPF_ARRAY(kt_LastTime,u32,u64,1); | ||
BPF_ARRAY(ut_LastTime,u32,u64,1); | ||
BPF_ARRAY(tick_user,u32,u64,1); | ||
BPF_ARRAY(symAddr,u32,u64,1); | ||
|
||
// 统计fork数 | ||
SEC("kprobe/finish_task_switch") | ||
//SEC("kprobe/finish_task_switch.isra.0") | ||
int kprobe__finish_task_switch(struct pt_regs *ctx) | ||
{ | ||
u32 key = 0; | ||
u64 val, *valp = NULL; | ||
unsigned long total_forks; | ||
|
||
if(forks_addr !=0){ | ||
valp = (u64 *)forks_addr; | ||
bpf_probe_read_kernel(&total_forks, sizeof(unsigned long), valp); | ||
key = 1; | ||
val = total_forks; | ||
bpf_map_update_elem(&countMap,&key,&val,BPF_ANY); | ||
} | ||
return 0; | ||
} | ||
|
||
//获取进程切换数; | ||
SEC("tracepoint/sched/sched_switch")//静态挂载点 | ||
int trace_sched_switch2(struct cswch_args *info) { | ||
//从参数info中获取上一个(prev)和下一个(next)进程的进程号 | ||
pid_t prev = info->prev_pid, next = info->next_pid;//定义上一个、下一个进程的进程号 | ||
|
||
// 只有当上一个进程和下一个进程不相同时才执行以下操作,相同则代表是同一个进程 | ||
if (prev != next) { | ||
u32 key = 0; | ||
u64 *valp, delta, cur; | ||
struct task_struct *ts; | ||
|
||
// 将下一个进程的进程号赋给pid | ||
pid_t pid = next; | ||
u64 time = bpf_ktime_get_ns();//获取当前时间,ns; | ||
|
||
// Step1: 记录next进程的起始时间 | ||
bpf_map_update_elem(&procStartTime,&pid,&time,BPF_ANY);//上传当前时间到start map中 | ||
//procStartTime.update(&pid, &time);//python | ||
|
||
// Step2: Syscall时间处理 | ||
// record_sysc(time, prev, next); | ||
|
||
// Step3: UserMode时间处理 | ||
// record_user(time, prev, next); | ||
|
||
// Step4: 记录上下文切换的总次数 | ||
valp = bpf_map_lookup_elem(&countMap,&key); | ||
if (!valp) { | ||
// 没有找到表项 | ||
u64 initval = 1; | ||
bpf_map_update_elem(&countMap,&key,&initval,BPF_ANY);//初始化切换次数到countMap中 | ||
} | ||
else *valp += 1; | ||
//bpf_map_update_elem(&countMap,&key,&valp,BPF_ANY);//上传当前切换次数到countMap中 | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
SEC("kprobe/finish_task_switch") | ||
int BPF_KPROBE(finish_task_switch,struct task_struct *prev){ | ||
pid_t pid=BPF_CORE_READ(prev,pid); | ||
u64 *val, time = bpf_ktime_get_ns(); | ||
u64 delta; | ||
// Step1: 记录内核进程(非IDLE)运行时间 | ||
if ((BPF_CORE_READ(prev,flags) & PF_KTHREAD) && pid!= 0) { | ||
val = bpf_map_lookup_elem(&procStartTime, &pid); | ||
if (val) { | ||
u32 key = 0; | ||
delta = time - *val; | ||
val = bpf_map_lookup_elem(&kt_LastTime, &key); | ||
if (val) *val += delta; | ||
else bpf_map_update_elem(&kt_LastTime, &key, &delta, BPF_ANY); | ||
}// Step2: 记录用户进程的运行时间 | ||
}else if (!(BPF_CORE_READ(prev,flags) & PF_KTHREAD) && !(BPF_CORE_READ(prev,flags) &PF_IDLE)) { | ||
val = bpf_map_lookup_elem(&procStartTime, &pid); | ||
if (val) { | ||
u32 key = 0; | ||
delta = (time - *val)/1000;//us | ||
val = bpf_map_lookup_elem(&ut_LastTime, &key); | ||
if (val) *val += delta; | ||
else bpf_map_update_elem(&ut_LastTime, &key, &delta, BPF_ANY); | ||
} | ||
} | ||
return 0; | ||
|
||
} | ||
|
||
|
||
static __always_inline int user_mode(struct pt_regs *regs) | ||
{ | ||
#ifdef CONFIG_X86_32 | ||
return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL; | ||
#else | ||
return !!(regs->cs & 3); | ||
#endif | ||
} | ||
// 两个CPU各自会产生一个调用,这正好方便我们使用 | ||
SEC("perf_event") | ||
int tick_update(struct pt_regs *ctx) { | ||
|
||
// bpf_trace_printk("cs_rpl = %x\n", ctx->cs & 3); | ||
u32 key = 0; | ||
u64 val, *valp; | ||
|
||
// 记录用户态时间,直接从头文件arch/x86/include/asm/ptrace.h中引用 | ||
if (user_mode(ctx)) { | ||
u64 initval = 1; | ||
valp = bpf_map_lookup_elem(&tick_user, &key); | ||
if (valp) *valp += 1; | ||
else bpf_map_update_elem(&tick_user, &key, &initval, BPF_ANY); | ||
} | ||
|
||
unsigned long total_forks; | ||
|
||
// if(forks_addr !=0){ | ||
// valp = (u64 *)forks_addr; | ||
// bpf_probe_read_kernel(&total_forks, sizeof(unsigned long), valp); | ||
// key = 1; | ||
// val = total_forks; | ||
// bpf_map_update_elem(&countMap,&key,&val,BPF_ANY); | ||
// } | ||
|
||
valp = bpf_map_lookup_elem(&symAddr, &key); | ||
if (valp) { | ||
void *addr = (void *)(*valp); | ||
if (addr > 0) { | ||
bpf_probe_read_kernel(&total_forks, sizeof(unsigned long), addr); | ||
key = 1; | ||
val = total_forks; | ||
bpf_map_update_elem(&countMap, &key, &val, BPF_ANY); | ||
} | ||
} | ||
|
||
return 0; | ||
} |
Oops, something went wrong.