From 1387c9687b9e5962140c303b8010b6851ba16c6f Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 1 Aug 2018 13:21:53 +0900 Subject: [PATCH] Add test cases for #765 Refs: #765 Change-Id: I50d70a15d5d5ce31227cacbed4eccd49b218713b --- test/issues/765/C765.c | 113 ++++++++++++++++++++++++++++++++ test/issues/765/C765.patch | 128 +++++++++++++++++++++++++++++++++++++ test/issues/765/C765.sh | 57 +++++++++++++++++ test/issues/765/C765.txt | 22 +++++++ test/issues/765/Makefile | 13 ++++ test/issues/765/README | 49 ++++++++++++++ 6 files changed, 382 insertions(+) create mode 100644 test/issues/765/C765.c create mode 100644 test/issues/765/C765.patch create mode 100755 test/issues/765/C765.sh create mode 100644 test/issues/765/C765.txt create mode 100644 test/issues/765/Makefile create mode 100644 test/issues/765/README diff --git a/test/issues/765/C765.c b/test/issues/765/C765.c new file mode 100644 index 00000000..3f5e1225 --- /dev/null +++ b/test/issues/765/C765.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMALL_PAGE_SIZE 4096L +#define PAGE_MASK (~(SMALL_PAGE_SIZE - 1)) +#define GET_PAGE_INFO 733 + +int +is_small_page(long pageinfo) +{ + return (pageinfo & PAGE_MASK) == SMALL_PAGE_SIZE; +} + +int +is_shared(long pageinfo) +{ + return pageinfo & 1; +} + +void +print_test(char *id, char *msg, void *p, int valid_small, int valid_shared) +{ + long pageinfo = syscall(GET_PAGE_INFO, p); + int ng = 0; + int small_page = is_small_page(pageinfo); + int shared = is_shared(pageinfo); + char buf[80]; + + if (pageinfo == -1 && errno == ENOSYS) { + fprintf(stderr, "get_page_info: unsupported\n"); + exit(1); + } + + sprintf(buf, "%s %s addr=%p %s %s ", id, msg, p, + small_page ? "SMALL" : "LARGE", shared ? "SHARED" : "PRIVATE"); + + if (valid_small != -1 && + small_page != valid_small) { + ng = 1; + } + if (shared != valid_shared) { + ng = 1; + } + printf("%s %s\n", buf, ng ? "NG" : "OK"); +} + +int +main(int argc, char **argv) +{ + void *p; + char x[10]; + key_t key; + int shmid; + struct shmid_ds buf; + + p = x; + memset(p, '\0', 10); + print_test("C765T01", "stack", p, -1, 0); + + p = malloc(10); + memset(p, '\0', 10); + print_test("C765T02", "heap", p, -1, 0); + + p = mmap(NULL, 8 * 1024, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memset(p, '\0', 8 * 1024); + print_test("C765T03", "private(8k)", p, 1, 0); + munmap(p, 8 * 1024); + + p = mmap(NULL, 2 * 1024 * 1024, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + memset(p, '\0', 2 * 1024 * 1024); + print_test("C765T04", "private(2M)", p, 0, 0); + munmap(p, 2 * 1024 * 1024); + + p = mmap(NULL, 8 * 1024, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + memset(p, '\0', 8 * 1024); + print_test("C765T05", "shared(8k)", p, 1, 1); + munmap(p, 8 * 1024); + + p = mmap(NULL, 2 * 1024 * 1024, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + memset(p, '\0', 2 * 1024 * 1024); + print_test("C765T06", "shared(2M)", p, 1, 1); + munmap(p, 2 * 1024 * 1024); + + key = ftok(argv[0], 1); + shmid = shmget(key, 8 * 1024, IPC_CREAT | 0660); + p = shmat(shmid, NULL, 0); + memset(p, '\0', 8 * 1024); + print_test("C765T07", "shm(8k)", p, 1, 1); + shmctl(shmid, IPC_RMID, &buf); + shmdt(p); + + key = ftok(argv[0], 2); + shmid = shmget(key, 2 * 1024 * 1024, IPC_CREAT | 0660); + p = shmat(shmid, NULL, 0); + memset(p, '\0', 2 * 1024 * 1024); + print_test("C765T08", "shm(2M)", p, 1, 1); + shmctl(shmid, IPC_RMID, &buf); + shmdt(p); + + exit(0); +} diff --git a/test/issues/765/C765.patch b/test/issues/765/C765.patch new file mode 100644 index 00000000..be46b822 --- /dev/null +++ b/test/issues/765/C765.patch @@ -0,0 +1,128 @@ +diff --git arch/x86_64/kernel/include/syscall_list.h arch/x86_64/kernel/include/syscall_list.h +index 48b1ea0..a752a7e 100644 +--- arch/x86_64/kernel/include/syscall_list.h ++++ arch/x86_64/kernel/include/syscall_list.h +@@ -161,6 +161,7 @@ SYSCALL_HANDLED(__NR_profile, profile) + SYSCALL_HANDLED(730, util_migrate_inter_kernel) + SYSCALL_HANDLED(731, util_indicate_clone) + SYSCALL_HANDLED(732, get_system) ++SYSCALL_HANDLED(733, get_mem_info) + + /* McKernel Specific */ + SYSCALL_HANDLED(801, swapout) +diff --git kernel/mem.c kernel/mem.c +index f6dc309..cdd7928 100644 +--- kernel/mem.c ++++ kernel/mem.c +@@ -1608,6 +1608,9 @@ int page_unmap(struct page *page) + return 1; + } + */ ++ if(ihk_atomic_read(&page->count) < 0) { ++ kprintf("page_unmap: BAD count\n"); ++ } + + dkprintf("page_unmap(%p %x %d): 1\n", page, page->mode, page->count); + list_del(&page->hash); +@@ -2540,3 +2543,31 @@ int ihk_mc_get_mem_user_page(void *arg0, page_table_t pt, pte_t *ptep, void *pga + + return 0; + } ++ ++void dbg_page_count(int init) ++{ ++ ++ int i; ++ struct page *page_iter; ++ unsigned long irqflags; ++ int cnt = 0; ++ int bad = 0; ++ ++ for (i = 0; i < PHYS_PAGE_HASH_SIZE; i++) { ++ irqflags = ihk_mc_spinlock_lock(&page_hash_locks[i]); ++ list_for_each_entry(page_iter, &page_hash[i], hash) { ++ cnt++; ++ if (ihk_atomic_read(&page_iter->count) < 0) ++ bad++; ++ } ++ ihk_mc_spinlock_unlock(&page_hash_locks[i], irqflags); ++ } ++ ++ if (init || bad) { ++ if (!bad) ++ kprintf("struct page # = %d\n", cnt); ++ else ++ kprintf("struct page # = %d, bad # = %d\n", cnt, bad); ++ } ++} ++ +diff --git kernel/process.c kernel/process.c +index bb15608..25daa0e 100644 +--- kernel/process.c ++++ kernel/process.c +@@ -95,6 +95,7 @@ extern void procfs_delete_thread(struct thread *); + extern void perf_start(struct mc_perf_event *event); + extern void perf_reset(struct mc_perf_event *event); + #endif /* !POSTK_DEBUG_ARCH_DEP_22 */ ++extern void dbg_page_count(int) ; + + struct list_head resource_set_list; + mcs_rwlock_lock_t resource_set_lock; +@@ -2769,6 +2770,8 @@ static void idle(void) + v->status = CPU_STATUS_IDLE; + cpu_enable_interrupt(); + ++ dbg_page_count(1); ++ + while (1) { + cpu_local_var(current)->status = PS_STOPPED; + schedule(); +@@ -3304,6 +3307,8 @@ redo: + + if ((last != NULL) && (last->status == PS_EXITED)) { + release_thread(last); ++ ++ dbg_page_count(0); + } + + /* Have we migrated to another core meanwhile? */ +diff --git kernel/syscall.c kernel/syscall.c +index d51cdeb..1073060 100644 +--- kernel/syscall.c ++++ kernel/syscall.c +@@ -9186,6 +9186,35 @@ SYSCALL_DECLARE(resume_threads) + return 0; + } + ++SYSCALL_DECLARE(get_mem_info) ++{ ++ unsigned long addr = ihk_mc_syscall_arg0(ctx); ++ struct thread *thread = cpu_local_var(current); ++ struct vm_range *range = lookup_process_memory_range(thread->vm, ++ addr, addr + 1); ++ struct process_vm *vm = thread->vm; ++ pte_t *ptep; ++ void *pgaddr; ++ size_t pgsize; ++ int p2align; ++ struct page *page = NULL; ++ ++ if (!range) ++ return -EINVAL; ++ ++ ihk_mc_spinlock_lock_noirq(&vm->page_table_lock); ++ ptep = ihk_mc_pt_lookup_pte(vm->address_space->page_table, ++ (void *)addr, range->pgshift, &pgaddr, &pgsize, &p2align); ++ if (ptep && !pte_is_null(ptep) && !pte_is_fileoff(ptep, pgsize)) { ++ unsigned long phys; ++ phys = pte_get_phys(ptep); ++ page = phys_to_page(phys); ++ } ++ ++ ihk_mc_spinlock_unlock_noirq(&vm->page_table_lock); ++ return pgsize | (page ? 1 : 0); ++} ++ + void + reset_cputime() + { diff --git a/test/issues/765/C765.sh b/test/issues/765/C765.sh new file mode 100755 index 00000000..c104858b --- /dev/null +++ b/test/issues/765/C765.sh @@ -0,0 +1,57 @@ +#!/bin/sh +BIN= +SBIN= +OSTEST= +BOOTPARAM="-c 1-7 -m 2G@0" + +if [ -f ../../../config.h ]; then + str=`grep "^#define BINDIR " ../../../config.h | head -1 | sed 's/^#define BINDIR /BINDIR=/'` + eval $str +fi + +if [ -f ../../../Makefile ]; then + str=`grep ^SBINDIR ../../../Makefile | head -1 | sed 's/ //g'` + eval $str +fi + +if [ "x$BINDIR" = x ];then + BINDIR="$BIN" +fi +if [ "x$SBINDIR" = x ];then + SBINDIR="$SBIN" +fi + +if [ -f $HOME/ostest/bin/test_mck ]; then + OSTESTDIR="$HOME/ostest" +fi + +if [ "x$OSTESTDIR" = x ]; then + OSTESTDIR="$OSTEST" +fi + +if [ ! -x "$OSTESTDIR"/bin/test_mck ]; then + echo no ostest found >&2 + exit 1 +fi + +if lsmod | grep mcctrl > /dev/null 2>&1; then + sudo $SBINDIR/mcstop+release.sh +fi +if ! lsmod | grep mcctrl > /dev/null 2>&1; then + sudo $SBINDIR/mcreboot.sh $BOOTPARAM +fi +if ! lsmod | grep mcctrl > /dev/null 2>&1; then + echo no mcctrl.ko found >&2 + exit 1 +fi + +$BINDIR/mcexec ./C765 + +$BINDIR/mcexec "$OSTESTDIR"/bin/test_mck -s mem_limits -n 0 -- -f mmap -s 7340032 -c 1 + +if $SBINDIR/ihkosctl 0 kmsg | grep -i bad > /dev/null 2>&1; then + $SBINDIR/ihkosctl 0 kmsg + echo C765T09 NG +else + echo C765T09 OK +fi diff --git a/test/issues/765/C765.txt b/test/issues/765/C765.txt new file mode 100644 index 00000000..5a5e1533 --- /dev/null +++ b/test/issues/765/C765.txt @@ -0,0 +1,22 @@ +Script started on Wed Aug 1 14:18:26 2018 +bash-4.2$ make test +gcc -o C765 C765.c -Wall -g +sh ./C765.sh +C765T01 stack addr=0x547ffffffc40 LARGE PRIVATE OK +C765T02 heap addr=0x802f30 SMALL PRIVATE OK +C765T03 private(8k) addr=0x2aaaac739000 SMALL PRIVATE OK +C765T04 private(2M) addr=0x2aaaac800000 LARGE PRIVATE OK +C765T05 shared(8k) addr=0x2aaaaca00000 SMALL SHARED OK +C765T06 shared(2M) addr=0x2aaaaca02000 SMALL SHARED OK +C765T07 shm(8k) addr=0x2aaaacc02000 SMALL SHARED OK +C765T08 shm(2M) addr=0x2aaaacc04000 SMALL SHARED OK +TEST_SUITE: mem_limits +TEST_NUMBER: 0 +ARGS: -f mmap -s 7340032 -c 1 +alloc#0: p=0x2aaaac800000 +RESULT: ok +C765T09 OK +bash-4.2$ exit +exit + +Script done on Wed Aug 1 14:18:40 2018 diff --git a/test/issues/765/Makefile b/test/issues/765/Makefile new file mode 100644 index 00000000..bff4e4be --- /dev/null +++ b/test/issues/765/Makefile @@ -0,0 +1,13 @@ +CC=gcc +TARGET=C765 + +all:: $(TARGET) + +C765: C765.c + $(CC) -o C765 C765.c -Wall -g + +test:: $(TARGET) + sh ./C765.sh + +clean:: + rm -f *.o $(TARGET) diff --git a/test/issues/765/README b/test/issues/765/README new file mode 100644 index 00000000..035f0e99 --- /dev/null +++ b/test/issues/765/README @@ -0,0 +1,49 @@ +【Issue#765 動作確認】 +□ テスト内容 +1. 共有可能なページがラージページに割り当てられないことの確認 +Issue#765の問題は、共有可能なラージページをスモールページに分割したとき、 +共有情報が不正になることであった。 +しかし、McKernel は共有対象の領域をラージページに割り当てないため、共有 +可能なページが分割されることはあり得ず、Issueが顕在化することは無い。 +このことをテストプログラムを用いて確認する。 + +C765T01 スタック領域がラージページに割り当てられ、共有不能なことを確認する。 +C765T02 ヒープ領域がスモールページに割り当てられ、共有不能なことを確認する。 +C765T03 mmapで8kBのMAP_PRIVATE領域がスモールページに割り当てられ、共有不能な + ことを確認する。 +C765T04 mmapで2MBのMAP_PRIVATE領域がラージページに割り当てられ、共有不能な + ことを確認する。 +C765T05 mmapで8kBのMAP_SHARED領域がスモールページに割り当てられ、共有可能な + ことを確認する。 +C765T06 mmapで2MBのMAP_SHARED領域がスモールページに割り当てられ、共有可能な + ことを確認する。 +C765T07 shmatで8kBの領域がスモールページに割り当てられ、共有可能なことを + 確認する。 +C765T08 shmatで2MBの領域がスモールページに割り当てられ、共有可能なことを + 確認する。 + +2. 指摘プログラムで現象が発生しないことの確認 +ostestのmem_limitsを実行し、現象が発生しないことを確認する。 + +C765T09 struct pageの参照カウンタが負にならないことを確認する。 + +□ パッチ適用 +動作確認のため、McKernelにパッチを適用する。 +$ cd /path/to/mckernel +$ patch -p0 < test/issue/765/C765.patch +$ + +C765.patch 指定されたメモリのページサイズと共有状況を調べるシステムコールを + 追加するパッチ。 + +□ 実行手順 +$ make test + +実行できない場合は、C765.shの以下の行を適切に書き換えた後に実行。 +BIN= mcexec が存在するパス +SBIN= mcreboot.sh が存在するパス +OSTEST= ostest が存在するパス + +□ 実行結果 +C765.txt 参照。 +全ての項目が OK となっていることを確認。