diff options
-rw-r--r-- | arch/x86/mm/pageattr.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 3810f7a83b1d..7d21cd658ed3 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -188,6 +188,14 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address) | |||
188 | return prot; | 188 | return prot; |
189 | } | 189 | } |
190 | 190 | ||
191 | /* | ||
192 | * Lookup the page table entry for a virtual address. Return a pointer | ||
193 | * to the entry and the level of the mapping. | ||
194 | * | ||
195 | * Note: We return pud and pmd either when the entry is marked large | ||
196 | * or when the present bit is not set. Otherwise we would return a | ||
197 | * pointer to a nonexisting mapping. | ||
198 | */ | ||
191 | pte_t *lookup_address(unsigned long address, int *level) | 199 | pte_t *lookup_address(unsigned long address, int *level) |
192 | { | 200 | { |
193 | pgd_t *pgd = pgd_offset_k(address); | 201 | pgd_t *pgd = pgd_offset_k(address); |
@@ -206,7 +214,7 @@ pte_t *lookup_address(unsigned long address, int *level) | |||
206 | return NULL; | 214 | return NULL; |
207 | 215 | ||
208 | *level = PG_LEVEL_2M; | 216 | *level = PG_LEVEL_2M; |
209 | if (pmd_large(*pmd)) | 217 | if (pmd_large(*pmd) || !pmd_present(*pmd)) |
210 | return (pte_t *)pmd; | 218 | return (pte_t *)pmd; |
211 | 219 | ||
212 | *level = PG_LEVEL_4K; | 220 | *level = PG_LEVEL_4K; |