From 1a976aa9ba210a2e932625d746d037d170721279 Mon Sep 17 00:00:00 2001 From: l00580197 Date: Thu, 27 Jul 2023 17:05:35 +0800 Subject: [PATCH] add hugepage --- src/binfmt_rto/binfmt_rto.c | 43 +++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/binfmt_rto/binfmt_rto.c b/src/binfmt_rto/binfmt_rto.c index 2c4f9cf..e3f552c 100644 --- a/src/binfmt_rto/binfmt_rto.c +++ b/src/binfmt_rto/binfmt_rto.c @@ -73,6 +73,10 @@ MODULE_PARM_DESC(debug, "debug mode"); extern int map_vdso(const struct vdso_image *image, unsigned long addr); +unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long pgoff); + #define proc_symbol(SYM) typeof(SYM) *(SYM) static struct global_symbols { #ifdef CONFIG_ARM64 @@ -81,6 +85,7 @@ static struct global_symbols { proc_symbol(cpu_get_elf_hwcap2); proc_symbol(signal_minsigstksz); proc_symbol(arch_elf_adjust_prot); + proc_symbol(vm_mmap_pgoff); #else proc_symbol(elf_hwcap2); /* 22.03 LTS not have get_sigframe_size */ @@ -603,9 +608,31 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, return 0; } +static int elf_read(struct file *file, void *buf, size_t len, loff_t pos); + +static unsigned long vm_mmap_hugepage(struct file *filep, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flag, unsigned long off) +{ + if (len & (HPAGE_SIZE - 1)) + return -EINVAL; + struct page *pages = alloc_pages(GFP_KERNEL, HPAGE_PMD_ORDER); + if (!page) + return -ENOMEM; + void* paddr = page_address(pages); + if (elf_read(filep, paddr, len, off) < 0) { + __free_page(pages); + return -EINVAL; + } + + // mmap pages + flag |= MAP_SHARED | MAP_NORESERVE; + return g_sym.vm_mmap_pgoff(NULL, paddr, len, prot, flag, 0); +} + static unsigned long elf_map(struct file *filep, unsigned long addr, const struct elf_phdr *eppnt, int prot, int type, - unsigned long total_size) + unsigned long total_size, bool is_rto_format) { unsigned long map_addr; unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); @@ -628,9 +655,13 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, */ if (total_size) { total_size = ELF_PAGEALIGN(total_size); - map_addr = vm_mmap(filep, addr, total_size, prot, type, off); - if (!BAD_ADDR(map_addr)) - vm_munmap(map_addr+size, total_size-size); + if (is_rto_format) { + map_addr = vm_mmap_hugepage(filep, addr, total_size, prot, type, off); + } else { + map_addr = vm_mmap(filep, addr, total_size, prot, type, off); + if (!BAD_ADDR(map_addr)) + vm_munmap(map_addr+size, total_size-size); + } } else map_addr = vm_mmap(filep, addr, size, prot, type, off); @@ -891,7 +922,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, load_addr = -vaddr; map_addr = elf_map(interpreter, load_addr + vaddr, - eppnt, elf_prot, elf_type, total_size); + eppnt, elf_prot, elf_type, total_size, is_rto_format); total_size = 0; error = map_addr; if (BAD_ADDR(map_addr)) @@ -1511,7 +1542,7 @@ out_free_interp: } error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, - elf_prot, elf_flags, total_size); + elf_prot, elf_flags, total_size, is_rto_format); if (BAD_ADDR(error)) { retval = IS_ERR((void *)error) ? PTR_ERR((void*)error) : -EINVAL; -- Gitee