From 9a60997ea094183dac520185c35b7257ddd0696a Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Wed, 15 Jan 2020 15:45:17 +0900 Subject: [PATCH] shmobj: Support large page Mixing page sizes is allowed by shmobj. Change-Id: Ic48b71da2db6ce3f68fa3dbc8ad5ae96347d6018 Refs: #1381 Refs: #1458 --- arch/arm64/kernel/include/arch-memory.h | 28 +-- arch/arm64/kernel/memory.c | 52 ++++- arch/x86_64/kernel/include/arch-memory.h | 7 +- arch/x86_64/kernel/memory.c | 17 +- kernel/include/memobj.h | 13 ++ kernel/include/page.h | 1 + kernel/include/shm.h | 1 + kernel/mem.c | 16 ++ kernel/process.c | 47 +++- kernel/shmobj.c | 105 +++++++-- kernel/syscall.c | 5 +- lib/include/ihk/mm.h | 5 +- test/issues/1381/C1381.sh | 44 ++++ test/issues/1381/C1381T01.c | 106 +++++++++ test/issues/1381/Makefile | 11 + test/issues/1381/README | 38 ++++ test/issues/1381/aarch64_result.log | 116 ++++++++++ test/issues/1381/x86_64_result.log | 116 ++++++++++ test/issues/1458/C1458T01.c | 267 +++++++++++++++++++++++ test/issues/1458/C1458T01.sh.in | 38 ++++ test/issues/1458/C1458T02.c | 238 ++++++++++++++++++++ test/issues/1458/C1458T02.sh.in | 38 ++++ test/issues/1458/C1458T03.c | 263 ++++++++++++++++++++++ test/issues/1458/C1458T03.sh.in | 38 ++++ test/issues/1458/CMakeLists.txt | 69 ++++++ test/issues/1458/README | 65 ++++++ test/issues/1458/aarch64.conf | 1 + test/issues/1458/aarch64_result.log | 248 +++++++++++++++++++++ test/issues/1458/common.sh.in | 19 ++ test/issues/1458/regression_test.sh | 21 ++ test/issues/1458/x86_64.conf | 1 + test/issues/1458/x86_64_result.log | 253 +++++++++++++++++++++ 32 files changed, 2212 insertions(+), 75 deletions(-) create mode 100755 test/issues/1381/C1381.sh create mode 100644 test/issues/1381/C1381T01.c create mode 100644 test/issues/1381/Makefile create mode 100644 test/issues/1381/README create mode 100644 test/issues/1381/aarch64_result.log create mode 100644 test/issues/1381/x86_64_result.log create mode 100644 test/issues/1458/C1458T01.c create mode 100644 test/issues/1458/C1458T01.sh.in create mode 100644 test/issues/1458/C1458T02.c create mode 100644 test/issues/1458/C1458T02.sh.in create mode 100644 test/issues/1458/C1458T03.c create mode 100644 test/issues/1458/C1458T03.sh.in create mode 100644 test/issues/1458/CMakeLists.txt create mode 100644 test/issues/1458/README create mode 100644 test/issues/1458/aarch64.conf create mode 100644 test/issues/1458/aarch64_result.log create mode 100644 test/issues/1458/common.sh.in create mode 100755 test/issues/1458/regression_test.sh create mode 100644 test/issues/1458/x86_64.conf create mode 100644 test/issues/1458/x86_64_result.log diff --git a/arch/arm64/kernel/include/arch-memory.h b/arch/arm64/kernel/include/arch-memory.h index f5341f5f..23b7b7f0 100644 --- a/arch/arm64/kernel/include/arch-memory.h +++ b/arch/arm64/kernel/include/arch-memory.h @@ -778,32 +778,8 @@ static inline pte_t *get_contiguous_tail(pte_t *__ptep, size_t __pgsize) return (pte_t *)__page_align_up(__ptep + 1, align) - 1; } -static inline int split_contiguous_pages(pte_t *ptep, size_t pgsize) -{ - int ret; - pte_t *head = get_contiguous_head(ptep, pgsize); - pte_t *tail = get_contiguous_tail(ptep, pgsize); - pte_t *ptr; - - uintptr_t phys; - struct page *page; - - phys = pte_get_phys(head); - page = phys_to_page(phys); - if (page && (page_is_in_memobj(page) - || page_is_multi_mapped(page))) { - ret = -EINVAL; - goto out; - } - - for (ptr = head; ptr <= tail; ptr++) { - *ptr &= ~PTE_CONT; - } - - ret = 0; -out: - return ret; -} +int split_contiguous_pages(pte_t *ptep, size_t pgsize, + uint32_t memobj_flags); static inline int page_is_contiguous_head(pte_t *ptep, size_t pgsize) { diff --git a/arch/arm64/kernel/memory.c b/arch/arm64/kernel/memory.c index a84bc218..24ad739e 100644 --- a/arch/arm64/kernel/memory.c +++ b/arch/arm64/kernel/memory.c @@ -2352,7 +2352,8 @@ static int clear_range(struct page_table *pt, struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_head(ptep, pgsize)) { // start pte is not contiguous head - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + memobj ? memobj->flags : 0); if (error) { return error; } @@ -2364,7 +2365,8 @@ static int clear_range(struct page_table *pt, struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_tail(ptep, pgsize)) { // end pte is not contiguous tail - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + memobj ? memobj->flags : 0); if (error) { return error; } @@ -2985,7 +2987,8 @@ out: return error; } -int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, void *addr) +int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, + struct vm_range *range, void *addr) { int error; pte_t *ptep; @@ -3007,7 +3010,9 @@ retry: if (ptep && !ptl_null(ptep, level) && (pgaddr != addr)) { page = NULL; if (ptl_is_contiguous(ptep, level)) { - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + range->memobj ? + range->memobj->flags : 0); if (error) { goto out; } @@ -3018,8 +3023,8 @@ retry: phys = ptl_phys(ptep, level); page = phys_to_page(phys); } - if (page && (page_is_in_memobj(page) - || page_is_multi_mapped(page))) { + if (!is_splitable(page, range->memobj ? + range->memobj->flags : 0)) { error = -EINVAL; kprintf("ihk_mc_pt_split:NYI:page break down\n"); goto out; @@ -3192,7 +3197,9 @@ int move_pte_range(page_table_t pt, struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_head(ptep, pgsize)) { // start pte is not contiguous head - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + range->memobj ? + range->memobj->flags : 0); if (error) { goto out; } @@ -3203,7 +3210,9 @@ int move_pte_range(page_table_t pt, struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_tail(ptep, pgsize)) { // end pte is not contiguous tail - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + range->memobj ? + range->memobj->flags : 0); if (error) { goto out; } @@ -3808,3 +3817,30 @@ void arch_adjust_allocate_page_size(struct page_table *pt, } } } + +int split_contiguous_pages(pte_t *ptep, size_t pgsize, + uint32_t memobj_flags) +{ + int ret; + pte_t *head = get_contiguous_head(ptep, pgsize); + pte_t *tail = get_contiguous_tail(ptep, pgsize); + pte_t *ptr; + + uintptr_t phys; + struct page *page; + + phys = pte_get_phys(head); + page = phys_to_page(phys); + if (!is_splitable(page, memobj_flags)) { + ret = -EINVAL; + goto out; + } + + for (ptr = head; ptr <= tail; ptr++) { + *ptr &= ~PTE_CONT; + } + + ret = 0; +out: + return ret; +} diff --git a/arch/x86_64/kernel/include/arch-memory.h b/arch/x86_64/kernel/include/arch-memory.h index e067a5e1..52de7ac5 100644 --- a/arch/x86_64/kernel/include/arch-memory.h +++ b/arch/x86_64/kernel/include/arch-memory.h @@ -19,6 +19,7 @@ #include #include +struct memobj; #define KERNEL_CS_ENTRY 4 #define KERNEL_DS_ENTRY 5 #define USER_CS_ENTRY 6 @@ -412,10 +413,8 @@ static inline pte_t *get_contiguous_tail(pte_t *__ptep, size_t __pgsize) return __ptep; } -static inline int split_contiguous_pages(pte_t *ptep, size_t pgsize) -{ - return 0; -} +int split_contiguous_pages(pte_t *ptep, size_t pgsize, + uint32_t memobj_flags); static inline int page_is_contiguous_head(pte_t *ptep, size_t pgsize) { diff --git a/arch/x86_64/kernel/memory.c b/arch/x86_64/kernel/memory.c index 6b34036b..606ed0bd 100644 --- a/arch/x86_64/kernel/memory.c +++ b/arch/x86_64/kernel/memory.c @@ -884,7 +884,7 @@ static int split_large_page(pte_t *ptep, size_t pgsize) } for (i = 0; i < PT_ENTRIES; ++i) { - if (phys_base != NOPHYS) { + if (phys_base != NOPHYS && pgsize != PTL2_SIZE) { phys = phys_base + (i * pgsize / PT_ENTRIES); page = phys_to_page(phys); if (page) { @@ -2219,7 +2219,8 @@ out: return error; } -int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, void *addr) +int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, + struct vm_range *range, void *addr) { int error; pte_t *ptep; @@ -2228,7 +2229,6 @@ int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, void *addr) intptr_t phys; struct page *page; - retry: ptep = ihk_mc_pt_lookup_pte(pt, addr, 0, &pgaddr, &pgsize, NULL); if (ptep && !pte_is_null(ptep) && (pgaddr != addr)) { @@ -2237,8 +2237,8 @@ retry: phys = pte_get_phys(ptep); page = phys_to_page(phys); } - if (page && (page_is_in_memobj(page) - || page_is_multi_mapped(page))) { + if (!is_splitable(page, range->memobj ? + range->memobj->flags : 0)) { error = -EINVAL; kprintf("ihk_mc_pt_split:NYI:page break down\n"); goto out; @@ -3001,3 +3001,10 @@ int patch_process_vm(struct process_vm *vm, void *udst, const void *ksrc, size_t dkprintf("patch_process_vm(%p,%p,%p,%lx):%d\n", vm, udst, ksrc, siz, 0); return 0; } /* patch_process_vm() */ + +int split_contiguous_pages(pte_t *ptep, size_t pgsize, + uint32_t memobj_flags) +{ + return 0; +} + diff --git a/kernel/include/memobj.h b/kernel/include/memobj.h index ad5cb5a0..f704d22e 100644 --- a/kernel/include/memobj.h +++ b/kernel/include/memobj.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,8 @@ typedef uintptr_t memobj_copy_page_func_t(struct memobj *obj, uintptr_t orgphys, typedef int memobj_flush_page_func_t(struct memobj *obj, uintptr_t phys, size_t pgsize); typedef int memobj_invalidate_page_func_t(struct memobj *obj, uintptr_t phys, size_t pgsize); typedef int memobj_lookup_page_func_t(struct memobj *obj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag); +typedef int memobj_update_page_func_t(struct memobj *obj, page_table_t pt, + struct page *orig_page, void *vaddr); struct memobj_ops { memobj_free_func_t *free; @@ -69,6 +72,7 @@ struct memobj_ops { memobj_flush_page_func_t *flush_page; memobj_invalidate_page_func_t *invalidate_page; memobj_lookup_page_func_t *lookup_page; + memobj_update_page_func_t *update_page; }; static inline int memobj_ref(struct memobj *obj) @@ -131,6 +135,15 @@ static inline int memobj_lookup_page(struct memobj *obj, off_t off, return -ENXIO; } +static inline int memobj_update_page(struct memobj *obj, page_table_t pt, + struct page *orig_page, void *vaddr) +{ + if (obj->ops->update_page) { + return (*obj->ops->update_page)(obj, pt, orig_page, vaddr); + } + return -ENXIO; +} + static inline int memobj_has_pager(struct memobj *obj) { return !!(obj->flags & MF_HAS_PAGER); diff --git a/kernel/include/page.h b/kernel/include/page.h index 617bdf2d..b0f7ece9 100644 --- a/kernel/include/page.h +++ b/kernel/include/page.h @@ -23,6 +23,7 @@ struct page { ihk_atomic_t count; ihk_atomic64_t mapped; off_t offset; + int pgshift; /* Using by shmobj */ }; /* mode */ diff --git a/kernel/include/shm.h b/kernel/include/shm.h index d8b136b6..76551dbd 100644 --- a/kernel/include/shm.h +++ b/kernel/include/shm.h @@ -107,5 +107,6 @@ void shmobj_list_unlock(void); int shmobj_create_indexed(struct shmid_ds *ds, struct shmobj **objp); void shmlock_user_free(struct shmlock_user *user); int shmlock_user_get(uid_t ruid, struct shmlock_user **userp); +struct shmobj *to_shmobj(struct memobj *memobj); #endif /* HEADER_SHM_H */ diff --git a/kernel/mem.c b/kernel/mem.c index e8facbf4..bc4213e7 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -45,6 +45,7 @@ #include #include #include +#include //#define DEBUG_PRINT_MEM @@ -2712,3 +2713,18 @@ int ihk_mc_get_mem_user_page(void *arg0, page_table_t pt, pte_t *ptep, void *pga return 0; } + +int is_splitable(struct page *page, uint32_t memobj_flags) +{ + int ret = 1; + + if (page && (page_is_in_memobj(page) + || page_is_multi_mapped(page))) { + if (memobj_flags & MF_SHM) { + goto out; + } + ret = 0; + } +out: + return ret; +} diff --git a/kernel/process.c b/kernel/process.c index 47c0b0d8..5e2025b4 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -914,20 +915,19 @@ int split_process_memory_range(struct process_vm *vm, struct vm_range *range, { int error; struct vm_range *newrange = NULL; - unsigned long page_mask; dkprintf("split_process_memory_range(%p,%lx-%lx,%lx,%p)\n", vm, range->start, range->end, addr, splitp); if (range->pgshift != 0) { - page_mask = (1 << range->pgshift) - 1; - if (addr & page_mask) { + if (addr & ((1UL << range->pgshift) - 1)) { /* split addr is not aligned */ range->pgshift = 0; } } - error = ihk_mc_pt_split(vm->address_space->page_table, vm, (void *)addr); + error = ihk_mc_pt_split(vm->address_space->page_table, vm, + range, (void *)addr); if (error) { ekprintf("split_process_memory_range:" "ihk_mc_pt_split failed. %d\n", error); @@ -935,6 +935,37 @@ int split_process_memory_range(struct process_vm *vm, struct vm_range *range, } // memory_stat_rss_add() is called in child-node, i.e. ihk_mc_pt_split() to deal with L3->L2 case + if (range->memobj && range->memobj->flags & MF_SHM) { + /* Target range is shared memory */ + uintptr_t _phys = 0; + struct page *page = NULL; + unsigned long page_mask; + + /* Lookup the page split target */ + error = memobj_lookup_page(range->memobj, + range->objoff + addr - range->start, + 0, &_phys, NULL); + if (error && error != -ENOENT) { + ekprintf("%s: memobj_lookup_page failed. %d\n", + __func__, error); + goto out; + } + page = phys_to_page(_phys); + + if (page) { + page_mask = ~((1UL << page->pgshift) - 1); + /* Update existing page */ + error = memobj_update_page(range->memobj, + vm->address_space->page_table, page, + (void *)(addr & page_mask)); + if (error) { + ekprintf("%s: memobj_update_page failed. %d\n", + __func__, error); + goto out; + } + } + } + newrange = kmalloc(sizeof(struct vm_range), IHK_MC_AP_NOWAIT); if (!newrange) { ekprintf("split_process_memory_range(%p,%lx-%lx,%lx,%p):" @@ -1865,7 +1896,9 @@ int invalidate_process_memory_range(struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_head(ptep, pgsize)) { // start pte is not contiguous head - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + range->memobj ? + range->memobj->flags : 0); if (error) { ihk_spinlock_t *page_table_lock; @@ -1883,7 +1916,9 @@ int invalidate_process_memory_range(struct process_vm *vm, if (ptep && pte_is_contiguous(ptep)) { if (!page_is_contiguous_tail(ptep, pgsize)) { // end pte is not contiguous tail - error = split_contiguous_pages(ptep, pgsize); + error = split_contiguous_pages(ptep, pgsize, + range->memobj ? + range->memobj->flags : 0); if (error) { ihk_spinlock_t *page_table_lock; diff --git a/kernel/shmobj.c b/kernel/shmobj.c index 1abc7b5a..86bfbb84 100644 --- a/kernel/shmobj.c +++ b/kernel/shmobj.c @@ -32,14 +32,16 @@ static memobj_free_func_t shmobj_free; static memobj_get_page_func_t shmobj_get_page; static memobj_invalidate_page_func_t shmobj_invalidate_page; static memobj_lookup_page_func_t shmobj_lookup_page; +static memobj_update_page_func_t shmobj_update_page; static struct memobj_ops shmobj_ops = { .free = &shmobj_free, .get_page = &shmobj_get_page, .lookup_page = &shmobj_lookup_page, + .update_page = &shmobj_update_page, }; -static struct shmobj *to_shmobj(struct memobj *memobj) +struct shmobj *to_shmobj(struct memobj *memobj) { return (struct shmobj *)memobj; } @@ -86,7 +88,8 @@ static struct page *page_list_lookup(struct shmobj *obj, off_t off) struct page *page; list_for_each_entry(page, &obj->page_list, list) { - if (page->offset == off) { + if (page->offset <= off && + off < page->offset + (1UL << page->pgshift)) { goto out; } } @@ -245,7 +248,6 @@ static void shmobj_destroy(struct shmobj *obj) } /* zap page_list */ - npages = (size_t)1 << (obj->pgshift - PAGE_SHIFT); for (;;) { struct page *page; void *page_va; @@ -259,6 +261,7 @@ static void shmobj_destroy(struct shmobj *obj) page_list_remove(obj, page); phys = page_to_phys(page); page_va = phys_to_virt(phys); + npages = (size_t)1 << (page->pgshift - PAGE_SHIFT); if (ihk_atomic_read(&page->count) != 1) { kprintf("%s: WARNING: page count for phys 0x%lx is invalid\n", @@ -270,8 +273,8 @@ static void shmobj_destroy(struct shmobj *obj) * (3) terminate() --> ... --> free_process_memory_range() */ - size_t free_pgsize = 1UL << obj->pgshift; - size_t free_size = 1UL << obj->pgshift; + size_t free_pgsize = 1UL << page->pgshift; + size_t free_size = 1UL << page->pgshift; ihk_mc_free_pages_user(page_va, npages); dkprintf("%lx-,%s: calling memory_stat_rss_sub(),phys=%lx,size=%ld,pgsize=%ld\n", @@ -369,12 +372,6 @@ static int shmobj_get_page(struct memobj *memobj, off_t off, int p2align, memobj, off, p2align, physp, error); goto out; } - if (p2align != (obj->pgshift - PAGE_SHIFT)) { - error = -ENOMEM; - ekprintf("shmobj_get_page(%p,%#lx,%d,%p):pgsize mismatch. %d\n", - memobj, off, p2align, physp, error); - goto out; - } if (obj->real_segsz <= off) { error = -ERANGE; ekprintf("shmobj_get_page(%p,%#lx,%d,%p):beyond the end. %d\n", @@ -416,6 +413,7 @@ static int shmobj_get_page(struct memobj *memobj, off_t off, int p2align, memset(virt, 0, npages*PAGE_SIZE); page->mode = PM_MAPPED; page->offset = off; + page->pgshift = p2align + PAGE_SHIFT; /* Page contents should survive over unmap */ ihk_atomic_set(&page->count, 1); @@ -460,24 +458,12 @@ static int shmobj_lookup_page(struct memobj *memobj, off_t off, int p2align, memobj, off, p2align, physp, error); goto out; } - if (p2align != (obj->pgshift - PAGE_SHIFT)) { - error = -ENOMEM; - ekprintf("shmobj_lookup_page(%p,%#lx,%d,%p):pgsize mismatch. %d\n", - memobj, off, p2align, physp, error); - goto out; - } if (obj->real_segsz <= off) { error = -ERANGE; ekprintf("shmobj_lookup_page(%p,%#lx,%d,%p):beyond the end. %d\n", memobj, off, p2align, physp, error); goto out; } - if ((obj->real_segsz - off) < (PAGE_SIZE << p2align)) { - error = -ENOSPC; - ekprintf("shmobj_lookup_page(%p,%#lx,%d,%p):too large. %d\n", - memobj, off, p2align, physp, error); - goto out; - } page_list_lock(obj); page = page_list_lookup(obj, off); @@ -501,3 +487,76 @@ out: memobj, off, p2align, physp, error, phys); return error; } /* shmobj_lookup_page() */ + +static int shmobj_update_page(struct memobj *memobj, page_table_t pt, + struct page *orig_page, void *vaddr) +{ + struct shmobj *obj = to_shmobj(memobj); + int error; + pte_t *pte; + size_t pte_size, orig_pgsize, page_off; + struct page *page; + int p2align; + uintptr_t base_phys, phys; + + dkprintf("%s(%p,%p,%p,%p)\n", + memobj, pt, orig_page, vaddr); + memobj_ref(&obj->memobj); + + if (!pt || !orig_page || !vaddr) { + error = -ENOENT; + dkprintf("%s(%p,%p,%p,%p): invalid argument. %d\n", __func__, + memobj, pt, orig_page, vaddr); + goto out; + } + base_phys = page_to_phys(orig_page); + pte = ihk_mc_pt_lookup_pte(pt, vaddr, 0, NULL, &pte_size, &p2align); + if (!pte) { + error = -ENOENT; + dkprintf("%s(%p,%p,%p,%p): pte not found. %d\n", + __func__, memobj, pt, orig_page, vaddr); + goto out; + } + + orig_pgsize = (1UL << orig_page->pgshift); + + /* Update original page */ + orig_page->pgshift = p2align + PAGE_SHIFT; + + /* Fit pages to pte */ + page_off = pte_size; + while (page_off < orig_pgsize) { + pte = ihk_mc_pt_lookup_pte(pt, vaddr + page_off, 0, NULL, + &pte_size, &p2align); + if (!pte) { + error = -ENOENT; + dkprintf("%s(%p,%p,%p,%p): pte not found. %d\n", + __func__, memobj, pt, orig_page, vaddr); + goto out; + } + + phys = base_phys + page_off; + page = phys_to_page_insert_hash(phys); + + page->mode = orig_page->mode; + page->offset = orig_page->offset + page_off; + page->pgshift = p2align + PAGE_SHIFT; + + ihk_atomic_set(&page->count, + ihk_atomic_read(&orig_page->count)); + + ihk_atomic64_set(&page->mapped, + ihk_atomic64_read(&orig_page->mapped)); + page_list_insert(obj, page); + + page_off += pte_size; + } + + error = 0; + +out: + memobj_unref(&obj->memobj); + dkprintf("%s(%p,%p,%p,%p):%d\n", __func__, + memobj, pt, orig_page, vaddr); + return error; +} /* shmobj_update_page() */ diff --git a/kernel/syscall.c b/kernel/syscall.c index 2b60730a..76bd78d7 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1714,7 +1714,8 @@ do_mmap(const uintptr_t addr0, const size_t len0, const int prot, } p2align = pgshift - PAGE_SHIFT; } - else if ((flags & MAP_PRIVATE) && (flags & MAP_ANONYMOUS) + else if (((flags & (MAP_PRIVATE | MAP_SHARED)) + && (flags & MAP_ANONYMOUS)) && !proc->thp_disable) { pgshift = 0; /* transparent huge page */ p2align = PAGE_P2ALIGN; @@ -1950,7 +1951,7 @@ do_mmap(const uintptr_t addr0, const size_t len0, const int prot, memset(&ads, 0, sizeof(ads)); ads.shm_segsz = len; ads.shm_perm.mode = SHM_DEST; - ads.init_pgshift = PAGE_SHIFT; + ads.init_pgshift = PAGE_SHIFT + p2align; error = shmobj_create(&ads, &memobj); if (error) { ekprintf("do_mmap:shmobj_create failed. %d\n", error); diff --git a/lib/include/ihk/mm.h b/lib/include/ihk/mm.h index e5b94c2f..83dd4630 100644 --- a/lib/include/ihk/mm.h +++ b/lib/include/ihk/mm.h @@ -20,6 +20,7 @@ #include #include #include +#include struct memobj; struct process_vm; @@ -184,7 +185,9 @@ int ihk_mc_pt_set_range(page_table_t pt, struct process_vm *vm, void *start, int ihk_mc_pt_set_pte(page_table_t pt, pte_t *ptep, size_t pgsize, uintptr_t phys, enum ihk_mc_pt_attribute attr); int ihk_mc_pt_prepare_map(page_table_t pt, void *virt, unsigned long size, enum ihk_mc_pt_prepare_flag); -int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, void *addr); +int ihk_mc_pt_split(page_table_t pt, struct process_vm *vm, + struct vm_range *range, void *addr); +int is_splitable(struct page *page, uint32_t memobj_flags); typedef int pte_visitor_t(void *arg, page_table_t pt, pte_t *ptep, void *pgaddr, int pgshift); diff --git a/test/issues/1381/C1381.sh b/test/issues/1381/C1381.sh new file mode 100755 index 00000000..9ed08e11 --- /dev/null +++ b/test/issues/1381/C1381.sh @@ -0,0 +1,44 @@ +#/bin/sh + +USELTP=1 +USEOSTEST=0 + +. ../../common.sh + +issue="1381" +tid=01 + +arch=`uname -p` +if [ "$arch" == "x86_64" ]; then + pgshift=21 +elif [ "$arch" == "aarch64" ]; then + pgshift=29 +fi + +tname=`printf "C${issue}T%02d" ${tid}` +echo "*** ${tname} start *******************************" +${MCEXEC} ./C1381T01 ${pgshift} + +if [ $? -eq 0 ]; then + echo "*** ${tname} PASSED ******************************" +else + echo "*** ${tname} FAILED ******************************" +fi +let tid++ +echo "" + +for tp in futex_wake04 shmat01 shmat02 shmat03 shmctl01 shmctl02 shmctl03 shmctl04 shmdt01 shmdt02 shmget01 shmget02 shmget03 shmget04 shmget05 +do + tname=`printf "C${issue}T%02d" ${tid}` + echo "*** ${tname} start *******************************" + sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt + ok=`grep PASS $tp.txt | wc -l` + ng=`grep FAIL $tp.txt | wc -l` + if [ $ng = 0 ]; then + echo "*** ${tname} PASSED ($ok)" + else + echo "*** ${tname} FAILED (ok=$ok ng=$ng)" + fi + let tid++ + echo "" +done diff --git a/test/issues/1381/C1381T01.c b/test/issues/1381/C1381T01.c new file mode 100644 index 00000000..f9a848f0 --- /dev/null +++ b/test/issues/1381/C1381T01.c @@ -0,0 +1,106 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#define PAGES 3 +#define MAP_HUGE_SHIFT 26 + +static unsigned long ps, hps; + +void *test_mmap(unsigned long size, int pgshift) +{ + int lp_flags = 0; + + if (pgshift != 0) { + lp_flags = MAP_HUGETLB | (pgshift << MAP_HUGE_SHIFT); + } + + return mmap(NULL, size, PROT_WRITE | PROT_READ, + MAP_ANONYMOUS | MAP_SHARED | + lp_flags, + -1, 0); +} + +int main(int argc, char **argv) +{ + void *addr; + int i, pgshift, err, ret = 0; + size_t size; + + if (argc < 2) { + printf("error: too few arguments\n"); + ret = -1; + goto out; + } + pgshift = atoi(argv[1]); + hps = (1 << pgshift); + ps = getpagesize(); + + printf("** Case 1: specified MAP_HUGETLB\n"); + size = hps * PAGES; + addr = test_mmap(size, pgshift); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + memset(addr, 'a', size); + errno = 0; + err = munmap(addr + size - ps, ps); + if (err == -1 && errno == EINVAL) { + printf("[OK] munmap returned %d and errno: EINVAL\n", err); + } + else { + printf("[NG] munamp succceeded\n"); + ret = -1; +// goto out; + } + + printf("** Case 2: size is aligned on large page\n"); + size = hps * PAGES; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + memset(addr, 'a', size); + errno = 0; + err = munmap(addr + size - ps, ps); + if (err == -1 && errno == EINVAL) { + printf("[OK] munmap returned %d and errno: EINVAL\n", err); + } + else { + printf("[NG] munamp succceeded\n"); + ret = -1; +// goto out; + } + + printf("** Case 3: size is NOT aligned on large page\n"); + size = hps * PAGES - ps; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + memset(addr, 'a', size); + errno = 0; + err = munmap(addr + size - ps, ps); + if (err == 0 && errno == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + +out: + return ret; +} diff --git a/test/issues/1381/Makefile b/test/issues/1381/Makefile new file mode 100644 index 00000000..7f4518c2 --- /dev/null +++ b/test/issues/1381/Makefile @@ -0,0 +1,11 @@ +CFLAGS=-g +LDFLAGS= + +TARGET= C1381T01 + +all: $(TARGET) + +test: all + sh ./C1381.sh +clean: + rm -f $(TARGET) *.o *.txt diff --git a/test/issues/1381/README b/test/issues/1381/README new file mode 100644 index 00000000..8c0a1ce0 --- /dev/null +++ b/test/issues/1381/README @@ -0,0 +1,38 @@ +【Issue#1381 動作確認】 +□ テスト内容 +1. 以下のケースでMAP_SHARED指定のmmapをした領域の、 + 最後のスモールページ1ページ分をmunmapし、期待通りの動作となることを確認する + - MAP_HUGETLB指定 : munmapが-1を返し、errnoにEINVALがセットされる + - ラージページサイズの倍数のサイズ : munampが-1を返し、errnoにEINVALがセットされる + - ラージページサイズの倍数ではないサイズ :munmapが成功する + +2. Issueで報告された以下のLTPを実行し、症状が発生しないことを確認する + - futex_wake04 + +3. 以下のLTPを用いて既存のshm機能に影響が無いことを確認 + - shmat01 + - shmat02 + - shmat03 + - shmctl01 + - shmctl02 + - shmctl03 + - shmctl04 + - shmdt01 + - shmdt02 + - shmget01 + - shmget02 + - shmget03 + - shmget04 + - shmget05 + +□ 実行手順 +$ make test + +McKernelのインストール先や、OSTEST, LTPの配置場所は、 +$HOME/.mck_test_config を参照している +.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを +$HOMEにコピーし、適宜編集する + +□ 実行結果 +x86_64_result.log aarch64_result.log 参照。 +すべての項目をPASSしていることを確認。 diff --git a/test/issues/1381/aarch64_result.log b/test/issues/1381/aarch64_result.log new file mode 100644 index 00000000..b22a90c6 --- /dev/null +++ b/test/issues/1381/aarch64_result.log @@ -0,0 +1,116 @@ +*** C1381T01 start ******************************* +** Case 1: specified MAP_HUGETLB +[OK] munmap returned -1 and errno: EINVAL +** Case 2: size is aligned on large page +[OK] munmap returned -1 and errno: EINVAL +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +*** C1381T01 PASSED ****************************** + +*** C1381T02 start ******************************* +futex_wake04 0 TINFO : Hugepagesize 536870912 +futex_wake04 1 TPASS : Hi hydra, thread2 awake! +*** C1381T02 PASSED (1) + +*** C1381T03 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat01.c:147: PASS: shmat() succeeded to attach NULL address +shmat01.c:147: PASS: shmat() succeeded to attach aligned address +shmat01.c:147: PASS: shmat() succeeded to attach unaligned address with SHM_RND +shmat01.c:147: PASS: shmat() succeeded to attach aligned address with SHM_READONLY, and got S IGSEGV on write + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** C1381T03 PASSED (4) + +*** C1381T04 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EACCES + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1381T04 PASSED (3) + +*** C1381T05 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat03.c:75: INFO: Attempting to attach shared memory to null page +shmat03.c:91: INFO: Mapped shared memory to 0x1000001e0000 +shmat03.c:98: PASS: The kernel assigned a different VM address +shmat03.c:101: INFO: Touching shared memory to see if anything strange happens + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1381T05 PASSED (1) + +*** C1381T06 start ******************************* +shmctl01 1 TPASS : pid, size, # of attaches and mode are correct - pass #1 +shmctl01 2 TPASS : pid, size, # of attaches and mode are correct - pass #2 +shmctl01 3 TPASS : new mode and change time are correct +shmctl01 4 TPASS : get correct shared memory limits +shmctl01 5 TPASS : get correct shared memory id +shmctl01 6 TPASS : SHM_LOCK is set +shmctl01 7 TPASS : SHM_LOCK is cleared +shmctl01 8 TPASS : shared memory appears to be removed +*** C1381T06 PASSED (8) + +*** C1381T07 start ******************************* +shmctl02 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl02 2 TPASS : expected failure - errno = 14 : Bad address +shmctl02 3 TPASS : expected failure - errno = 14 : Bad address +shmctl02 4 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 5 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 6 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +shmctl02 7 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +*** C1381T07 PASSED (5) + +*** C1381T08 start ******************************* +shmctl03 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl03 2 TPASS : expected failure - errno = 1 : Operation not permitted +shmctl03 3 TPASS : expected failure - errno = 1 : Operation not permitted +*** C1381T08 PASSED (3) + +*** C1381T09 start ******************************* +shmctl04 1 TPASS : SHM_INFO call succeeded +*** C1381T09 PASSED (1) + +*** C1381T10 start ******************************* +shmdt01 1 TPASS : shared memory detached correctly +*** C1381T10 PASSED (1) + +*** C1381T11 start ******************************* +shmdt02 1 TPASS : expected failure - errno = 22 : Invalid argument +*** C1381T11 PASSED (1) + +*** C1381T12 start ******************************* +shmget01 1 TPASS : size, pid & mode are correct +*** C1381T12 PASSED (1) + +*** C1381T13 start ******************************* +shmget02 1 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 2 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 3 TPASS : expected failure - errno = 17 : File exists +shmget02 4 TPASS : expected failure - errno = 2 : No such file or directory +*** C1381T13 PASSED (4) + +*** C1381T14 start ******************************* +shmget03 1 TPASS : expected failure - errno = 28 : No space left on device +*** C1381T14 PASSED (1) + +*** C1381T15 start ******************************* +shmget04 1 TPASS : expected failure - errno = 13 : Permission denied +*** C1381T15 PASSED (1) + +*** C1381T16 start ******************************* +shmget05 1 TPASS : expected failure - errno = 13 : Permission denied +*** C1381T16 PASSED (1) diff --git a/test/issues/1381/x86_64_result.log b/test/issues/1381/x86_64_result.log new file mode 100644 index 00000000..c78259ec --- /dev/null +++ b/test/issues/1381/x86_64_result.log @@ -0,0 +1,116 @@ +*** C1381T01 start ******************************* +** Case 1: specified MAP_HUGETLB +[OK] munmap returned -1 and errno: EINVAL +** Case 2: size is aligned on large page +[OK] munmap returned -1 and errno: EINVAL +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +*** C1381T01 PASSED ****************************** + +*** C1381T02 start ******************************* +futex_wake04 0 TINFO : Hugepagesize 2097152 +futex_wake04 1 TPASS : Hi hydra, thread2 awake! +*** C1381T02 PASSED (1) + +*** C1381T03 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat01.c:147: PASS: shmat() succeeded to attach NULL address +shmat01.c:147: PASS: shmat() succeeded to attach aligned address +shmat01.c:147: PASS: shmat() succeeded to attach unaligned address with SHM_RND +shmat01.c:147: PASS: shmat() succeeded to attach aligned address with SHM_READONLY, and got SIGSEGV on write + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** C1381T03 PASSED (4) + +*** C1381T04 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EACCES + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1381T04 PASSED (3) + +*** C1381T05 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat03.c:75: INFO: Attempting to attach shared memory to null page +shmat03.c:91: INFO: Mapped shared memory to 0x2aaaaadea000 +shmat03.c:98: PASS: The kernel assigned a different VM address +shmat03.c:101: INFO: Touching shared memory to see if anything strange happens + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1381T05 PASSED (1) + +*** C1381T06 start ******************************* +shmctl01 1 TPASS : pid, size, # of attaches and mode are correct - pass #1 +shmctl01 2 TPASS : pid, size, # of attaches and mode are correct - pass #2 +shmctl01 3 TPASS : new mode and change time are correct +shmctl01 4 TPASS : get correct shared memory limits +shmctl01 5 TPASS : get correct shared memory id +shmctl01 6 TPASS : SHM_LOCK is set +shmctl01 7 TPASS : SHM_LOCK is cleared +shmctl01 8 TPASS : shared memory appears to be removed +*** C1381T06 PASSED (8) + +*** C1381T07 start ******************************* +shmctl02 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl02 2 TPASS : expected failure - errno = 14 : Bad address +shmctl02 3 TPASS : expected failure - errno = 14 : Bad address +shmctl02 4 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 5 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 6 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +shmctl02 7 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +*** C1381T07 PASSED (5) + +*** C1381T08 start ******************************* +shmctl03 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl03 2 TPASS : expected failure - errno = 1 : Operation not permitted +shmctl03 3 TPASS : expected failure - errno = 1 : Operation not permitted +*** C1381T08 PASSED (3) + +*** C1381T09 start ******************************* +shmctl04 1 TPASS : SHM_INFO call succeeded +*** C1381T09 PASSED (1) + +*** C1381T10 start ******************************* +shmdt01 1 TPASS : shared memory detached correctly +*** C1381T10 PASSED (1) + +*** C1381T11 start ******************************* +shmdt02 1 TPASS : expected failure - errno = 22 : Invalid argument +*** C1381T11 PASSED (1) + +*** C1381T12 start ******************************* +shmget01 1 TPASS : size, pid & mode are correct +*** C1381T12 PASSED (1) + +*** C1381T13 start ******************************* +shmget02 1 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 2 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 3 TPASS : expected failure - errno = 17 : File exists +shmget02 4 TPASS : expected failure - errno = 2 : No such file or directory +*** C1381T13 PASSED (4) + +*** C1381T14 start ******************************* +shmget03 1 TPASS : expected failure - errno = 28 : No space left on device +*** C1381T14 PASSED (1) + +*** C1381T15 start ******************************* +shmget04 1 TPASS : expected failure - errno = 13 : Permission denied +*** C1381T15 PASSED (1) + +*** C1381T16 start ******************************* +shmget05 1 TPASS : expected failure - errno = 13 : Permission denied +*** C1381T16 PASSED (1) diff --git a/test/issues/1458/C1458T01.c b/test/issues/1458/C1458T01.c new file mode 100644 index 00000000..91c9a587 --- /dev/null +++ b/test/issues/1458/C1458T01.c @@ -0,0 +1,267 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGES 3 +#define MAP_HUGE_SHIFT 26 + +static unsigned long ps, hps; + +void *test_mmap(unsigned long size, int pgshift) +{ + int lp_flags = 0; + + if (pgshift != 0) { + lp_flags = MAP_HUGETLB | (pgshift << MAP_HUGE_SHIFT); + } + + return mmap(NULL, size, PROT_WRITE | PROT_READ, + MAP_ANONYMOUS | MAP_SHARED | + lp_flags, + -1, 0); +} + +int check_data(char *data_head, char chk_data, unsigned long off1, + unsigned long off2, unsigned long off3) +{ + int ret = -1; + + if (*(data_head + off1) == chk_data && + *(data_head + off2) == chk_data && + *(data_head + off3) == chk_data) { + ret = 0; + } + + return ret; +} + +int main(int argc, char **argv) +{ + void *addr; + int map_pgshift, unmap_pgshift, pid, status, err, ret = 0; + size_t size, unmap_off; + + if (argc < 3) { + printf("error: too few arguments\n"); + ret = -1; + goto out; + } + map_pgshift = atoi(argv[1]); + unmap_pgshift = atoi(argv[2]); + hps = (1 << map_pgshift); + ps = (1 << unmap_pgshift); + unmap_off = hps * (PAGES - 1) - ps; + + printf("** Case 1: specified MAP_HUGETLB\n"); + size = hps * PAGES; + addr = test_mmap(size, map_pgshift); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + memset(addr, 'a', size); + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + if (check_data((char *)addr, 'a', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + printf("** Case 2: size is aligned on large page\n"); + size = hps * PAGES; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + memset(addr, 'a', size); + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + if (check_data((char *)addr, 'a', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + printf("** Case 3: size is NOT aligned on large page\n"); + size = hps * PAGES - ps; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + memset(addr, 'a', size); + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + if (check_data((char *)addr, 'a', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + +out: + return ret; +} diff --git a/test/issues/1458/C1458T01.sh.in b/test/issues/1458/C1458T01.sh.in new file mode 100644 index 00000000..7ab7a4ca --- /dev/null +++ b/test/issues/1458/C1458T01.sh.in @@ -0,0 +1,38 @@ +#!/usr/bin/bash + +SCRIPT_PATH=$(readlink -m "${BASH_SOURCE[0]}") +SCRIPT_NAME="${SCRIPT_PATH##*/}" + +# prepare recorddir +. @CMAKE_INSTALL_PREFIX@/bin/common.sh +recorddir=$WORKDIR/output/$SCRIPT_NAME +[[ ! -d $recorddir ]] && mkdir -p $recorddir + +issue="1458" +tid=01 +tname=`printf "C${issue}T%02d" ${tid}` + +echo "*** ${tname} start *******************************" +ng=0 +for mapps in ${PS_LIST} +do + for unmapps in ${PS_LIST} + do + if [ $unmapps -ge $mapps ]; then + continue + fi + log_file=$recorddir/${SCRIPT_NAME}.log + echo "** Map pgshift:${mapps} Unmap pgshift:${unmapps}" | tee $log_file + sudo @WITH_MCK@/bin/mcexec @CMAKE_INSTALL_PREFIX@/bin/${tname} ${mapps} ${unmapps} | tee $log_file + if [ $? -ne 0 ]; then + $((++ng)) + fi + done +done +if [ $ng -eq 0 ]; then + echo "*** ${tname} PASSED ******************************" +else + echo "*** ${tname} FAILED ******************************" +fi +exit $ng + diff --git a/test/issues/1458/C1458T02.c b/test/issues/1458/C1458T02.c new file mode 100644 index 00000000..667d3837 --- /dev/null +++ b/test/issues/1458/C1458T02.c @@ -0,0 +1,238 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGES 3 +#define MAP_HUGE_SHIFT 26 + +static unsigned long ps, hps; + +void *test_mmap(unsigned long size, int pgshift) +{ + int lp_flags = 0; + + if (pgshift != 0) { + lp_flags = MAP_HUGETLB | (pgshift << MAP_HUGE_SHIFT); + } + + return mmap(NULL, size, PROT_WRITE | PROT_READ, + MAP_ANONYMOUS | MAP_SHARED | + lp_flags, + -1, 0); +} + +int check_data(char *data_head, char chk_data, unsigned long off1, + unsigned long off2, unsigned long off3) +{ + int ret = -1; + + if (*(data_head + off1) == chk_data && + *(data_head + off2) == chk_data && + *(data_head + off3) == chk_data) { + ret = 0; + } + + return ret; +} + +int main(int argc, char **argv) +{ + void *addr; + int map_pgshift, unmap_pgshift, pid, status, err, ret = 0; + size_t size, unmap_off; + + if (argc < 3) { + printf("error: too few arguments\n"); + ret = -1; + goto out; + } + map_pgshift = atoi(argv[1]); + unmap_pgshift = atoi(argv[2]); + hps = (1 << map_pgshift); + ps = (1 << unmap_pgshift); + unmap_off = hps * (PAGES - 1) - ps; + + printf("** Case 1: specified MAP_HUGETLB\n"); + size = hps * PAGES; + unmap_off = hps * (PAGES - 1) - ps; + addr = test_mmap(size, map_pgshift); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0 && errno == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + printf("** Case 2: size is aligned on large page\n"); + size = hps * PAGES; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0 && errno == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + printf("** Case 3: size is NOT aligned on large page\n"); + size = hps * PAGES - ps; + addr = test_mmap(size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0 && errno == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + +out: + return ret; +} diff --git a/test/issues/1458/C1458T02.sh.in b/test/issues/1458/C1458T02.sh.in new file mode 100644 index 00000000..a6e57e4d --- /dev/null +++ b/test/issues/1458/C1458T02.sh.in @@ -0,0 +1,38 @@ +#!/usr/bin/bash + +SCRIPT_PATH=$(readlink -m "${BASH_SOURCE[0]}") +SCRIPT_NAME="${SCRIPT_PATH##*/}" + +# prepare recorddir +. @CMAKE_INSTALL_PREFIX@/bin/common.sh +recorddir=$WORKDIR/output/$SCRIPT_NAME +[[ ! -d $recorddir ]] && mkdir -p $recorddir + +issue="1458" +tid=02 +tname=`printf "C${issue}T%02d" ${tid}` + +echo "*** ${tname} start *******************************" +ng=0 +for mapps in ${PS_LIST} +do + for unmapps in ${PS_LIST} + do + if [ $unmapps -ge $mapps ]; then + continue + fi + log_file=$recorddir/${SCRIPT_NAME}.log + echo "** Map pgshift:${mapps} Unmap pgshift:${unmapps}" | tee $log_file + sudo @WITH_MCK@/bin/mcexec @CMAKE_INSTALL_PREFIX@/bin/${tname} ${mapps} ${unmapps} | tee $log_file + if [ $? -ne 0 ]; then + $((++ng)) + fi + done +done +if [ $ng -eq 0 ]; then + echo "*** ${tname} PASSED ******************************" +else + echo "*** ${tname} FAILED ******************************" +fi +exit $ng + diff --git a/test/issues/1458/C1458T03.c b/test/issues/1458/C1458T03.c new file mode 100644 index 00000000..b9f85c9b --- /dev/null +++ b/test/issues/1458/C1458T03.c @@ -0,0 +1,263 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGES 3 +#define MAP_HUGE_SHIFT 26 + +static unsigned long ps, hps; +static int shmid = -1; + +void *test_shmget(key_t key, unsigned long size, int pgshift) +{ + int shm_flags = 0; + + if (pgshift != 0) { + shm_flags |= SHM_HUGETLB; + } + + shmid = shmget(key, size, IPC_CREAT | 0660 | shm_flags); + if (shmid == -1) { + perror("shmget fail:"); + return NULL; + } + printf("shmid: %d\n", shmid); + return shmat(shmid, NULL, 0); +} + +int check_data(char *data_head, char chk_data, unsigned long off1, + unsigned long off2, unsigned long off3) +{ + int ret = -1; + + if (*(data_head + off1) == chk_data && + *(data_head + off2) == chk_data && + *(data_head + off3) == chk_data) { + ret = 0; + } + + return ret; +} + +int main(int argc, char **argv) +{ + void *addr; + int map_pgshift, unmap_pgshift, pid, status, err, ret = 0; + size_t size, unmap_off; + key_t key = ftok(argv[0], 0); + + if (argc < 3) { + printf("error: too few arguments\n"); + ret = -1; + goto out; + } + map_pgshift = atoi(argv[1]); + unmap_pgshift = atoi(argv[2]); + hps = (1 << map_pgshift); + ps = (1 << unmap_pgshift); + unmap_off = hps * (PAGES - 1) - ps; + + printf("** Case 1: specified MAP_HUGETLB\n"); + size = hps * PAGES; + addr = test_shmget(key, size, map_pgshift); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + + if (shmctl(shmid, IPC_RMID, NULL) == -1) { + printf("[NG] shmctl(IPC_RMID) failed\n"); + } + else { + printf("[OK] shmctl(IPC_RMID) succeeded\n"); + } + + printf("** Case 2: size is aligned on large page\n"); + size = hps * PAGES; + addr = test_shmget(key, size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + if (shmctl(shmid, IPC_RMID, NULL) == -1) { + printf("[NG] shmctl(IPC_RMID) failed\n"); + } + else { + printf("[OK] shmctl(IPC_RMID) succeeded\n"); + } + + printf("** Case 3: size is NOT aligned on large page\n"); + size = hps * PAGES - ps; + addr = test_shmget(key, size, 0); + if (addr == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + } + + errno = 0; + err = munmap(addr + unmap_off, ps); + if (err == 0) { + printf("[OK] munamp succceeded\n"); + } + else { + printf("[NG] munmap returned %d and errno: EINVAL\n", err); + ret = -1; +// goto out; + } + + pid = fork(); + if (pid == 0) { + /* Child */ + memset(addr, 'b', unmap_off); + memset(addr + unmap_off + ps, 'b', hps); + memset(addr + unmap_off, '0', ps); /* expect SEGV */ + return 0; + } + else if (pid > 0) { + /* Parent */ + if (waitpid(pid, &status, 0) == pid) { + if (WIFSIGNALED(status) && + WTERMSIG(status) == SIGSEGV) { + printf("[OK] Occurred SEGV on unmap area\n"); + } + else { + printf("[NG] Didn't occur SEGV\n"); + ret = -1; + } + } + else { + printf("[NG] waitpid failed\n"); + ret = -1; + } + } + else { + printf("[NG] fork failed\n"); + ret = -1; + } + + if (check_data((char *)addr, 'b', + 0, unmap_off - 1, unmap_off + ps) == 0) { + printf("[OK] data is correct\n"); + } + else { + printf("[NG] data is NOT correct\n"); + ret = -1; + } + if (shmctl(shmid, IPC_RMID, NULL) == -1) { + printf("[NG] shmctl(IPC_RMID) failed\n"); + } + else { + printf("[OK] shmctl(IPC_RMID) succeeded\n"); + } + +out: + return ret; +} diff --git a/test/issues/1458/C1458T03.sh.in b/test/issues/1458/C1458T03.sh.in new file mode 100644 index 00000000..924dd847 --- /dev/null +++ b/test/issues/1458/C1458T03.sh.in @@ -0,0 +1,38 @@ +#!/usr/bin/bash + +SCRIPT_PATH=$(readlink -m "${BASH_SOURCE[0]}") +SCRIPT_NAME="${SCRIPT_PATH##*/}" + +# prepare recorddir +. @CMAKE_INSTALL_PREFIX@/bin/common.sh +recorddir=$WORKDIR/output/$SCRIPT_NAME +[[ ! -d $recorddir ]] && mkdir -p $recorddir + +issue="1458" +tid=03 +tname=`printf "C${issue}T%02d" ${tid}` + +echo "*** ${tname} start *******************************" +ng=0 +for mapps in ${PS_LIST} +do + for unmapps in ${PS_LIST} + do + if [ $unmapps -ge $mapps ]; then + continue + fi + log_file=$recorddir/${SCRIPT_NAME}.log + echo "** Map pgshift:${mapps} Unmap pgshift:${unmapps}" | tee $log_file + sudo @WITH_MCK@/bin/mcexec @CMAKE_INSTALL_PREFIX@/bin/${tname} ${mapps} ${unmapps} | tee $log_file + if [ $? -ne 0 ]; then + $((++ng)) + fi + done +done +if [ $ng -eq 0 ]; then + echo "*** ${tname} PASSED ******************************" +else + echo "*** ${tname} FAILED ******************************" +fi +exit $ng + diff --git a/test/issues/1458/CMakeLists.txt b/test/issues/1458/CMakeLists.txt new file mode 100644 index 00000000..82e131a6 --- /dev/null +++ b/test/issues/1458/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_policy(SET CMP0005 NEW) + +# Options: -DWITH_MCK= +add_definitions(-DWITH_MCK=${WITH_MCK}) + +# Options: -DWITH_MCK_SRC= +add_definitions(-DWITH_MCK_SRC=${WITH_MCK_SRC}) + +# not used when integrated with autotest +# Options: -DWITH_MCK_BUILD= +add_definitions(-DWITH_MCK_BUILD=${WITH_MCK_BUILD}) + +# for autotest +if(NOT DEFINED CMAKE_INSTALL_PREFIX_SCRIPTS) + set(CMAKE_INSTALL_PREFIX_SCRIPTS ${CMAKE_INSTALL_PREFIX}/scripts) +endif() + +cmake_minimum_required(VERSION 2.0) + +project(myautotest C) + +# CPPFLAGS + +# CFLAGS +set(CFLAGS_WARNING "-Wall" "-Wextra" "-Wno-unused-parameter" "-Wno-sign-compare" "-Wno-unused-function" ${EXTRA_WARNINGS} CACHE STRING "Warning flags") +add_compile_options(-O2 -g ${CFLAGS_WARNING}) + +# -L, this must be done before adding dependants + +# -Wl,--rpath=, this must be done before adding dependants +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +foreach(target IN ITEMS + C1458T01 + C1458T02 + C1458T03 + ) + + # Add target + add_executable(${target} ${target}.c) + + # -D + + # -I + + # -l + + # String replacement and install + configure_file(${target}.sh.in shmobj-${target} @ONLY) + + # Install + install(TARGETS ${target} DESTINATION bin) + install(PROGRAMS ${CMAKE_BINARY_DIR}/shmobj-${target} DESTINATION ${CMAKE_INSTALL_PREFIX_SCRIPTS}) +endforeach() + +foreach(target IN ITEMS + common.sh + ) + configure_file(${target}.in ${target} @ONLY) + install(PROGRAMS ${CMAKE_BINARY_DIR}/${target} DESTINATION bin) +endforeach() + +foreach(target IN ITEMS + x86_64.conf + aarch64.conf + ) + install(FILES ${target} DESTINATION etc) +endforeach() + diff --git a/test/issues/1458/README b/test/issues/1458/README new file mode 100644 index 00000000..8f67f3f8 --- /dev/null +++ b/test/issues/1458/README @@ -0,0 +1,65 @@ +【Issue#1458 動作確認】 +□ テスト内容 +1. C1458T01 + 以下のケースでMAP_SHARED指定のmmapをした領域についてページインした後、 + 最後から2番めのラージページの最後の部分をより小さいページサイズ1ページ分でunmapし、 + 期待通りの動作となることを確認する + また、当該領域への読み書き操作が正常に行えることを確認する + - MAP_HUGETLB指定 : munmapが成功する + - ラージページサイズの倍数のサイズ : munmapが成功する + - ラージページサイズの倍数ではないサイズ :munmapが成功する + +2. C1458T02 + 以下のケースでMAP_SHARED指定のmmapをした領域についてページインする前に、 + 最後から2番めのラージページの最後の部分をより小さいページサイズ1ページ分でunmapし、 + 期待通りの動作となることを確認する + また、当該領域への読み書き操作が正常に行えることを確認する + - MAP_HUGETLB指定 : munmapが成功する + - ラージページサイズの倍数のサイズ : munmapが成功する + - ラージページサイズの倍数ではないサイズ :munmapが成功する + +3. C1458T03 + 以下のケースでshmget()で作成した共有メモリ領域の、 + 最後から2番めのラージページの最後の部分をより小さいページサイズ1ページ分でunmapし、 + 期待通りの動作となることを確認する + また、当該領域への読み書き操作が正常に行えることを確認する + - MAP_HUGETLB指定 : munmapが成功する + - ラージページサイズの倍数のサイズ : munmapが成功する + - ラージページサイズの倍数ではないサイズ :munmapが成功する + +4. 以下のLTPを用いて既存のshm機能に影響が無いことを確認する + - shmat01 + - shmat02 + - shmat03 + - shmctl01 + - shmctl02 + - shmctl03 + - shmctl04 + - shmdt01 + - shmdt02 + - shmget01 + - shmget02 + - shmget03 + - shmget04 + - shmget05 + +□ 実行手順 +1. McKernelをビルドした際に生成されるmck_test_config.sample ファイルを + $HOME/.mck_test_configとしてコピーし、パスを編集する。 + +2. 以下の手順でビルドと実行を行う +$ (build mckernel) +$ cd /test/issues/1458 +$ mkdir build && cd build +$ cmake ../ -DWITH_MCK= -DWITH_MCK_SRC= -DWITH_MCK_BUILD= -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_INSTALL_PREFIX_SCRIPTS=./install/data/scripts +$ make install +$ ./install/scripts/issue-C1458T01 +$ ./install/scripts/issue-C1458T02 +$ ./install/scripts/issue-C1458T03 + +$ cd /test/issues/1458 +$ ./regression_test.sh + +□ 実行結果 +x86_64_result.log aarch64_result.log 参照。 +すべての項目をPASSしていることを確認。 diff --git a/test/issues/1458/aarch64.conf b/test/issues/1458/aarch64.conf new file mode 100644 index 00000000..c5d1de1c --- /dev/null +++ b/test/issues/1458/aarch64.conf @@ -0,0 +1 @@ +PS_LIST="16 21 29" diff --git a/test/issues/1458/aarch64_result.log b/test/issues/1458/aarch64_result.log new file mode 100644 index 00000000..ce80262e --- /dev/null +++ b/test/issues/1458/aarch64_result.log @@ -0,0 +1,248 @@ +*** C1458T01 start ******************************* +** Map pgshift:21 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:29 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:29 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +*** C1458T01 PASSED ****************************** +*** C1458T02 start ******************************* +** Map pgshift:21 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:29 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:29 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +*** C1458T02 PASSED ****************************** +*** C1458T03 start ******************************* +** Map pgshift:21 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +shmid: 18 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 65555 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 131092 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Map pgshift:29 Unmap pgshift:16 +** Case 1: specified MAP_HUGETLB +shmid: 21 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 65558 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 131095 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Map pgshift:29 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +shmid: 24 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 65561 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 131098 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +*** C1458T03 PASSED ****************************** + +*** LTP-shmat01 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat01.c:147: PASS: shmat() succeeded to attach NULL address +shmat01.c:147: PASS: shmat() succeeded to attach aligned address +shmat01.c:147: PASS: shmat() succeeded to attach unaligned address with SHM_RND +shmat01.c:147: PASS: shmat() succeeded to attach aligned address with SHM_READONLY, and got SIGSEGV on write + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** PASSED (4) + +*** LTP-shmat02 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EACCES + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** PASSED (3) + +*** LTP-shmat03 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat03.c:75: INFO: Attempting to attach shared memory to null page +shmat03.c:91: INFO: Mapped shared memory to 0x1000001e0000 +shmat03.c:98: PASS: The kernel assigned a different VM address +shmat03.c:101: INFO: Touching shared memory to see if anything strange happens + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** PASSED (1) + +*** LTP-shmctl01 start ******************************* +shmctl01 1 TBROK : safe_macros.c:635: shmctl01.c:351: waitpid(52554,(nil),0) failed: errno=EINTR(4): Interrupted system call +shmctl01 2 TBROK : safe_macros.c:635: Remaining cases broken +*** PASSED (0) + +*** LTP-shmctl02 start ******************************* +shmctl02 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl02 2 TPASS : expected failure - errno = 14 : Bad address +shmctl02 3 TPASS : expected failure - errno = 14 : Bad address +shmctl02 4 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 5 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 6 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +shmctl02 7 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +*** PASSED (5) + +*** LTP-shmctl03 start ******************************* +shmctl03 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl03 2 TPASS : expected failure - errno = 1 : Operation not permitted +shmctl03 3 TPASS : expected failure - errno = 1 : Operation not permitted +*** PASSED (3) + +*** LTP-shmctl04 start ******************************* +shmctl04 1 TPASS : SHM_INFO call succeeded +*** PASSED (1) + +*** LTP-shmdt01 start ******************************* +shmdt01 1 TPASS : shared memory detached correctly +*** PASSED (1) + +*** LTP-shmdt02 start ******************************* +shmdt02 1 TPASS : expected failure - errno = 22 : Invalid argument +*** PASSED (1) + +*** LTP-shmget01 start ******************************* +shmget01 1 TPASS : size, pid & mode are correct +*** PASSED (1) + +*** LTP-shmget02 start ******************************* +shmget02 1 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 2 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 3 TPASS : expected failure - errno = 17 : File exists +shmget02 4 TPASS : expected failure - errno = 2 : No such file or directory +*** PASSED (4) + +*** LTP-shmget03 start ******************************* +shmget03 1 TPASS : expected failure - errno = 28 : No space left on device +*** PASSED (1) + +*** LTP-shmget04 start ******************************* +shmget04 1 TPASS : expected failure - errno = 13 : Permission denied +*** PASSED (1) + +*** LTP-shmget05 start ******************************* +shmget05 1 TPASS : expected failure - errno = 13 : Permission denied +*** PASSED (1) + diff --git a/test/issues/1458/common.sh.in b/test/issues/1458/common.sh.in new file mode 100644 index 00000000..3ef90069 --- /dev/null +++ b/test/issues/1458/common.sh.in @@ -0,0 +1,19 @@ +#!/usr/bin/sh + +# expecting this script is on /shmobj/install/bin +SCRIPT_PATH=$(readlink -m "${BASH_SOURCE[0]}") +AUTOTEST_HOME="${SCRIPT_PATH%/*/*/*/*}" +if [[ -e ${AUTOTEST_HOME}/bin/config.sh ]]; then + . ${AUTOTEST_HOME}/bin/config.sh +else + WORKDIR=$(pwd) +fi + +arch=`uname -p` +if [ -f @CMAKE_INSTALL_PREFIX@/etc/${arch}.conf ]; then + . @CMAKE_INSTALL_PREFIX@/etc/${arch}.conf +else + echo "unknown arch: $1" + exit 1 +fi + diff --git a/test/issues/1458/regression_test.sh b/test/issues/1458/regression_test.sh new file mode 100755 index 00000000..1ac003b8 --- /dev/null +++ b/test/issues/1458/regression_test.sh @@ -0,0 +1,21 @@ +#/bin/sh + +USELTP=1 +USEOSTEST=0 + +. ../../common.sh + +for tp in shmat01 shmat02 shmat03 shmctl01 shmctl02 shmctl03 shmctl04 shmdt01 shmdt02 shmget01 shmget02 shmget03 shmget04 shmget05 +do + tname=`printf "" ${tid}` + echo "*** LTP-${tp} start *******************************" + sudo $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.ltplog + ok=`grep PASS $tp.ltplog | wc -l` + ng=`grep FAIL $tp.ltplog | wc -l` + if [ $ng = 0 ]; then + echo "*** ${tname} PASSED ($ok)" + else + echo "*** ${tname} FAILED (ok=$ok ng=$ng)" + fi + echo "" +done diff --git a/test/issues/1458/x86_64.conf b/test/issues/1458/x86_64.conf new file mode 100644 index 00000000..1113f3c6 --- /dev/null +++ b/test/issues/1458/x86_64.conf @@ -0,0 +1 @@ +PS_LIST="12 21 30" diff --git a/test/issues/1458/x86_64_result.log b/test/issues/1458/x86_64_result.log new file mode 100644 index 00000000..c89e96e0 --- /dev/null +++ b/test/issues/1458/x86_64_result.log @@ -0,0 +1,253 @@ +*** C1458T01 start ******************************* +** Map pgshift:21 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:30 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:30 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] data is correct +[OK] Occurred SEGV on unmap area +[OK] data is correct +*** C1458T01 PASSED ****************************** +*** C1458T02 start ******************************* +** Map pgshift:21 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:30 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Map pgshift:30 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 2: size is aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +** Case 3: size is NOT aligned on large page +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +*** C1458T02 PASSED ****************************** +*** C1458T03 start ******************************* +** Map pgshift:21 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +shmid: 4182 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 69719 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 135256 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Map pgshift:30 Unmap pgshift:12 +** Case 1: specified MAP_HUGETLB +shmid: 4185 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 69722 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 135259 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Map pgshift:30 Unmap pgshift:21 +** Case 1: specified MAP_HUGETLB +shmid: 4188 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 2: size is aligned on large page +shmid: 69725 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +** Case 3: size is NOT aligned on large page +shmid: 135262 +[OK] munamp succceeded +[OK] Occurred SEGV on unmap area +[OK] data is correct +[OK] shmctl(IPC_RMID) succeeded +*** C1458T03 PASSED ****************************** +*** LTP-shmat01 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat01.c:147: PASS: shmat() succeeded to attach NULL address +shmat01.c:147: PASS: shmat() succeeded to attach aligned address +shmat01.c:147: PASS: shmat() succeeded to attach unaligned address with SHM_RND +shmat01.c:147: PASS: shmat() succeeded to attach aligned address with SHM_READONLY, and got SIGSEGV on write + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** PASSED (4) + +*** LTP-shmat02 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EINVAL +shmat02.c:68: PASS: shmat() failed as expected: EACCES + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** PASSED (3) + +*** LTP-shmat03 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +shmat03.c:75: INFO: Attempting to attach shared memory to null page +shmat03.c:91: INFO: Mapped shared memory to 0x2aaaaadea000 +shmat03.c:98: PASS: The kernel assigned a different VM address +shmat03.c:101: INFO: Touching shared memory to see if anything strange happens + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** PASSED (1) + +*** LTP-shmctl01 start ******************************* +shmctl01 1 TPASS : pid, size, # of attaches and mode are correct - pass #1 +shmctl01 2 TPASS : pid, size, # of attaches and mode are correct - pass #2 +shmctl01 3 TPASS : new mode and change time are correct +shmctl01 4 TPASS : get correct shared memory limits +shmctl01 5 TPASS : get correct shared memory id +shmctl01 6 TPASS : SHM_LOCK is set +shmctl01 7 TPASS : SHM_LOCK is cleared +shmctl01 8 TPASS : shared memory appears to be removed +*** PASSED (8) + +*** LTP-shmctl02 start ******************************* +shmctl02 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl02 2 TPASS : expected failure - errno = 14 : Bad address +shmctl02 3 TPASS : expected failure - errno = 14 : Bad address +shmctl02 4 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 5 TPASS : expected failure - errno = 22 : Invalid argument +shmctl02 6 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +shmctl02 7 TCONF : shmctl02.c:138: shmctl() did not fail for non-root user.This may be okay for your distribution. +*** PASSED (5) + +*** LTP-shmctl03 start ******************************* +shmctl03 1 TPASS : expected failure - errno = 13 : Permission denied +shmctl03 2 TPASS : expected failure - errno = 1 : Operation not permitted +shmctl03 3 TPASS : expected failure - errno = 1 : Operation not permitted +*** PASSED (3) + +*** LTP-shmctl04 start ******************************* +shmctl04 1 TPASS : SHM_INFO call succeeded +*** PASSED (1) + +*** LTP-shmdt01 start ******************************* +shmdt01 1 TPASS : shared memory detached correctly +*** PASSED (1) + +*** LTP-shmdt02 start ******************************* +shmdt02 1 TPASS : expected failure - errno = 22 : Invalid argument +*** PASSED (1) + +*** LTP-shmget01 start ******************************* +shmget01 1 TPASS : size, pid & mode are correct +*** PASSED (1) + +*** LTP-shmget02 start ******************************* +shmget02 1 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 2 TPASS : expected failure - errno = 22 : Invalid argument +shmget02 3 TPASS : expected failure - errno = 17 : File exists +shmget02 4 TPASS : expected failure - errno = 2 : No such file or directory +*** PASSED (4) + +*** LTP-shmget03 start ******************************* +shmget03 1 TPASS : expected failure - errno = 28 : No space left on device +*** PASSED (1) + +*** LTP-shmget04 start ******************************* +shmget04 1 TPASS : expected failure - errno = 13 : Permission denied +*** PASSED (1) + +*** LTP-shmget05 start ******************************* +shmget05 1 TPASS : expected failure - errno = 13 : Permission denied +*** PASSED (1) +