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

Reply via email to