12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /*
- * Multifd zero page detection implementation.
- *
- * Copyright (c) 2024 Bytedance Inc
- *
- * Authors:
- * Hao Xiang <hao.xiang@bytedance.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
- #include "qemu/osdep.h"
- #include "qemu/cutils.h"
- #include "exec/ramblock.h"
- #include "migration.h"
- #include "migration-stats.h"
- #include "multifd.h"
- #include "options.h"
- #include "ram.h"
- static bool multifd_zero_page_enabled(void)
- {
- return migrate_zero_page_detection() == ZERO_PAGE_DETECTION_MULTIFD;
- }
- static void swap_page_offset(ram_addr_t *pages_offset, int a, int b)
- {
- ram_addr_t temp;
- if (a == b) {
- return;
- }
- temp = pages_offset[a];
- pages_offset[a] = pages_offset[b];
- pages_offset[b] = temp;
- }
- /**
- * multifd_send_zero_page_detect: Perform zero page detection on all pages.
- *
- * Sorts normal pages before zero pages in p->pages->offset and updates
- * p->pages->normal_num.
- *
- * @param p A pointer to the send params.
- */
- void multifd_send_zero_page_detect(MultiFDSendParams *p)
- {
- MultiFDPages_t *pages = &p->data->u.ram;
- RAMBlock *rb = pages->block;
- int i = 0;
- int j = pages->num - 1;
- if (!multifd_zero_page_enabled()) {
- pages->normal_num = pages->num;
- goto out;
- }
- /*
- * Sort the page offset array by moving all normal pages to
- * the left and all zero pages to the right of the array.
- */
- while (i <= j) {
- uint64_t offset = pages->offset[i];
- if (!buffer_is_zero(rb->host + offset, multifd_ram_page_size())) {
- i++;
- continue;
- }
- swap_page_offset(pages->offset, i, j);
- ram_release_page(rb->idstr, offset);
- j--;
- }
- pages->normal_num = i;
- out:
- stat64_add(&mig_stats.normal_pages, pages->normal_num);
- stat64_add(&mig_stats.zero_pages, pages->num - pages->normal_num);
- }
- void multifd_recv_zero_page_process(MultiFDRecvParams *p)
- {
- for (int i = 0; i < p->zero_num; i++) {
- void *page = p->host + p->zero[i];
- if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) {
- memset(page, 0, multifd_ram_page_size());
- } else {
- ramblock_recv_bitmap_set_offset(p->block, p->zero[i]);
- }
- }
- }
|