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:优化代码并完善说明文档 #787

Merged
merged 34 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
07b2488
add kvmexit watcher
Monkey857 Feb 2, 2024
c7e7088
Update kvmexit.py
Monkey857 Feb 2, 2024
df01307
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Feb 19, 2024
dbc493c
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Feb 26, 2024
dbb0fc6
VMexit
Monkey857 Mar 1, 2024
9190fa1
修改action
Monkey857 Mar 1, 2024
47a3077
修改action
Monkey857 Mar 1, 2024
389a192
修改makefile
Monkey857 Mar 1, 2024
8d18306
update makefile
Monkey857 Mar 1, 2024
f4f9ce2
update yml
Monkey857 Mar 1, 2024
2248966
调整代码格式
Monkey857 Mar 1, 2024
781523b
merge
Monkey857 Mar 5, 2024
1e4a880
vm exit
Monkey857 Mar 8, 2024
1548430
优化代码
Monkey857 Mar 8, 2024
8b3d9a9
.c
Monkey857 Mar 19, 2024
0654095
Merge branch 'develop' of github.com:Monkey857/lmp into develop
Monkey857 Mar 19, 2024
fa67984
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Mar 21, 2024
6eac5e6
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Mar 22, 2024
a1ca34d
modify sort_bug
Monkey857 Mar 22, 2024
0c02211
modify sort_bug
Monkey857 Mar 22, 2024
013e146
add fun
Monkey857 Mar 22, 2024
0353dc5
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Mar 25, 2024
d70269d
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Apr 1, 2024
26537d1
vcpu_load
Monkey857 Apr 2, 2024
2d96bc6
resolve conflict
Monkey857 Apr 2, 2024
bd1c242
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Apr 7, 2024
063fc19
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Apr 8, 2024
7a2d292
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Apr 14, 2024
cd20a57
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 Apr 25, 2024
fa3b350
optimize code
Monkey857 Apr 25, 2024
8b213c6
Merge branch 'linuxkerneltravel:develop' into develop
Monkey857 May 10, 2024
3bb0058
modify sortFun
Monkey857 May 10, 2024
7725b23
Revert "modify sortFun"
Monkey857 May 10, 2024
ba56e3f
fix bug
Monkey857 May 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
39 changes: 37 additions & 2 deletions eBPF_Supermarket/kvm_watcher/docs/kvm_vcpu.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 概述

kvm watcher中的kvm vcpu子功能模块是设计用于监控和分析虚拟化环境中虚拟 CPU (VCPU) 活动的工具,它通过精确记录 VCPU 的唤醒/挂起事件、halt poll 时间的变化,以及 KVM 虚拟机在热迁移过程中产生的脏页信息,为优化虚拟机性能、提高系统响应速度、提供数据支持。
kvm watcher中的kvm vcpu子功能模块是设计用于监控和分析虚拟化环境中虚拟 CPU (VCPU) 活动的工具,它通过精确记录 VCPU 的唤醒/挂起事件、halt poll 时间的变化,虚拟cpu进调度和出调度的时间记录,以及 KVM 虚拟机在热迁移过程中产生的脏页信息,为优化虚拟机性能、提高系统响应速度、提供数据支持。

## 原理介绍

Expand All @@ -22,6 +22,9 @@ KVM 暂停轮询系统是 KVM 内的一项功能,其在某些情况下可以

在虚拟化环境中,脏页指的是自上次同步以来已经被修改的内存页。特别是在虚拟机热迁移过程中,源虚拟机上的内存页在复制到目标虚拟机的同时仍然处于活动状态,任何在此过程中对这些页的修改都会导致脏页的产生。监控这些脏页对于优化热迁移过程至关重要,因为过多的脏页生成可能会导致迁移延迟,甚至影响到虚拟机的运行性能。此监控功能特别适用于虚拟机热迁移的场景,其中脏页的精确监控和管理可以显著优化迁移过程。

### load_vcpu

加载虚拟 CPU(vCPU)是虚拟化环境中的一个重要步骤,它涉及为虚拟机创建和配置虚拟 CPU 实例,并将其加载到虚拟化平台中的运行环境中。加载 vCPU 将为客户机提供计算资源,允许其执行操作系统和应用程序代码。每个 vCPU 实例代表了一个独立的处理器核心,可以并行执行客户机指令。虚拟化环境中的多个 vCPU 可以并发执行客户机代码,从而支持虚拟机中的多任务和并发执行。加载多个 vCPU 允许虚拟机同时运行多个线程或进程。通过合理地分配物理资源并加载 vCPU,KVM可以优化虚拟机的性能和资源利用率。
## 挂载点

### wakeup
Expand All @@ -43,6 +46,12 @@ KVM 暂停轮询系统是 KVM 内的一项功能,其在某些情况下可以
| :----- | :---------------------- |
| kprobe | mark_page_dirty_in_slot |

### load_vcpu

| 类型 | 名称 |
| :----- | :----------------------|
| kprobe | vmx_vcpu_load |
| kprobe | vmx_vcpu_put |
## 示例输出

### wakeup
Expand Down Expand Up @@ -128,7 +137,22 @@ PID GFN REL_GFN SLOT_ID COUNTS
630632 f0122 122 3 61
....
```
### load_vcpu

```
sudo ./kvm_watcher -o
TIME:15:23:05
pid tid total_time max_time min_time counts vcpuid pcpuid
------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------
49214 49224 1.2344 0.3670 0.0346 9 1 2
49214 49225 0.5978 0.2171 0.1820 3 2 0
49062 49072 2.4008 0.2656 0.0806 14 0 4
49214 49223 4.5310 0.2794 0.0217 66 0 7
54504 54514 6.9243 0.8872 0.0235 34 1 10
49145 49166 2.8076 1.1653 0.0689 10 1 9
54504 54513 3.8860 0.3099 0.0210 30 0 0
49145 49165 1.4737 0.4106 0.0690 8 0 12
```
## 参数介绍

### dirty page
Expand All @@ -140,4 +164,15 @@ PID GFN REL_GFN SLOT_ID COUNTS
- **REL_GFN**: 相对于 GFN 的偏移量。
- **NPAGES**: 内存槽的页面数量。
- **USERSPACE_ADDR**: 触发脏页的用户空间地址。
- **SLOT_ID**: 内存插槽标识,指示哪个内存区域包含了脏页。
- **SLOT_ID**: 内存插槽标识,指示哪个内存区域包含了脏页。

### load_vcpu

- **TIME(ms)**: 事件发生的时间,以毫秒为单位。
- **PID/TID**: 进程或线程的标识符。
- **total_time**: 2秒内调度vcpu的总时间。
- **max_time**: 2秒内调度vcpu的最大时间。
- **min_time**: 2秒内调度vcpu的最小时间。
- **counts**: 2秒内调度vcpu的次数。
- **vcpuid**: 虚拟CPU号。
- **pcpuid**: vCPU对应绑定的物理CPU号。
172 changes: 79 additions & 93 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,80 @@ const char *getCurrentTimeFormatted() {
return ts; // 返回指向静态字符串的指针
}

// In order to sort vm_exit maps
int sort_by_key(int fd, struct exit_key *keys, struct exit_value *values) {
int err = 0;
struct exit_key lookup_key = {};
struct exit_key next_key = {};
struct exit_value exit_value;
int first = 1;
int i = 0, j;
int count = 0;
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
count++;
if (first) {
first = 0;
bpf_map_lookup_elem(fd, &next_key, &exit_value);
keys[0] = next_key;
values[0] = exit_value;
i++;
lookup_key = next_key;
continue;
}
err = bpf_map_lookup_elem(fd, &next_key, &exit_value);
if (err < 0) {
fprintf(stderr, "failed to lookup exit_value: %d\n", err);
return -1;
}
// insert sort
j = i - 1;
struct exit_key temp_key = next_key;
struct exit_value temp_value = exit_value;
while (j >= 0 &&
(keys[j].pid > temp_key.pid || (keys[j].tid > temp_key.tid))) {
keys[j + 1] = keys[j];
values[j + 1] = values[j];
j--;
}
i++;
keys[j + 1] = next_key;
values[j + 1] = temp_value;
// Move to the next key
lookup_key = next_key;
}
return count;
}

// clear the specific map
int clear_map(void *lookup_key, void *next_key, enum EventType type, int fd) {
int err;
switch (type) {
case HYPERCALL:
memset(lookup_key, 0, sizeof(struct hc_key));
break;
case TIMER:
memset(lookup_key, 0, sizeof(struct timer_key));
break;
case VCPU_LOAD:
memset(lookup_key, 0, sizeof(struct load_key));
break;
case EXIT:
memset(lookup_key, 0, sizeof(struct exit_key));
break;
default:
return -1;
}
while (!bpf_map_get_next_key(fd, lookup_key, next_key)) {
err = bpf_map_delete_elem(fd, next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup map: %d\n", err);
return -1;
}
lookup_key = next_key;
}
return 1;
}

int print_hc_map(struct kvm_watcher_bpf *skel) {
int fd = bpf_map__fd(skel->maps.hc_map);
int count_fd = bpf_map__fd(skel->maps.hc_count);
Expand Down Expand Up @@ -894,24 +968,8 @@ int print_hc_map(struct kvm_watcher_bpf *skel) {
// // Move to the next key
lookup_key = next_key;
}
memset(&lookup_key, 0, sizeof(struct hc_key));
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_delete_elem(fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup hc_map: %d\n", err);
return -1;
}
lookup_key = next_key;
}
memset(&lookup_key, 0, sizeof(struct hc_key));
while (!bpf_map_get_next_key(count_fd, &lookup_key, &next_key)) {
err = bpf_map_delete_elem(count_fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup hc_count: %d\n", err);
return -1;
}
lookup_key = next_key;
}
clear_map(&lookup_key, &next_key, HYPERCALL, fd);
clear_map(&lookup_key, &next_key, HYPERCALL, count_fd);
return 0;
}

Expand Down Expand Up @@ -946,64 +1004,10 @@ int print_timer_map(struct kvm_watcher_bpf *skel) {
// Move to the next key
lookup_key = next_key;
}

// Clear the timer_map
memset(&lookup_key, 0, sizeof(struct timer_key));
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_delete_elem(fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup timer_map: %d\n", err);
return -1;
}
lookup_key = next_key;
}
clear_map(&lookup_key, &next_key, TIMER, fd);
return 0;
}

// In order to sort vm_exit maps
int sort_by_key(int fd, struct exit_key *keys, struct exit_value *values) {
int err = 0;
struct exit_key lookup_key = {};
struct exit_key next_key = {};
struct exit_value exit_value;
int first = 1;
int i = 0, j;
int count = 0;
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
count++;
if (first) {
first = 0;
bpf_map_lookup_elem(fd, &next_key, &exit_value);
keys[0] = next_key;
values[0] = exit_value;
i++;
lookup_key = next_key;
continue;
}
err = bpf_map_lookup_elem(fd, &next_key, &exit_value);
if (err < 0) {
fprintf(stderr, "failed to lookup exit_value: %d\n", err);
return -1;
}
// insert sort
j = i - 1;
struct exit_key temp_key = next_key;
struct exit_value temp_value = exit_value;
while (j >= 0 &&
(keys[j].pid > temp_key.pid || (keys[j].tid > temp_key.tid))) {
keys[j + 1] = keys[j];
values[j + 1] = values[j];
j--;
}
i++;
keys[j + 1] = next_key;
values[j + 1] = temp_value;
// Move to the next key
lookup_key = next_key;
}
return count;
}

int print_vcpu_load_map(struct kvm_watcher_bpf *skel) {
int fd = bpf_map__fd(skel->maps.load_map);
int err;
Expand Down Expand Up @@ -1038,16 +1042,7 @@ int print_vcpu_load_map(struct kvm_watcher_bpf *skel) {
load_value.vcpu_id, load_value.pcpu_id);
lookup_key = next_key;
}
// clear the maps
memset(&lookup_key, 0, sizeof(struct load_key));
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
err = bpf_map_delete_elem(fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup counters: %d\n", err);
return -1;
}
lookup_key = next_key;
}
clear_map(&lookup_key, &next_key, VCPU_LOAD, fd);
return 0;
}

Expand Down Expand Up @@ -1107,16 +1102,7 @@ void __print_exit_map(int fd, enum NameType name_type) {
getName(keys[i].reason, name_type));
}
}
// clear the maps
memset(&lookup_key, 0, sizeof(struct exit_key));
while (!bpf_map_get_next_key(fd, &lookup_key, &next_key)) {
int err = bpf_map_delete_elem(fd, &next_key);
if (err < 0) {
fprintf(stderr, "failed to cleanup counters: %d\n", err);
return;
}
lookup_key = next_key;
}
clear_map(&lookup_key, &next_key, EXIT, fd);
}
int print_exit_map(struct kvm_watcher_bpf *skel) {
int exit_fd = bpf_map__fd(skel->maps.exit_map);
Expand Down
Loading