aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/pat.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/pat.c')
-rw-r--r--arch/x86/mm/pat.c45
1 files changed, 13 insertions, 32 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 160c42d3eb8f..8b08fb955274 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -505,35 +505,6 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
505} 505}
506#endif /* CONFIG_STRICT_DEVMEM */ 506#endif /* CONFIG_STRICT_DEVMEM */
507 507
508/*
509 * Change the memory type for the physial address range in kernel identity
510 * mapping space if that range is a part of identity map.
511 */
512static int kernel_map_sync_memtype(u64 base, unsigned long size,
513 unsigned long flags)
514{
515 unsigned long id_sz;
516 int ret;
517
518 if (!pat_enabled || base >= __pa(high_memory))
519 return 0;
520
521 id_sz = (__pa(high_memory) < base + size) ?
522 __pa(high_memory) - base :
523 size;
524
525 ret = ioremap_change_attr((unsigned long)__va(base), id_sz, flags);
526 /*
527 * -EFAULT return means that the addr was not valid and did not have
528 * any identity mapping. That case is a success for
529 * kernel_map_sync_memtype.
530 */
531 if (ret == -EFAULT)
532 ret = 0;
533
534 return ret;
535}
536
537int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, 508int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
538 unsigned long size, pgprot_t *vma_prot) 509 unsigned long size, pgprot_t *vma_prot)
539{ 510{
@@ -584,7 +555,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
584 if (retval < 0) 555 if (retval < 0)
585 return 0; 556 return 0;
586 557
587 if (kernel_map_sync_memtype(offset, size, flags)) { 558 if (((pfn < max_low_pfn_mapped) ||
559 (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) &&
560 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
588 free_memtype(offset, offset + size); 561 free_memtype(offset, offset + size);
589 printk(KERN_INFO 562 printk(KERN_INFO
590 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", 563 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
@@ -632,7 +605,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
632 int strict_prot) 605 int strict_prot)
633{ 606{
634 int is_ram = 0; 607 int is_ram = 0;
635 int ret; 608 int id_sz, ret;
636 unsigned long flags; 609 unsigned long flags;
637 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK); 610 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
638 611
@@ -673,7 +646,15 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
673 flags); 646 flags);
674 } 647 }
675 648
676 if (kernel_map_sync_memtype(paddr, size, flags)) { 649 /* Need to keep identity mapping in sync */
650 if (paddr >= __pa(high_memory))
651 return 0;
652
653 id_sz = (__pa(high_memory) < paddr + size) ?
654 __pa(high_memory) - paddr :
655 size;
656
657 if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
677 free_memtype(paddr, paddr + size); 658 free_memtype(paddr, paddr + size);
678 printk(KERN_ERR 659 printk(KERN_ERR
679 "%s:%d reserve_pfn_range ioremap_change_attr failed %s " 660 "%s:%d reserve_pfn_range ioremap_change_attr failed %s "