Messages in this thread Patch in this message | | | Date | Tue, 14 Jul 2015 20:46:06 +0800 | From | Pan Xinhui <> | Subject | [PATCH] x86/mm/pat: let level meaningful even NULL return in, lookup_address_in_pgd |
| |
If pmd or pud is not set, we may set a wrong page mapping level.
Base knowledge: 1) If we have passed pgd_none() check, then current level is at least PG_LEVEL_1G. 2) If we have passed pud_large() ||!pud_present() check, then current level is at least PG_LEVEL_2M.
This patch does not change the behavior when a non-NULL value is returned.
Let's take bask knowledge 2 as an example. We know *address* belongs to *pud*, however for some reasons *pmd* is NULL. For example, this address has no physical pages mapped. What we could benefit from this patch are below: 1) We can walk memory range easier. If addressA passed to lookup_address(), and NULL returned. We can pass addressA + level_to_size(level) to lookup_address() in next loop. ... if (!pte) { /* level_to_size has not been implemented in upstream*/ address += level_to_size(level); continue; } ... 2) keep same behavior because level is set to PG_LEVEL_4K even when pte is NULL.
So let *level* meaningful even lookup_address_in_pgd return NULL by moving the assignment before pud/pmd_offset.
Signed-off-by: Pan Xinhui <xinhuix.pan@intel.com> --- arch/x86/mm/pageattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 727158c..a887704 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -336,19 +336,19 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address, if (pgd_none(*pgd)) return NULL; + *level = PG_LEVEL_1G; pud = pud_offset(pgd, address); if (pud_none(*pud)) return NULL; - *level = PG_LEVEL_1G; if (pud_large(*pud) || !pud_present(*pud)) return (pte_t *)pud; + *level = PG_LEVEL_2M; pmd = pmd_offset(pud, address); if (pmd_none(*pmd)) return NULL; - *level = PG_LEVEL_2M; if (pmd_large(*pmd) || !pmd_present(*pmd)) return (pte_t *)pmd; -- 1.9.1
| |