mremap: Fix to work correctly when old_page is large_page

Change-Id: I5a589383644a8098d910e49cd7ade6df325e0366
Refs: #1383
This commit is contained in:
Ken Sato
2020-01-30 14:11:22 +09:00
committed by Masamichi Takagi
parent 4bbdee395e
commit 41ea9d16c4
8 changed files with 344 additions and 1 deletions

View File

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

View File

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

48
test/issues/1383/C1383.sh Executable file
View File

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

View File

@ -0,0 +1,93 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

11
test/issues/1383/Makefile Normal file
View File

@ -0,0 +1,11 @@
CFLAGS=-g
LDFLAGS=
TARGET= C1383T01
all: $(TARGET)
test: all
sh ./C1383.sh
clean:
rm -f $(TARGET) *.o *.txt

29
test/issues/1383/README Normal file
View File

@ -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していることを確認。

View File

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

View File

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