Re: [RFC PATCH v1 00/17] ban the use of _PAGE_XXX flags outside platform specific code

From: Christophe Leroy
Date: Wed Sep 05 2018 - 10:33:19 EST




On 09/05/2018 02:03 PM, Aneesh Kumar K.V wrote:
On 09/05/2018 06:06 PM, Christophe Leroy wrote:
Today flags like for instance _PAGE_RW or _PAGE_USER are used through
common parts of code.
Using those directly in common parts of code have proven to lead to
mistakes or misbehaviour, because their use is not always as trivial
as one could think.

For instance, (flags & _PAGE_USER) == 0 isn't enough to tell
that a page is a kernel page, because some targets are using
_PAGE_PRIVILEDGED and not _PAGE_USER, so the test has to be
(flags & (_PAGE_USER | _PAGE_PRIVILEDGED)) == _PAGE_PRIVILEDGED
This has to (bad) consequences:

 - All targets must define every bit, even the unsupported ones,
ÂÂÂ leading to a lot of useless #define _PAGE_XXX 0
 - If someone forgets to take into account all possible _PAGE_XXX bits
ÂÂÂ for the case, we can get unexpected behaviour on some targets.

This becomes even more complex when we come to using _PAGE_RW.
Testing (flags & _PAGE_RW) is not enough to test whether a page
if writable or not, because:

 - Some targets have _PAGE_RO instead, which has to be unset to tell
ÂÂÂ a page is writable
 - Some targets have _PAGE_R and _PAGE_W, in which case
ÂÂÂ _PAGE_RW = _PAGE_R | _PAGE_W
 - Even knowing whether a page is readable is not always trivial because:
ÂÂÂ - Some targets requires to check that _PAGE_R is set to ensure page
ÂÂÂ is readable
ÂÂÂ - Some targets requires to check that _PAGE_NA is not set
ÂÂÂ - Some targets requires to check that _PAGE_RO or _PAGE_RW is set

Etc ....

In order to work around all those issues and minimise the risks of errors,
this serie aims at removing all use of _PAGE_XXX flags from powerpc code
and always use pte_xxx() and pte_mkxxx() accessors instead. Those accessors
are then defined in target specific parts of the kernel code.

We recently did on book3s 64.

static inline int pte_present(pte_t pte)
{
ÂÂÂÂ/*
ÂÂÂÂ * A pte is considerent present if _PAGE_PRESENT is set.
ÂÂÂÂ * We also need to consider the pte present which is marked
ÂÂÂÂ * invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID
ÂÂÂÂ * if we find _PAGE_PRESENT cleared.
ÂÂÂÂ */
ÂÂÂÂreturn !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
}

So I guess with that pte_present conversion we need to be careful.

Do you have a git tree which I can use to double check?

I pushed on branch 'helpers' on https://github.com/chleroy/linux.git

Christophe