From 41ea9d16c4985bd88cc4b7e540409a49e05fbda8 Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Thu, 30 Jan 2020 14:11:22 +0900 Subject: [PATCH] mremap: Fix to work correctly when old_page is large_page Change-Id: I5a589383644a8098d910e49cd7ade6df325e0366 Refs: #1383 --- kernel/process.c | 9 +++ kernel/syscall.c | 25 +++++++- test/issues/1383/C1383.sh | 48 +++++++++++++++ test/issues/1383/C1383T01.c | 93 +++++++++++++++++++++++++++++ test/issues/1383/Makefile | 11 ++++ test/issues/1383/README | 29 +++++++++ test/issues/1383/aarch64_result.log | 65 ++++++++++++++++++++ test/issues/1383/x86_64_result.log | 65 ++++++++++++++++++++ 8 files changed, 344 insertions(+), 1 deletion(-) create mode 100755 test/issues/1383/C1383.sh create mode 100644 test/issues/1383/C1383T01.c create mode 100644 test/issues/1383/Makefile create mode 100644 test/issues/1383/README create mode 100644 test/issues/1383/aarch64_result.log create mode 100644 test/issues/1383/x86_64_result.log diff --git a/kernel/process.c b/kernel/process.c index 9282909c..1f4c3d81 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -908,10 +908,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) { + /* split addr is not aligned */ + range->pgshift = 0; + } + } + error = ihk_mc_pt_split(vm->address_space->page_table, vm, (void *)addr); if (error) { ekprintf("split_process_memory_range:" diff --git a/kernel/syscall.c b/kernel/syscall.c index fa5715b6..ccd947e5 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -8498,7 +8498,7 @@ SYSCALL_DECLARE(mremap) error = add_process_memory_range(thread->vm, newstart, newend, -1, range->flag, range->memobj, range->objoff + (oldstart - range->start), - range->pgshift, NULL, NULL); + 0, NULL, NULL); if (error) { ekprintf("sys_mremap(%#lx,%#lx,%#lx,%#x,%#lx):" "add failed. %d\n", @@ -8518,6 +8518,29 @@ SYSCALL_DECLARE(mremap) if (oldsize > 0) { size = (oldsize < newsize)? oldsize: newsize; ihk_mc_spinlock_lock_noirq(&vm->page_table_lock); + if (range->start != oldstart) { + error = split_process_memory_range(vm, + range, oldstart, &range); + if (error) { + ekprintf("sys_mremap(%#lx,%#lx,%#lx,%#x,%#lx):" + "split range failed. %d\n", + oldaddr, oldsize0, newsize0, + flags, newaddr, error); + goto out; + } + } + if (range->end != oldstart + size) { + error = split_process_memory_range(vm, + range, oldstart + size, NULL); + if (error) { + ekprintf("sys_mremap(%#lx,%#lx,%#lx,%#x,%#lx):" + "split range failed. %d\n", + oldaddr, oldsize0, newsize0, + flags, newaddr, error); + goto out; + } + } + error = move_pte_range(vm->address_space->page_table, vm, (void *)oldstart, (void *)newstart, size, range); diff --git a/test/issues/1383/C1383.sh b/test/issues/1383/C1383.sh new file mode 100755 index 00000000..2ef64e64 --- /dev/null +++ b/test/issues/1383/C1383.sh @@ -0,0 +1,48 @@ +#/bin/sh + +USELTP=1 +USEOSTEST=0 + +. ../../common.sh + +issue="1383" +tid=01 + +arch=`uname -p` +if [ "$arch" == "x86_64" ]; then + pgshift=21 +elif [ "$arch" == "aarch64" ]; then + pgshift=29 +fi + +for tno in 01 +do + tname=`printf "C${issue}T%02d" ${tid}` + echo "*** ${tname} start *******************************" + sudo ${MCEXEC} ./C1383T${tno} ${pgshift} + + if [ $? -eq 0 ]; then + echo "*** ${tname} PASSED ******************************" + else + echo "*** ${tname} FAILED ******************************" + fi + let tid++ + echo "" +done + +for tp in thp02 mremap01 mremap02 mremap03 mremap04 mremap05 move_pages10 +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/1383/C1383T01.c b/test/issues/1383/C1383T01.c new file mode 100644 index 00000000..e76596d1 --- /dev/null +++ b/test/issues/1383/C1383T01.c @@ -0,0 +1,93 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#define PAGES 3 +#define MAP_HUGE_SHIFT 26 + +static unsigned long ps, hps; + +void *hugetlb_mmap(unsigned long size, int pgshift) +{ + return mmap(NULL, size, PROT_WRITE | PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE | + MAP_HUGETLB | (pgshift << MAP_HUGE_SHIFT), + -1, 0); +} + +int main(int argc, char **argv) +{ + void *p1, *p2, *p3, *p4, *old_addr, *new_addr; + int i, pgshift, err, ret = 0; + unsigned long base_start, base_size, new_start, new_size; + size_t size, remap_size; + + if (argc < 2) { + printf("error: too few arguments\n"); + ret = -1; + goto out; + } + pgshift = atoi(argv[1]); + hps = (1 << pgshift); + ps = getpagesize(); + size = hps * PAGES; + + for (i = 0; i < 4; i++) { + p1 = hugetlb_mmap(size, pgshift); + if (p1 == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + goto out; + } + printf("** mmap p1: %p - %p\n", p1, p1 + size); + + p2 = hugetlb_mmap(size, pgshift); + if (p2 == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + goto out; + } + printf("** mmap p2: %p - %p\n", p2, p2 + size); + + p3 = hugetlb_mmap(size, pgshift); + if (p3 == MAP_FAILED) { + perror("mmap fail: "); + ret = -1; + goto out; + } + printf("** mmap p3: %p - %p\n", p3, p3 + size); + + /* make page populate */ + memset(p1, 0xff, size); + memset(p2, 0xff, size); + memset(p3, 0x77, size); + + remap_size = size - ps; + old_addr = p1 + ps * (i >> 1); + new_addr = p3 + ps * (i & 1); + + p4 = mremap(old_addr, remap_size, remap_size, + MREMAP_FIXED | MREMAP_MAYMOVE, new_addr); + if (p4 == MAP_FAILED) { + perror("mremap fail: "); + ret = -1; + goto out; + } + if (memcmp(p4, p2, remap_size)) { + printf("memcmp detect DIFF!!\n"); + ret = -1; + goto out; + } + printf("*** mremap p4: %p - %p\n", p4, p4 + remap_size); + + } + + printf("[OK] mremap on HUGETLB\n"); +out: + return ret; +} diff --git a/test/issues/1383/Makefile b/test/issues/1383/Makefile new file mode 100644 index 00000000..4a7a85c4 --- /dev/null +++ b/test/issues/1383/Makefile @@ -0,0 +1,11 @@ +CFLAGS=-g +LDFLAGS= + +TARGET= C1383T01 + +all: $(TARGET) + +test: all + sh ./C1383.sh +clean: + rm -f $(TARGET) *.o *.txt diff --git a/test/issues/1383/README b/test/issues/1383/README new file mode 100644 index 00000000..974081de --- /dev/null +++ b/test/issues/1383/README @@ -0,0 +1,29 @@ +【Issue#1383 動作確認】 +□ テスト内容 +1. MAP_HUGETLB指定でラージページを確保し、スモールページへのsplitが発生する + mremapが正常に行えることを確認する。 + 具体的には、Issueで報告されたLTPのthp02相当の処理のmmap部分をthpからMAP_HUGETLB指定に + したプログラムを実行し、正常に終了することを確認する。 + +2. Issueで報告された以下のLTPを実行し、症状が発生しないことを確認する + - thp02 + +3. mremapを利用する以下のLTPを用いて既存機能に影響が無いことを確認する + - mremap01 + - mremap02 + - mremap03 + - mremap04 + - mremap05 + - move_pages10 + +□ 実行手順 +$ 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/1383/aarch64_result.log b/test/issues/1383/aarch64_result.log new file mode 100644 index 00000000..c43dd640 --- /dev/null +++ b/test/issues/1383/aarch64_result.log @@ -0,0 +1,65 @@ +*** C1383T01 start ******************************* +** mmap p1: 0x100020000000 - 0x100080000000 +** mmap p2: 0x1000a0000000 - 0x100100000000 +** mmap p3: 0x100100000000 - 0x100160000000 +*** mremap p4: 0x100100000000 - 0x10015fff0000 +** mmap p1: 0x100160000000 - 0x1001c0000000 +** mmap p2: 0x1001c0000000 - 0x100220000000 +** mmap p3: 0x100220000000 - 0x100280000000 +*** mremap p4: 0x100220010000 - 0x100280000000 +** mmap p1: 0x100280000000 - 0x1002e0000000 +** mmap p2: 0x1002e0000000 - 0x100340000000 +** mmap p3: 0x100340000000 - 0x1003a0000000 +*** mremap p4: 0x100340000000 - 0x10039fff0000 +** mmap p1: 0x1003a0000000 - 0x100400000000 +** mmap p2: 0x100400000000 - 0x100460000000 +** mmap p3: 0x100460000000 - 0x1004c0000000 +*** mremap p4: 0x100460010000 - 0x1004c0000000 +[OK] mremap on HUGETLB +*** C1383T01 PASSED ****************************** + +*** C1383T02 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +thp02.c:75: INFO: mremap 0x100040000000 to 0x1001c0000000 +thp02.c:75: INFO: mremap 0x100280000000 to 0x100400010000 +thp02.c:75: INFO: mremap 0x1004c0010000 to 0x100640000000 +thp02.c:75: INFO: mremap 0x100700010000 to 0x100880010000 +thp02.c:85: PASS: Still alive. + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1383T02 PASSED (1) + +*** C1383T03 start ******************************* +mremap01 1 TPASS : Functionality of mremap() is correct +*** C1383T03 PASSED (1) + +*** C1383T04 start ******************************* +mremap02 1 TPASS : mremap() Failed, 'invalid argument specified' - errno 22 +*** C1383T04 PASSED (1) + +*** C1383T05 start ******************************* +mremap03 1 TPASS : mremap() Fails, 'old region not mapped', errno 14 +*** C1383T05 PASSED (1) + +*** C1383T06 start ******************************* +mremap04 1 TPASS : mremap() failed, 'MREMAP_MAYMOVE flag unset', errno 12 +*** C1383T06 PASSED (1) + +*** C1383T07 start ******************************* +mremap05 1 TPASS : MREMAP_FIXED requires MREMAP_MAYMOVE +mremap05 2 TPASS : new_addr has to be page aligned +mremap05 3 TPASS : old/new area must not overlap +mremap05 4 TPASS : mremap #1 +mremap05 5 TPASS : mremap #1 value OK +mremap05 6 TPASS : mremap #2 +mremap05 7 TPASS : mremap #2 value OK +*** C1383T07 PASSED (7) + +*** C1383T08 start ******************************* +move_pages10 1 TPASS : move_pages failed with EINVAL as expected +*** C1383T08 PASSED (1) + diff --git a/test/issues/1383/x86_64_result.log b/test/issues/1383/x86_64_result.log new file mode 100644 index 00000000..d3906940 --- /dev/null +++ b/test/issues/1383/x86_64_result.log @@ -0,0 +1,65 @@ +*** C1383T01 start ******************************* +** mmap p1: 0x2aaaaae00000 - 0x2aaaab400000 +** mmap p2: 0x2aaaab600000 - 0x2aaaabc00000 +** mmap p3: 0x2aaaabc00000 - 0x2aaaac200000 +*** mremap p4: 0x2aaaabc00000 - 0x2aaaac1ff000 +** mmap p1: 0x2aaaac200000 - 0x2aaaac800000 +** mmap p2: 0x2aaaac800000 - 0x2aaaace00000 +** mmap p3: 0x2aaaace00000 - 0x2aaaad400000 +*** mremap p4: 0x2aaaace01000 - 0x2aaaad400000 +** mmap p1: 0x2aaaad400000 - 0x2aaaada00000 +** mmap p2: 0x2aaaada00000 - 0x2aaaae000000 +** mmap p3: 0x2aaaae000000 - 0x2aaaae600000 +*** mremap p4: 0x2aaaae000000 - 0x2aaaae5ff000 +** mmap p1: 0x2aaaae600000 - 0x2aaaaec00000 +** mmap p2: 0x2aaaaec00000 - 0x2aaaaf200000 +** mmap p3: 0x2aaaaf200000 - 0x2aaaaf800000 +*** mremap p4: 0x2aaaaf201000 - 0x2aaaaf800000 +[OK] mremap on HUGETLB +*** C1383T01 PASSED ****************************** + +*** C1383T02 start ******************************* +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +thp02.c:75: INFO: mremap 0x2aaaab800000 to 0x2aaaad000000 +thp02.c:75: INFO: mremap 0x2aaaadc00000 to 0x2aaaaf401000 +thp02.c:75: INFO: mremap 0x2aaab0001000 to 0x2aaab1800000 +thp02.c:75: INFO: mremap 0x2aaab2401000 to 0x2aaab3c01000 +thp02.c:85: PASS: Still alive. + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1383T02 PASSED (1) + +*** C1383T03 start ******************************* +mremap01 1 TPASS : Functionality of mremap() is correct +*** C1383T03 PASSED (1) + +*** C1383T04 start ******************************* +mremap02 1 TPASS : mremap() Failed, 'invalid argument specified' - errno 22 +*** C1383T04 PASSED (1) + +*** C1383T05 start ******************************* +mremap03 1 TPASS : mremap() Fails, 'old region not mapped', errno 14 +*** C1383T05 PASSED (1) + +*** C1383T06 start ******************************* +mremap04 1 TPASS : mremap() failed, 'MREMAP_MAYMOVE flag unset', errno 12 +*** C1383T06 PASSED (1) + +*** C1383T07 start ******************************* +mremap05 1 TPASS : MREMAP_FIXED requires MREMAP_MAYMOVE +mremap05 2 TPASS : new_addr has to be page aligned +mremap05 3 TPASS : old/new area must not overlap +mremap05 4 TPASS : mremap #1 +mremap05 5 TPASS : mremap #1 value OK +mremap05 6 TPASS : mremap #2 +mremap05 7 TPASS : mremap #2 value OK +*** C1383T07 PASSED (7) + +*** C1383T08 start ******************************* +move_pages10 1 TPASS : move_pages failed with EINVAL as expected +*** C1383T08 PASSED (1) +