Add test cases for #765

Refs: #765
Change-Id: I50d70a15d5d5ce31227cacbed4eccd49b218713b
This commit is contained in:
Tomoki Shirasawa
2018-08-01 13:21:53 +09:00
committed by Masamichi Takagi
parent ec99adde4a
commit 1387c9687b
6 changed files with 382 additions and 0 deletions

113
test/issues/765/C765.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#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);
}

128
test/issues/765/C765.patch Normal file
View File

@ -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()
{

57
test/issues/765/C765.sh Executable file
View File

@ -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

22
test/issues/765/C765.txt Normal file
View File

@ -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

13
test/issues/765/Makefile Normal file
View File

@ -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)

49
test/issues/765/README Normal file
View File

@ -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
$ <configure, build, install>
C765.patch 指定されたメモリのページサイズと共有状況を調べるシステムコールを
追加するパッチ。
□ 実行手順
$ make test
実行できない場合は、C765.shの以下の行を適切に書き換えた後に実行。
BIN= mcexec が存在するパス
SBIN= mcreboot.sh が存在するパス
OSTEST= ostest が存在するパス
□ 実行結果
C765.txt 参照。
全ての項目が OK となっていることを確認。