diff --git a/SOURCES/libhugetlbfs-2.20-do-not-assume-default-huge-page-size-is-first.patch b/SOURCES/libhugetlbfs-2.20-do-not-assume-default-huge-page-size-is-first.patch new file mode 100644 index 0000000..5497a25 --- /dev/null +++ b/SOURCES/libhugetlbfs-2.20-do-not-assume-default-huge-page-size-is-first.patch @@ -0,0 +1,42 @@ +commit 77cf8bdf8f523c1417e5dc54db72fb74c8c15f56 +Author: Nishanth Aravamudan +Date: Tue Sep 1 12:26:59 2015 -0700 + + huge_page_setup_helper: do not assume default huge page size is first + + The helper script currently implicitly assumes that `hugeadm + --pool-list` will emit the default size first, as it assumes every line + has 5 fields in it. But only the default field does, and if `hugeadm + --pool-list` were to output: + + hugeadm --pool-list + Size Minimum Current Maximum Default + 1048576 0 0 0 + 16777216 0 0 0 * + 17179869184 0 0 0 + + we receive an error from the script: + # ./huge_page_setup_helper.py + Traceback (most recent call last): + File "./huge_page_setup_helper.py", line 51, in + if line.split()[4] == '*': + IndexError: list index out of range + + Just check for the '*' character to determine the default line. + + Signed-off-by: Nishanth Aravamudan + Signed-off-by: Eric B Munson + +diff --git a/huge_page_setup_helper.py b/huge_page_setup_helper.py +index 8bfef14..43c9916 100755 +--- a/huge_page_setup_helper.py ++++ b/huge_page_setup_helper.py +@@ -48,7 +48,7 @@ if memTotal == 0: + # Pick the default huge page size and see how many pages are allocated + poolList = os.popen("/usr/bin/hugeadm --pool-list").readlines() + for line in poolList: +- if line.split()[4] == '*': ++ if '*' in line: + hugePageSize = int(line.split()[0]) + hugePages = int(line.split()[2]) + break diff --git a/SOURCES/libhugetlbfs-2.20-tests-linkhuge_rw-function-ptr-may-not-refer-to-text.patch b/SOURCES/libhugetlbfs-2.20-tests-linkhuge_rw-function-ptr-may-not-refer-to-text.patch new file mode 100644 index 0000000..f854fd1 --- /dev/null +++ b/SOURCES/libhugetlbfs-2.20-tests-linkhuge_rw-function-ptr-may-not-refer-to-text.patch @@ -0,0 +1,196 @@ +commit 9dbe121e3132630e9094d36c2b0624404b75beea +Author: Jan Stancek +Date: Tue Sep 1 15:49:35 2015 +0200 + + tests/linkhuge_rw: function ptr may not refer to .text + + On some ABIs function pointer may not refer to .text section. + For example on powerPC 64-bit ABI, function pointer may refer + to a call stub from .opd section. + + This creates a problem for linkhuge_rw tests which run with + HUGETLB_ELFMAP=R, because test is expecting that address of + function pointer will be backed by huge pages. But because + .opd section is from RW PT_LOAD segment, this doens't happen, + since libhugetlbfs is instructed to map only R segments via + HUGETLB_ELFMAP=R. + + This patch is replacing use of function pointer with address + returned by gcc's __builtin_return_address(), that is called + by the function itself. This should provide an address that + is from an actual code, residing in .text section. + + Signed-off-by: Jan Stancek + Cc: Adam Litke + Cc: Eric B Munson + Cc: Petr Holasek + Signed-off-by: Eric B Munson + +diff --git a/tests/linkhuge_rw.c b/tests/linkhuge_rw.c +index f58fff2..c1c2e96 100644 +--- a/tests/linkhuge_rw.c ++++ b/tests/linkhuge_rw.c +@@ -31,7 +31,8 @@ + #include "hugetests.h" + + #define BLOCK_SIZE 16384 +-#define CONST 0xdeadbeef ++#define CONST 0xdeadbeef ++#define RETURN_ADDRESS 0x0 + + #define BIG_INIT { \ + [0] = CONST, [17] = CONST, [BLOCK_SIZE-1] = CONST, \ +@@ -45,13 +46,49 @@ static int big_bss[BLOCK_SIZE]; + const int small_const = CONST; + const int big_const[BLOCK_SIZE] = BIG_INIT; + +-static int static_func(int x) ++/* ++ * Turn function pointer into address from .text. ++ * ++ * On some ABIs function pointer may not refer to .text section. For example ++ * on powerPC 64-bit ABI, function pointer may refer to call stub from ++ * .opd section. ++ * ++ * This function expects that parameter data is a function pointer of type: ++ * long f(long), and when called with special parameter, it returns an address ++ * corresponding to actual code of the function. Current implementation relies ++ * on gcc's __builtin_return_address, see get_pc() below. ++ */ ++static inline void *get_text_addr(void *data) ++{ ++ long (*gettext)(long) = data; ++ ++ return (void *)gettext(RETURN_ADDRESS); ++} ++ ++static void __attribute__ ((noinline)) *get_pc(void) ++{ ++#if defined(__s390__) && __WORDSIZE == 32 ++ /* taken from sysdeps/unix/sysv/linux/s390/s390-32/profil-counter.h ++ * 31-bit s390 pointers don't use the 32th bit, however integers do, ++ * so wrap the value around at 31 bits */ ++ return (void *) ++ ((unsigned long) __builtin_return_address(0) & 0x7fffffffUL); ++#else ++ return __builtin_return_address(0); ++#endif ++} ++ ++static long static_func(long x) + { ++ if (x == RETURN_ADDRESS) ++ return (long)get_pc(); + return x; + } + +-int global_func(int x) ++long global_func(long x) + { ++ if (x == RETURN_ADDRESS) ++ return (long)get_pc(); + return x; + } + +@@ -59,27 +96,28 @@ static struct test_entry { + const char *name; + void *data; + int size; +- int writable, execable; ++ int writable; ++ int execable; + int is_huge; + } testtab[] = { +-#define ENT(name, exec) { #name, (void *)&name, sizeof(name), 0, exec, } ++#define ENT(entry_name, exec) { \ ++ .name = #entry_name, \ ++ .data = (void *)&entry_name, \ ++ .size = sizeof(entry_name), \ ++ .writable = 0, \ ++ .execable = exec } ++ + ENT(small_data, 0), + ENT(big_data, 0), + ENT(small_bss, 0), + ENT(big_bss, 0), + ENT(small_const, 0), + ENT(big_const, 0), +- +- /* +- * XXX: Due to the way functions are defined in the powerPC 64-bit ABI, +- * the following entries will point to a call stub in the data segment +- * instead of to the code as one might think. Therefore, test coverage +- * is not quite as good as it could be for ppc64. +- */ + ENT(static_func, 1), + ENT(global_func, 1), + }; + ++ + #define NUM_TESTS (sizeof(testtab) / sizeof(testtab[0])) + + static +@@ -116,12 +154,18 @@ static void check_if_writable(struct test_entry *te) + { + int pid, ret, status; + +- + pid = fork(); + if (pid < 0) + FAIL("fork: %s", strerror(errno)); + else if (pid == 0) { +- (*(char *) te->data) = 0; ++ void *data; ++ ++ if (te->execable) ++ data = get_text_addr(te->data); ++ else ++ data = te->data; ++ ++ (*(char *)data) = 0; + exit (0); + } else { + ret = waitpid(pid, &status, 0); +@@ -137,11 +181,15 @@ static void check_if_writable(struct test_entry *te) + static void do_test(struct test_entry *te) + { + int i; +- volatile int *p = te->data; ++ void *data = te->data; + + check_if_writable(te); ++ verbose_printf("entry: %s, data: %p, writable: %d\n", ++ te->name, data, te->writable); + + if (te->writable) { ++ volatile int *p = data; ++ + for (i = 0; i < (te->size / sizeof(*p)); i++) + p[i] = CONST ^ i; + +@@ -151,17 +199,23 @@ static void do_test(struct test_entry *te) + if (p[i] != (CONST ^ i)) + FAIL("mismatch on %s", te->name); + } else if (te->execable) { +- int (*pf)(int) = te->data; ++ long (*pf)(long) = data; ++ ++ data = get_text_addr(data); + + if ((*pf)(CONST) != CONST) + FAIL("%s returns incorrect results", te->name); + } else { + /* Otherwise just read touch it */ ++ volatile int *p = data; ++ + for (i = 0; i < (te->size / sizeof(*p)); i++) + p[i]; + } + +- te->is_huge = (test_addr_huge(te->data) == 1); ++ te->is_huge = (test_addr_huge(data) == 1); ++ verbose_printf("entry: %s, data: %p, is_huge: %d\n", ++ te->name, data, te->is_huge); + } + + int main(int argc, char *argv[]) diff --git a/SPECS/libhugetlbfs.spec b/SPECS/libhugetlbfs.spec index 33ad8e6..c548021 100644 --- a/SPECS/libhugetlbfs.spec +++ b/SPECS/libhugetlbfs.spec @@ -1,6 +1,6 @@ Name: libhugetlbfs Version: 2.16 -Release: 11%{?dist} +Release: 12%{?dist} Summary: A library which provides easy access to huge pages of memory Group: System Environment/Libraries License: LGPLv2+ @@ -16,6 +16,9 @@ Patch6: libhugetlbfs-2.16-mounts_warning.patch Patch7: libhugetlbfs-2.16-ppc64le-support.patch Patch8: libhugetlbfs-2.16-plt_extrasz_fix.patch Patch9: libhugetlbfs-2.16-map_high_truncate.patch +Patch10:libhugetlbfs-2.20-tests-linkhuge_rw-function-ptr-may-not-refer-to-text.patch +Patch11:libhugetlbfs-2.20-do-not-assume-default-huge-page-size-is-first.patch + BuildRequires: glibc-devel BuildRequires: glibc-static @@ -58,6 +61,8 @@ pool size control. pagesize lists page sizes available on the machine. %patch7 -p1 -b .ppc64le_support %patch8 -p1 -b .plt_extrasz_fix %patch9 -p1 -b .map_high_truncate +%patch10 -p1 -b .linkhuge_rw-func +%patch11 -p1 -b .default-huge-page %build ln -s sys-elf64ppc.S sys-elf64lppc.S @@ -121,6 +126,10 @@ rm -fr $RPM_BUILD_ROOT/%{_sbindir}/ %exclude /usr/lib/perl5/TLBC %changelog +* Tue Jun 07 2016 Petr holasek - 2.16-12 +- linkhuge_rw test fix (#1240568) +- hugeadm fix for firestone ppc systems (#1258622) + * Mon Dec 15 2014 Petr Holasek - 2.16-11 - map_high_truncate_2 test fix (#1161677)