On Sat, 15 Dec 2018 13:36:37 -0500
George Koehler <[email protected]> wrote:
> My test program can write pages but can't modify them, as if
> OpenBSD is ignoring writes to pages after they got swapped out and in.
By my guess, pmap_is_modified() is broken on powerpc. It seems to
fail to return true, so uvm wouldn't know that the page is modified,
and then uvm wouldn't write the modified page to swap.
I am able to build kernels. (My 1G of RAM is enough to build a kernel
without swapping. 512M of RAM might be enough, 256M might not.) I
modified my kernel to add code like
static int aaa = 0;
...
if (!aaa) {
printf("reached aaa: pmap_test_attrs\n");
aaa = 1;
}
to detect if code is reached. pmap_is_modified(pg) is a macro [1]
for pmap_test_attrs(pg, PMAP_MOD), so I added my printf()s to
pmap_test_attrs() [2].
[1] /sys/arch/powerpc/include/pmap.h
[2] /sys/arch/powerpc/powerpc/pmap.c
When the system boots, as soon as the kernel runs init, it reaches
"aaa" (at the beginning of pmap_test_attrs()) and "bbb" (just
before the LIST_FOREACH loop). I run my swap test, but the kernel
never reaches any printf() inside the loop. It never reaches "ccc",
which is just after the PMAP_HASH_LOCK. This suggests that the
kernel never enters the loop.
The hardware uses a hashtable of page table entries (pte). When a
page is modified, the hardware sets a flag PTE_CHG_32. The
LIST_FOREACH loop in pmap_test_attrs() seems to iterate each mapping
(struct pte_desc pted) of a physical page (struct vm_page *pg). For
each such mapping, the kernel would find the pte in the hashtable
and check its PTE_CHG_32 flag.
If the kernel never enters the loop, it would miss the PTE_CHG_32
flag and fail to detect that the page is modified.
--
George Koehler <[email protected]>