Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kvm_watcher:优化代码,完善了一些功能 #699

Merged
merged 20 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6bc2674
update mk
nanshuaibo Mar 1, 2024
244a659
update mk
nanshuaibo Mar 1, 2024
3ca0f8d
修改action
nanshuaibo Mar 1, 2024
ed2f177
update yml
nanshuaibo Mar 1, 2024
2b84b86
update mk
nanshuaibo Mar 1, 2024
3bfa9a4
添加hypercall(超级调用)统计功能
nanshuaibo Mar 1, 2024
4c75217
添加hypercall功能实现过程文档
nanshuaibo Mar 1, 2024
69b6efc
添加注释
nanshuaibo Mar 1, 2024
d32b4f5
Merge branch 'develop' into develop
nanshuaibo Mar 1, 2024
2db53ea
解决冲突 删除冗余代码
nanshuaibo Mar 1, 2024
c5845cb
Merge branch 'linuxkerneltravel:develop' into develop
nanshuaibo Mar 6, 2024
599d808
梳理kvm ept page fault处理流程
nanshuaibo Mar 8, 2024
9fb6314
更改tdp page fault ,和mmio page fault ,确保所统计的指标完整有效,添加ioctl的tp,后期方便提取kvm…
nanshuaibo Mar 8, 2024
b17bd77
添加内核态kvm ioctl提取框架,目前只统计部分ioctl信息,后期计划完善程序并对数据进行处理输出到用户态
nanshuaibo Mar 8, 2024
7b49dc4
优化代码
nanshuaibo Mar 8, 2024
218b21f
Revert "添加内核态kvm ioctl提取框架,目前只统计部分ioctl信息,后期计划完善程序并对数据进行处理输出到用户态"
nanshuaibo Mar 8, 2024
4bdcdfc
添加内核态kvm ioctl处理函数,后续计划统计相关ioctl信息
nanshuaibo Mar 8, 2024
05788a0
增加用户态kvm
nanshuaibo Mar 8, 2024
b3e3158
Merge branch 'develop' into develop
nanshuaibo Mar 10, 2024
660a1c3
解决冲突
nanshuaibo Mar 10, 2024
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
116 changes: 116 additions & 0 deletions eBPF_Supermarket/kvm_watcher/docs/kvm_mmu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@


vm exit(EPT_VIOLATION)处理流程:

```
static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
...
[EXIT_REASON_EPT_VIOLATION] = handle_ept_violation,
...
};

```

```c
vmx_handle_exit() {
# 处理 VMX(虚拟机扩展)退出的主要函数
__vmx_handle_exit() {
handle_ept_violation() {
# 处理 EPT(扩展页表)违规的函数
kvm_mmu_page_fault() {
# 处理 KVM MMU(内存管理单元)页错误
kvm_tdp_page_fault() {
# 处理 TDP(两级页表)页错误
kvm_arch_has_noncoherent_dma();
direct_page_fault() {
# 处理直接页错误
kvm_vcpu_gfn_to_memslot();
page_fault_handle_page_track();
fast_page_fault();
mmu_topup_memory_caches() {
# 增加内存缓存
kvm_mmu_topup_memory_cache() {
__kvm_mmu_topup_memory_cache();
}
kvm_mmu_topup_memory_cache() {
__kvm_mmu_topup_memory_cache();
}
kvm_mmu_topup_memory_cache() {
__kvm_mmu_topup_memory_cache();
}
}
kvm_faultin_pfn() {
# 处理 KVM PFN(物理帧号)故障
__gfn_to_pfn_memslot() {
# 将 GFN(全局帧号)转换为 PFN(物理帧号)并获取内存插槽
hva_to_pfn() {
# 将 HVA(主机虚拟地址)转换为 PFN(物理帧号)
get_user_pages_fast_only() {
# 快速获取用户页
internal_get_user_pages_fast() {
# 内部快速获取用户页
lockless_pages_from_mm() {
# 从内存管理结构中获取无锁页
gup_pgd_range() {
# 获取页表项(PGD)范围
pud_huge();
gup_pmd_range.constprop.0() {
# 获取中间页表项(PMD)范围
gup_huge_pmd() {
# 获取巨大页面的中间页表项
try_grab_folio();
}
}
}
}
}
}
}
}
}
handle_abnormal_pfn();
_raw_read_lock();
is_page_fault_stale();
kvm_tdp_mmu_map() {
# TDP MMU 映射
kvm_mmu_hugepage_adjust() {
# 调整 KVM MMU 巨大页面
kvm_mmu_max_mapping_level() {
# 获取 KVM MMU 最大映射级别
host_pfn_mapping_level();
}
}
__rcu_read_lock();
tdp_iter_start() {
# TDP 迭代器开始
tdp_iter_restart() {
# TDP 迭代器重新启动
tdp_iter_refresh_sptep();
}
}
disallowed_hugepage_adjust();
tdp_iter_next() {
# TDP 迭代器下一个
tdp_iter_refresh_sptep();
}
disallowed_hugepage_adjust();
tdp_iter_next() {
# TDP 迭代器下一个
tdp_iter_refresh_sptep();
}
}
tdp_iter_next() {
# TDP 迭代器下一个
tdp_iter_refresh_sptep();
}
}
disallowed_hugepage_adjust();
}
}
}
}
}

```

![kvm-init-mmu](https://gitee.com/nan-shuaibo/image/raw/master/202403081421893.png)
2 changes: 1 addition & 1 deletion eBPF_Supermarket/kvm_watcher/include/kvm_exits.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static int trace_kvm_exit(struct exit *ctx, pid_t vm_pid) {
CHECK_PID(vm_pid);
u32 reason;
reason = (u32)ctx->exit_reason;
//如果是节能停止退出,就不采集数据
// 如果是节能停止退出,就不采集数据
if (reason == EXIT_REASON_HLT) {
return 0;
}
Expand Down
32 changes: 32 additions & 0 deletions eBPF_Supermarket/kvm_watcher/include/kvm_ioctl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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]
//
// Kernel space BPF program used for KVM ioctl

#ifndef __KVM_IOCTL_H
#define __KVM_IOCTL_H

#include "kvm_watcher.h"
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>

static int trace_kvm_ioctl(struct trace_event_raw_sys_enter *args) {
return 0;
}

#endif /* __KVM_IOCTL_H */
36 changes: 22 additions & 14 deletions eBPF_Supermarket/kvm_watcher/include/kvm_mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>

#define PAGE_SHIFT 12

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
Expand Down Expand Up @@ -56,9 +58,9 @@ static int trace_page_fault(struct page_fault *ctx, pid_t vm_pid) {
return 0;
}

static int trace_direct_page_fault(struct kvm_vcpu *vcpu,
struct kvm_page_fault *fault, void *rb,
struct common_event *e) {
static int trace_tdp_page_fault(struct kvm_vcpu *vcpu,
struct kvm_page_fault *fault, void *rb,
struct common_event *e) {
u64 addr;
bpf_probe_read_kernel(&addr, sizeof(u64), &fault->addr);
u64 *ts;
Expand All @@ -81,7 +83,6 @@ static int trace_direct_page_fault(struct kvm_vcpu *vcpu,
if (count) {
(*count)++;
e->page_fault_data.count = *count;
bpf_map_update_elem(&pf_count, &addr, count, BPF_ANY);
} else {
e->page_fault_data.count = 1;
bpf_map_update_elem(&pf_count, &addr, &new_count, BPF_ANY);
Expand All @@ -104,36 +105,43 @@ static int trace_kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
CHECK_PID(vm_pid);
if (error_code & PFERR_RSVD_MASK) {
u64 ts = bpf_ktime_get_ns();
u64 addr = cr2_or_gpa;
bpf_map_update_elem(&pf_delay, &addr, &ts, BPF_ANY);
u64 gfn = cr2_or_gpa >> PAGE_SHIFT;
bpf_map_update_elem(&pf_delay, &gfn, &ts, BPF_ANY);
}
return 0;
}

static int trace_handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr,
bool direct, void *rb,
struct mmio_page_fault {
u64 pad;
u64 addr;
gfn_t gfn;
unsigned access;
};

static int trace_handle_mmio_page_fault(struct mmio_page_fault *ctx, void *rb,
struct common_event *e) {
u64 *ts;
ts = bpf_map_lookup_elem(&pf_delay, &addr);
u64 gfn;
bpf_probe_read_kernel(&gfn, sizeof(u64), &ctx->gfn);
ts = bpf_map_lookup_elem(&pf_delay, &gfn);
if (!ts) {
return 0;
}
u32 *count;
u32 new_count = 1;
u64 delay = bpf_ktime_get_ns() - *ts;
bpf_map_delete_elem(&pf_delay, &addr);
bpf_map_delete_elem(&pf_delay, &gfn);
RESERVE_RINGBUF_ENTRY(rb, e);
count = bpf_map_lookup_elem(&pf_count, &addr);
count = bpf_map_lookup_elem(&pf_count, &gfn);
if (count) {
(*count)++;
e->page_fault_data.count = *count;
bpf_map_update_elem(&pf_count, &addr, count, BPF_ANY);
} else {
e->page_fault_data.count = 1;
bpf_map_update_elem(&pf_count, &addr, &new_count, BPF_ANY);
bpf_map_update_elem(&pf_count, &gfn, &new_count, BPF_ANY);
}
e->page_fault_data.delay = delay;
e->page_fault_data.addr = addr;
e->page_fault_data.addr = gfn;
e->page_fault_data.error_code = PFERR_RSVD_MASK;
e->process.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&e->process.comm, sizeof(e->process.comm));
Expand Down
6 changes: 2 additions & 4 deletions eBPF_Supermarket/kvm_watcher/include/kvm_watcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@
#define NS_TO_US_WITH_DECIMAL(ns) ((double)(ns) / NS_TO_US_FACTOR)
#define NS_TO_MS_WITH_DECIMAL(ns) ((double)(ns) / NS_TO_MS_FACTOR)

#define MICROSECONDS_IN_SECOND 1000000
#define OUTPUT_INTERVAL_SECONDS 2

#define OUTPUT_INTERVAL(us) usleep((__u32)(us * MICROSECONDS_IN_SECOND))
#define OUTPUT_INTERVAL(SECONDS) sleep(SECONDS)

#define OPTIONS_LIST "-w, -p, -d, -f, -c, -i, ,-h or -e"

Expand Down Expand Up @@ -147,6 +144,7 @@ enum EventType {
IRQCHIP,
IRQ_INJECT,
HYPERCALL,
IOCTL,
} event_type;

struct common_event {
Expand Down
21 changes: 13 additions & 8 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "../include/kvm_watcher.h"
#include "../include/kvm_exits.h"
#include "../include/kvm_vcpu.h"
#include "../include/kvm_mmu.h"
#include "../include/kvm_irq.h"
#include "../include/kvm_hypercall.h"
#include "../include/kvm_watcher.h"
#include "../include/kvm_ioctl.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

Expand Down Expand Up @@ -75,10 +76,10 @@ int tp_page_fault(struct page_fault *ctx) {
return trace_page_fault(ctx, vm_pid);
}

SEC("fexit/direct_page_fault")
int BPF_PROG(fexit_direct_page_fault, struct kvm_vcpu *vcpu,
SEC("fexit/kvm_tdp_page_fault")
int BPF_PROG(fexit_tdp_page_fault, struct kvm_vcpu *vcpu,
struct kvm_page_fault *fault) {
return trace_direct_page_fault(vcpu, fault, &rb, e);
return trace_tdp_page_fault(vcpu, fault, &rb, e);
}

SEC("fentry/kvm_mmu_page_fault")
Expand All @@ -87,10 +88,9 @@ int BPF_PROG(fentry_kvm_mmu_page_fault, struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
return trace_kvm_mmu_page_fault(vcpu, cr2_or_gpa, error_code, vm_pid);
}

SEC("fexit/handle_mmio_page_fault")
int BPF_PROG(fexit_handle_mmio_page_fault, struct kvm_vcpu *vcpu, u64 addr,
bool direct) {
return trace_handle_mmio_page_fault(vcpu, addr, direct, &rb, e);
SEC("tp/kvmmmu/handle_mmio_page_fault")
int tp_handle_mmio_page_fault(struct mmio_page_fault *ctx) {
return trace_handle_mmio_page_fault(ctx, &rb, e);
}

SEC("fentry/kvm_pic_set_irq")
Expand Down Expand Up @@ -145,3 +145,8 @@ SEC("fentry/kvm_emulate_hypercall")
int BPF_PROG(fentry_emulate_hypercall, struct kvm_vcpu *vcpu) {
return entry_emulate_hypercall(vcpu, &rb, e, vm_pid);
}

SEC("tracepoint/syscalls/sys_enter_ioctl")
int tp_ioctl(struct trace_event_raw_sys_enter *args) {
return trace_kvm_ioctl(args);
}
Loading
Loading