From e6a15f1066222271a75f5f6efd2c89bf077eb77d Mon Sep 17 00:00:00 2001 From: Zhou Kang Date: Thu, 28 Sep 2023 09:39:43 +0000 Subject: [PATCH] add test for hugepage --- tests/test_hugepage/.gitignore | 1 + tests/test_hugepage/Makefile | 16 ++ tests/test_hugepage/hugepage.x86_64.lds | 250 ++++++++++++++++++++++++ tests/test_hugepage/test_hugepage.c | 28 +++ tests/test_hugepage/test_hugepage.o | Bin 0 -> 1808 bytes tests/test_sysboostd.py | 59 ++++-- 6 files changed, 343 insertions(+), 11 deletions(-) create mode 100644 tests/test_hugepage/.gitignore create mode 100644 tests/test_hugepage/Makefile create mode 100644 tests/test_hugepage/hugepage.x86_64.lds create mode 100644 tests/test_hugepage/test_hugepage.c create mode 100644 tests/test_hugepage/test_hugepage.o diff --git a/tests/test_hugepage/.gitignore b/tests/test_hugepage/.gitignore new file mode 100644 index 0000000..13fa916 --- /dev/null +++ b/tests/test_hugepage/.gitignore @@ -0,0 +1 @@ +test_hugepage diff --git a/tests/test_hugepage/Makefile b/tests/test_hugepage/Makefile new file mode 100644 index 0000000..e3aa4d2 --- /dev/null +++ b/tests/test_hugepage/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: MulanPSL-2.0 + +.PHONY: all + +all: app + +app: + gcc -c test_hugepage.c -o test_hugepage.o + # 编译过程找不到_start, 运行过程会coredump, 不影响测试 + ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -T hugepage.x86_64.lds -zcommon-page-size=2097152 -zmax-page-size=2097152 -o test_hugepage test_hugepage.o + +test: app + ./test_hugepage + +clean: + $(RM) *.o *.ro *.old *.so *.asm *.elf *.rto *.out test_hugepage diff --git a/tests/test_hugepage/hugepage.x86_64.lds b/tests/test_hugepage/hugepage.x86_64.lds new file mode 100644 index 0000000..8f74c6f --- /dev/null +++ b/tests/test_hugepage/hugepage.x86_64.lds @@ -0,0 +1,250 @@ +/* Script for -z combreloc -z separate-code */ +/* Copyright (C) 2014-2021 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", + "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SEARCH_DIR("=/usr/x86_64-openEuler-linux/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/x86_64-openEuler-linux/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); +SECTIONS +{ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) + *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) + *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) + *(.rela.ifunc) + } + .rela.plt : + { + *(.rela.plt) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + . = ALIGN(CONSTANT (MAXPAGESIZE)); + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) *(.iplt) } +.plt.got : { *(.plt.got) } +.plt.sec : { *(.plt.sec) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(SORT(.text.sorted.*)) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf.em. */ + *(.gnu.warning) + } + .text.pad ALIGN(16): + { + BYTE(0x00) + . = . + 0x200000 - 1; + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + . = ALIGN(CONSTANT (MAXPAGESIZE)); + /* Adjust the address for the rodata segment. We want to adjust up to + the same address within the page on the next page up. */ + . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1))); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } + .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : + { + PROVIDE_HIDDEN (__tdata_start = .); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we do not + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + .lbss : + { + *(.dynlbss) + *(.lbss .lbss.* .gnu.linkonce.lb.*) + *(LARGE_COMMON) + } + . = ALIGN(64 / 8); + . = SEGMENT_START("ldata-segment", .); + .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.lrodata .lrodata.* .gnu.linkonce.lr.*) + } + .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.ldata .ldata.* .gnu.linkonce.l.*) + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/tests/test_hugepage/test_hugepage.c b/tests/test_hugepage/test_hugepage.c new file mode 100644 index 0000000..861cba1 --- /dev/null +++ b/tests/test_hugepage/test_hugepage.c @@ -0,0 +1,28 @@ +// Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. +// +// sysboost is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan +// PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. + +#include +#include +#include +#include + +int main(void) +{ + char buf[1024] = {0}; + + printf("test_hugepage\n"); + pid_t pid = getpid(); + snprintf(buf, sizeof(buf), "cat /proc/%d/smaps", pid); + system(buf); + + return 0; +} diff --git a/tests/test_hugepage/test_hugepage.o b/tests/test_hugepage/test_hugepage.o new file mode 100644 index 0000000000000000000000000000000000000000..f79a17e0e20890ea24d31ada1fc4faf58baa80e4 GIT binary patch literal 1808 zcmbtU&1+LZ5TBRS){i#C52R2JQBW$?msT&;gG57Z4&tE@Jl5A_n?!vtkM}l^c&Lad z1S#a=U*SKX9#rU|c=V)yfPx1PiU$h@;>>0z-7LvP2R1Xm-+XO$CV8}S>t@1nfW?7p zu#cDp=p^^;oHBEef*B|l+FuKgzo#bv3cF8#{OR?`iRK=g+b^Ko>%AiS^%nWspMDiy zz9al?@X=oBJ}-6)+p0qQ;~R3k1uEL!RjDde`;k*nIX>)25zF;zqas4DBB12SOg4<_ zrR>>qHuk+R23XDKuV&^~Zx_#JmKNR1?h;UG$ly7E2OW?A=RI*Oj>h~JC$z(PxCTx$ z?aWP29qgd<6!LUPp3ukjRQg#WKQo!w!U!Tp3)P)~pX#;jh~&r#03_9Ihog@oJZ8kJ zJ0N!wPkK01p}8^qnKAsr7#@aR-7SId)dC0`GKPwfVXX{t5Jt5?ZbICOrSMgEfGb)b zMs2JVZe3q!1~d~~86|mxpEUS8n&&zxjcZ2ylo8)Fcp3}W&uBh@n$AGnxaCW41Ke0f zeO+ZM5)V9Ailzj&>`4#YjW`B3s`o*u?)xG@Ur?9A#of9XORsca<4VwQaXUj1$rk2N zB~e}9j67cqTK|uc!DQMkdMi_M8t{IwkN2A~?FY>u$As3Qew>cRM^IBPulTIy&uQMA zExC5I-&S`23m8B(|1}?f+Uj0IvqX;jpGMmhyFcwGaf@aU+Fvw2Ztf_CR+DlN**EO`zm=W3!2kdN literal 0 HcmV?d00001 diff --git a/tests/test_sysboostd.py b/tests/test_sysboostd.py index 73fd7b2..792d42a 100755 --- a/tests/test_sysboostd.py +++ b/tests/test_sysboostd.py @@ -38,36 +38,73 @@ def write_file(file_path, s): file.close() +def write_config_toml(elf_path, mode): + # 生成toml + run_cmd("mkdir -p /etc/sysboost.d") + run_cmd("rm -f /etc/sysboost.d/mysqld.toml") + s = f'''elf_path = "{elf_path}" +mode = "{mode}" +libs = [] +''' + write_file("/etc/sysboost.d/mysqld.toml", s) + + +def restart_sysboostd(): + run_cmd("killall -9 sysboostd") + run_cmd("/usr/bin/sysboostd --daemon &") + #run_cmd("systemctl restart sysboost") + + +def is_text_hugepage(s): + # 不是0的时候, 说明是大页 + # ShmemPmdMapped: 0 kB + # TODO: 实现判断 + pass + + class TestSysboostd(unittest.TestCase): - ''' 测试在线生成profile文件 + def test_gen_profile(self): + """ + 测试在线生成profile文件 sysboostd --gen-profile=mysqld 观察点: /usr/lib/sysboost.d/profile/mysqld.profile.now 是否正确生成 - ''' - def test_gen_profile(self): + """ # 测试环境需要安装perf, llvm-bolt # yum install perf llvm-bolt - + # 防止profile目录不存在 run_cmd("mkdir -p /usr/lib/sysboost.d/profile") # 不是每个测试环境都有mysql, 用小程序模拟测试, 目标程序需要有重定位信息 run_cmd("mkdir -p /home/test_sysboost") run_cmd("cp -f build/tests/test_simple/simple_app /home/test_sysboost/mysqld") # 生成toml - run_cmd("mkdir -p /etc/sysboost.d") - run_cmd("rm -f /etc/sysboost.d/mysqld.toml") - s = '''elf_path = "/home/test_sysboost/mysqld" -mode = "bolt" -libs = [] -''' - write_file("/etc/sysboost.d/mysqld.toml", s) + write_config_toml("/home/test_sysboost/mysqld", "bolt") # 测试 file_path = "/usr/lib/sysboost.d/profile/mysqld.profile.now" run_cmd("rm -f {}".format(file_path)) ret,output = run_cmd("sysboostd --gen-profile=mysqld --timeout=1") + # 虚拟机perf无法抓取相关事件 # TODO: 目标程序需要被采集到, 否则perf2bolt会报错, 返回1 self.assertEqual(ret, 1, msg=output) #self.assertEqual(os.path.exists(file_path), True) + def test_hugepage_mode(self): + """ + 测试代码大页 + 观察点: /proc/xxx/smaps 是否代码大页 + """ + run_cmd("mkdir -p /home/test_sysboost") + run_cmd("cd tests/test_hugepage; make") + run_cmd("cp -f tests/test_hugepage/test_hugepage /home/test_sysboost/") + run_cmd("sysboost -s /home/test_sysboost/test_hugepage") + _,output = run_cmd("/home/test_sysboost/test_hugepage") + ret = is_text_hugepage(output) + self.assertEqual(ret, True, msg=output) + + if __name__ == '__main__': + # python3 -m unittest test_sysboostd.TestSysboostd.test_hugepage_mode + # suite = unittest.TestLoader().loadTestsFromName('test_hugepage_mode') + # unittest.TextTestRunner().run(suite) unittest.main(verbosity=2) -- Gitee