blob: f1e988a9591c819e4f7b0d76d3b3c075ecc5648c [file] [log] [blame]
Hao Xiang303e6f52024-03-11 18:00:12 +00001/*
2 * Multifd zero page detection implementation.
3 *
4 * Copyright (c) 2024 Bytedance Inc
5 *
6 * Authors:
7 * Hao Xiang <hao.xiang@bytedance.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13#include "qemu/osdep.h"
14#include "qemu/cutils.h"
15#include "exec/ramblock.h"
16#include "migration.h"
Fabiano Rosas5aff7172024-08-27 14:45:55 -030017#include "migration-stats.h"
Hao Xiang303e6f52024-03-11 18:00:12 +000018#include "multifd.h"
19#include "options.h"
20#include "ram.h"
21
22static bool multifd_zero_page_enabled(void)
23{
24 return migrate_zero_page_detection() == ZERO_PAGE_DETECTION_MULTIFD;
25}
26
27static void swap_page_offset(ram_addr_t *pages_offset, int a, int b)
28{
29 ram_addr_t temp;
30
31 if (a == b) {
32 return;
33 }
34
35 temp = pages_offset[a];
36 pages_offset[a] = pages_offset[b];
37 pages_offset[b] = temp;
38}
39
40/**
41 * multifd_send_zero_page_detect: Perform zero page detection on all pages.
42 *
43 * Sorts normal pages before zero pages in p->pages->offset and updates
44 * p->pages->normal_num.
45 *
46 * @param p A pointer to the send params.
47 */
48void multifd_send_zero_page_detect(MultiFDSendParams *p)
49{
Fabiano Rosas9f0e1082024-08-27 14:45:54 -030050 MultiFDPages_t *pages = &p->data->u.ram;
Hao Xiang303e6f52024-03-11 18:00:12 +000051 RAMBlock *rb = pages->block;
52 int i = 0;
53 int j = pages->num - 1;
54
55 if (!multifd_zero_page_enabled()) {
56 pages->normal_num = pages->num;
Fabiano Rosas5aff7172024-08-27 14:45:55 -030057 goto out;
Hao Xiang303e6f52024-03-11 18:00:12 +000058 }
59
60 /*
61 * Sort the page offset array by moving all normal pages to
62 * the left and all zero pages to the right of the array.
63 */
64 while (i <= j) {
65 uint64_t offset = pages->offset[i];
66
Fabiano Rosas90fa1212024-08-27 14:45:49 -030067 if (!buffer_is_zero(rb->host + offset, multifd_ram_page_size())) {
Hao Xiang303e6f52024-03-11 18:00:12 +000068 i++;
69 continue;
70 }
71
72 swap_page_offset(pages->offset, i, j);
73 ram_release_page(rb->idstr, offset);
74 j--;
75 }
76
77 pages->normal_num = i;
Fabiano Rosas5aff7172024-08-27 14:45:55 -030078
79out:
80 stat64_add(&mig_stats.normal_pages, pages->normal_num);
81 stat64_add(&mig_stats.zero_pages, pages->num - pages->normal_num);
Hao Xiang303e6f52024-03-11 18:00:12 +000082}
83
84void multifd_recv_zero_page_process(MultiFDRecvParams *p)
85{
86 for (int i = 0; i < p->zero_num; i++) {
87 void *page = p->host + p->zero[i];
Yuan Liu5ef7e262024-04-01 23:41:10 +080088 if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) {
Fabiano Rosas90fa1212024-08-27 14:45:49 -030089 memset(page, 0, multifd_ram_page_size());
Yuan Liu5ef7e262024-04-01 23:41:10 +080090 } else {
91 ramblock_recv_bitmap_set_offset(p->block, p->zero[i]);
Hao Xiang303e6f52024-03-11 18:00:12 +000092 }
93 }
94}