From b5543c083777aa5d75d6b240b718f8c6be2def12 Mon Sep 17 00:00:00 2001 From: liubo Date: Thu, 18 Mar 2021 15:13:22 +0800 Subject: [PATCH] fix 64K pagesize scan problem Signed-off-by: liubo --- inc/etmemd_inc/etmemd_scan.h | 1 + src/etmemd_src/etmemd.c | 5 +++++ src/etmemd_src/etmemd_scan.c | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/inc/etmemd_inc/etmemd_scan.h b/inc/etmemd_inc/etmemd_scan.h index dbb6f70..9ae387e 100644 --- a/inc/etmemd_inc/etmemd_scan.h +++ b/inc/etmemd_inc/etmemd_scan.h @@ -109,4 +109,5 @@ void clean_page_refs_unexpected(void *arg); void clean_memory_grade_unexpected(void *arg); struct page_refs *add_page_refs_into_memory_grade(struct page_refs *page_refs, struct page_refs **list); +int init_g_page_size(void); #endif diff --git a/src/etmemd_src/etmemd.c b/src/etmemd_src/etmemd.c index 6670197..d99b7c8 100644 --- a/src/etmemd_src/etmemd.c +++ b/src/etmemd_src/etmemd.c @@ -20,6 +20,7 @@ #include "etmemd_rpc.h" #include "etmemd_common.h" #include "etmemd_project.h" +#include "etmemd_scan.h" int main(int argc, char *argv[]) { @@ -35,6 +36,10 @@ int main(int argc, char *argv[]) return 0; } + if (init_g_page_size() == -1) { + return -1; + } + etmemd_handle_signal(); if (etmemd_rpc_server() != 0) { printf("fail to start rpc server of etmemd\n"); diff --git a/src/etmemd_src/etmemd_scan.c b/src/etmemd_src/etmemd_scan.c index 8617e8f..d67c940 100644 --- a/src/etmemd_src/etmemd_scan.c +++ b/src/etmemd_src/etmemd_scan.c @@ -45,12 +45,46 @@ static const enum page_type g_page_type_by_idle_kind[] = { PAGE_TYPE_INVAL, }; -static const u_int64_t g_page_size[PAGE_TYPE_INVAL] = { +static u_int64_t g_page_size[PAGE_TYPE_INVAL] = { 1UL << PTE_SIZE_SHIFT, /* PTE size */ 1UL << PMD_SIZE_SHIFT, /* PMD size */ 1UL << PUD_SIZE_SHIFT, /* PUD size */ }; +static unsigned int get_page_shift(long pagesize) +{ + unsigned int page_shift = 0; + pagesize = pagesize >> 1; + while (pagesize != 0) { + page_shift++; + pagesize = pagesize >> 1; + } + + return page_shift; +} + +int init_g_page_size(void) +{ + unsigned int page_shift; + long pagesize = -1; + + pagesize = sysconf(_SC_PAGESIZE); + if (pagesize == -1) { + etmemd_log(ETMEMD_LOG_ERR, "get pagesize fail, error: %d\n", errno); + return -1; + } + + /* In the x86 architecture, the pagesize is 4kB. In the arm64 architecture, + * the pagesize is 4KB, 16KB, 64KB. Therefore, the pagesize in different + * scenarios is calculated as follows: */ + page_shift = get_page_shift(pagesize); + g_page_size[PTE_TYPE] = 1 << page_shift; /* PTE_SIZE */ + g_page_size[PMD_TYPE] = 1 << (((page_shift - 3) * (4 - 2)) + 3); /* PMD_SIZE = (page_shift - 3) * (4 - 2) + 3 */ + g_page_size[PUD_TYPE] = 1 << (((page_shift - 3) * (4 - 1)) + 3); /* PUD_SIZE = (page_shift - 3) * (4 - 1) + 3 */ + + return 0; +} + static bool is_anonymous(const struct vma *vma) { if (vma->stat[VMA_STAT_MAY_SHARE] || vma->stat[VMA_STAT_EXEC]) { @@ -470,7 +504,7 @@ static struct page_refs **walk_vmas(int fd, /* we make the buffer size as fitable as within a vma. * because the size of buffer passed to kernel will be calculated again (<< (3 + PAGE_SHIFT)) */ - size = (walk_address->walk_end - walk_address->walk_start) >> (3 + PAGE_SHIFT); + size = ((walk_address->walk_end - walk_address->walk_start) >> 3) / g_page_size[PTE_TYPE]; /* we need to compare the size to the minimum size that kernel handled */ size = size < EPT_IDLE_BUF_MIN ? EPT_IDLE_BUF_MIN : size; -- 1.8.3.1