summaryrefslogtreecommitdiff
path: root/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
diff options
context:
space:
mode:
Diffstat (limited to '0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch')
-rw-r--r--0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch312
1 files changed, 312 insertions, 0 deletions
diff --git a/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch b/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
new file mode 100644
index 0000000..8d899e5
--- /dev/null
+++ b/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
@@ -0,0 +1,312 @@
+From 7adf5ee832d2649fa85f8f104523932dab64f12e Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Tue, 7 Feb 2023 19:29:11 +0800
+Subject: [PATCH 1/3] ld.so: support ld.so mmap hugetlb hugepage according to
+ PT_LOAD segment granularity
+
+Only attempt to use hugepage to load PT_LOAD segments marked with PF_HUGEPAGE flag.
+Even if the segment is marked with the PF_HUGEPAGE flag, the segment does not
+necessarily use the hugetlb huge page, either because the segment is too small,
+or because the segment is in an address space that is not suitable for using
+a huge page. Also we add added the -i option to hugepageedit to mark any
+PT_LOAD segment with the PF_HUGEPAGE flag.
+
+Signed-off-by: Lv Ying <lvying6@huawei.com>
+---
+ elf/dl-load.c | 15 ++++---
+ elf/dl-map-segments-hugepage.h | 72 ++++++++++++++++++++++++++++++----
+ elf/elf.h | 2 +
+ elf/hugepageedit.c | 58 ++++++++++++++++++++++++---
+ 4 files changed, 128 insertions(+), 19 deletions(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index f4b5c4a7..e0d4fa2e 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1136,6 +1136,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ bool empty_dynamic = false;
+ #ifdef HUGEPAGE_SHARED_LIB
+ bool use_hugepage = false;
++ char hp_bitmap[l->l_phnum];
+ #endif
+
+ /* The struct is initialized to zero so this is not necessary:
+@@ -1182,6 +1183,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ goto lose;
+ }
+
++#ifdef HUGEPAGE_SHARED_LIB
++ if (ph->p_flags & PF_HUGEPAGE) {
++ hp_bitmap[nloadcmds] = 1;
++ use_hugepage = true;
++ } else
++ hp_bitmap[nloadcmds] = 0;
++#endif
+ struct loadcmd *c = &loadcmds[nloadcmds++];
+ c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
+ c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
+@@ -1194,11 +1202,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ if (nloadcmds > 1 && c[-1].mapend != c->mapstart)
+ has_holes = true;
+
+-#ifdef HUGEPAGE_SHARED_LIB
+- if (ph->p_flags & PF_HUGEPAGE)
+- use_hugepage = true;
+-#endif
+-
+ /* Optimize a common case. */
+ #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
+ c->prot = (PF_TO_PROT
+@@ -1297,7 +1300,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ ((GLRO(dl_hugepage_mask) & DL_HUGEPAGE_PROBE_FLAG) && use_hugepage))
+ {
+ errstring = _dl_map_segments_largein (l, fd, header, type, loadcmds, nloadcmds,
+- maplength, has_holes);
++ maplength, hp_bitmap);
+ if (__glibc_unlikely (errstring != NULL))
+ {
+ hp_errcode = errno;
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index 37788ef9..e7202131 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -400,6 +400,55 @@ _extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmd
+ return extra_len;
+ }
+
++static __always_inline const char *
++__mmap_segment_normalsz(const struct loadcmd *c, ElfW(Addr) mapstart, int fd,
++ size_t *mapseglen)
++{
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\tuse normal page mmap segment:[%lx-%lx)\n", mapstart,
++ mapstart + (c->allocend - c->mapstart));
++
++ if (c->mapend > c->mapstart &&
++ (__mmap((void *)mapstart, c->mapend - c->mapstart, c->prot,
++ MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, c->mapoff) == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
++ if (c->allocend > c->dataend) {
++ ElfW(Addr) zero, zeroend, zeropage;
++
++ zero = mapstart + c->dataend - c->mapstart;
++ zeroend = mapstart + c->allocend - c->mapstart;
++ zeropage = ((zero + GLRO(dl_pagesize) - 1)
++ & ~(GLRO(dl_pagesize) - 1));
++
++ if (zeroend < zeropage)
++ zeropage = zeroend;
++
++ if (zeropage > zero) {
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0)) {
++ if (__mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
++ GLRO(dl_pagesize), c->prot|PROT_WRITE) < 0)
++ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
++ }
++
++ memset ((void *) zero, '\0', zeropage - zero);
++
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
++ __mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
++ GLRO(dl_pagesize), c->prot);
++ }
++
++ if (zeroend > zeropage) {
++ if (__mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0) == MAP_FAILED)
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++ }
++ }
++
++ *mapseglen = c->allocend - c->mapstart;
++ return NULL;
++}
++
+ /*
+ * PT_LOAD segment is described by p_filesz and p_memsz.
+ * The bytes from the file are mapped to the beginning of the memory segment.
+@@ -409,11 +458,17 @@ _extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmd
+ */
+ static __always_inline const char *
+ _mmap_segment(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds,
+- const struct loadcmd *c, ElfW(Addr) mapstart, int fd, size_t *mapseglen)
++ const struct loadcmd *c, ElfW(Addr) mapstart, int fd,
++ size_t *mapseglen, const char hp_bitmap[])
+ {
+ const char * errstring = NULL;
+- size_t extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart);
+- size_t memsz_len = 0;
++ size_t extra_len, memsz_len = 0;
++
++ if (!hp_bitmap[((void *)c - (void *)loadcmds) / sizeof(struct loadcmd)]) {
++ return __mmap_segment_normalsz(c, mapstart, fd, mapseglen);
++ }
++
++ extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart);
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+ _dl_debug_printf("\t%s(0x%lx): extra_len = 0x%lx\n\t{\n", __func__,
+ (unsigned long)c, extra_len);
+@@ -448,7 +503,7 @@ static __always_inline const char *
+ _dl_map_segments_largein (struct link_map *l, int fd,
+ const ElfW(Ehdr) *header, int type,
+ const struct loadcmd loadcmds[], size_t nloadcmds,
+- const size_t maplength, bool has_holes)
++ const size_t maplength, const char hp_bitmap[])
+ {
+ if (__glibc_unlikely (type != ET_DYN))
+ return DL_MAP_SEGMENTS_ERROR_TYPE;
+@@ -470,7 +525,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ const struct loadcmd * c = loadcmds;
+ ElfW(Addr) text_addr = ALIGN_UP((ElfW(Addr))map_area_start + (text->mapstart - c->mapstart), SIZE_2MB);
+ size_t mapseglen;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+
+@@ -493,7 +549,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ }
+
+ map_addr += c->mapstart - prev->mapstart;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+ prev = c;
+@@ -514,7 +571,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ }
+
+ map_addr -= prev->mapstart - c->mapstart;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+
+diff --git a/elf/elf.h b/elf/elf.h
+index c5315d1b..a64576bb 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -730,8 +730,10 @@ typedef struct
+
+ /* Legal values for p_flags (segment flags). */
+
++#ifdef HUGEPAGE_SHARED_LIB
+ /* libhugetlbfs's hugeedit use 0x00100000, here use another */
+ #define PF_HUGEPAGE (0x01000000)
++#endif
+ #define PF_X (1 << 0) /* Segment is executable */
+ #define PF_W (1 << 1) /* Segment is writable */
+ #define PF_R (1 << 2) /* Segment is readable */
+diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
+index ab4247ad..0a44ece6 100644
+--- a/elf/hugepageedit.c
++++ b/elf/hugepageedit.c
+@@ -31,18 +31,52 @@
+
+ void print_usage(void)
+ {
+- fprintf(stderr, "%s [-x] [-d] <ELF file>\n" \
++ fprintf(stderr, "%s [-x] [-d] [-i index] <ELF file>\n" \
+ "\tdefault mark all PT_LOAD segment PF_HUGEPAGE flag\n" \
+ "\t-x option only mark executable PT_LOAD segment PF_HUGEPAGE flag\n" \
++ "\t-i [index(start from 0)] option specifies the index that marks the PT_LOAD segment PF_HUGEPAGE flag\n" \
+ "\t-d option delete all the PT_LOAD segment PF_HUGEPAGE flag\n", TOOL_NAME);
+ }
+
++
++static long parse_index(char *str)
++{
++ char *endptr;
++
++ errno = 0;
++ long val = strtol(str, &endptr, 10);
++
++ if (errno != 0) {
++ perror("strtol");
++ return -1;
++ }
++
++ if (endptr == str) {
++ fprintf(stderr, "No digits were found in -i option\n");
++ return -1;
++ }
++
++ if (*endptr != '\0') {
++ fprintf(stderr, "Invalid characters %s in -i %s option\n", endptr, str);
++ return -1;
++ }
++
++ if (val < 0) {
++ fprintf(stderr, "Negative index %ld in -i %s option\n", val, str);
++ return -1;
++ }
++
++ return val;
++}
++
++
+ int main(int argc, char *argv[])
+ {
+ size_t length;
+ int exit_status = -1;
+- int i, opt, delete = 0, exec_only = 0;
+- while ((opt = getopt(argc, argv, "dx")) != -1)
++ int i, opt, delete = 0, exec_only = 0, index_set = 0;
++ long index = -1;
++ while ((opt = getopt(argc, argv, "dxi:")) != -1)
+ {
+ switch (opt)
+ {
+@@ -52,15 +86,21 @@ int main(int argc, char *argv[])
+ case 'x':
+ exec_only = 1;
+ break;
++ case 'i':
++ index = parse_index(optarg);
++ index_set = 1;
++ if (index < 0)
++ return -1;
++ break;
+ default:
+ print_usage();
+ return 0;
+ }
+ }
+
+- if (delete && exec_only)
++ if (delete + exec_only + index_set > 1)
+ {
+- fprintf(stderr, "can not specify -x and -d option at the same time\n");
++ fprintf(stderr, "can not specify -x, -d and -i option at the same time\n");
+ return -1;
+ }
+
+@@ -81,6 +121,12 @@ int main(int argc, char *argv[])
+ if (ehdr == NULL)
+ goto close_fd;
+
++ if (index_set && index >= ((ElfW(Ehdr) *)ehdr)->e_phnum) {
++ fprintf(stderr, "Index %ld in -i %s option out of PT_LOAD segment range\n",
++ index, argv[optind]);
++ goto close_fd;
++ }
++
+ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
+ if (phdr == NULL)
+ goto unmap;
+@@ -100,7 +146,7 @@ int main(int argc, char *argv[])
+ }
+ else
+ {
+- if (exec_only && !(phdr[i].p_flags & PF_X))
++ if ((exec_only && !(phdr[i].p_flags & PF_X)) || (index_set && index != i))
+ continue;
+ phdr[i].p_flags |= PF_HUGEPAGE;
+ }
+--
+2.38.1
+