aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pageattr.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 2c44c0792301..1441368a7931 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -414,18 +414,28 @@ pmd_t *lookup_pmd_address(unsigned long address)
414phys_addr_t slow_virt_to_phys(void *__virt_addr) 414phys_addr_t slow_virt_to_phys(void *__virt_addr)
415{ 415{
416 unsigned long virt_addr = (unsigned long)__virt_addr; 416 unsigned long virt_addr = (unsigned long)__virt_addr;
417 phys_addr_t phys_addr; 417 unsigned long phys_addr, offset;
418 unsigned long offset;
419 enum pg_level level; 418 enum pg_level level;
420 unsigned long pmask;
421 pte_t *pte; 419 pte_t *pte;
422 420
423 pte = lookup_address(virt_addr, &level); 421 pte = lookup_address(virt_addr, &level);
424 BUG_ON(!pte); 422 BUG_ON(!pte);
425 pmask = page_level_mask(level); 423
426 offset = virt_addr & ~pmask; 424 switch (level) {
427 phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT; 425 case PG_LEVEL_1G:
428 return (phys_addr | offset); 426 phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
427 offset = virt_addr & ~PUD_PAGE_MASK;
428 break;
429 case PG_LEVEL_2M:
430 phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
431 offset = virt_addr & ~PMD_PAGE_MASK;
432 break;
433 default:
434 phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
435 offset = virt_addr & ~PAGE_MASK;
436 }
437
438 return (phys_addr_t)(phys_addr | offset);
429} 439}
430EXPORT_SYMBOL_GPL(slow_virt_to_phys); 440EXPORT_SYMBOL_GPL(slow_virt_to_phys);
431 441