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.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index aebbf67a79d0..399383c6f614 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -625,6 +625,33 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
625} 625}
626 626
627/* 627/*
628 * Change the memory type for the physial address range in kernel identity
629 * mapping space if that range is a part of identity map.
630 */
631int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
632{
633 unsigned long id_sz;
634
635 if (!pat_enabled || base >= __pa(high_memory))
636 return 0;
637
638 id_sz = (__pa(high_memory) < base + size) ?
639 __pa(high_memory) - base :
640 size;
641
642 if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
643 printk(KERN_INFO
644 "%s:%d ioremap_change_attr failed %s "
645 "for %Lx-%Lx\n",
646 current->comm, current->pid,
647 cattr_name(flags),
648 base, (unsigned long long)(base + size));
649 return -EINVAL;
650 }
651 return 0;
652}
653
654/*
628 * Internal interface to reserve a range of physical memory with prot. 655 * Internal interface to reserve a range of physical memory with prot.
629 * Reserved non RAM regions only and after successful reserve_memtype, 656 * Reserved non RAM regions only and after successful reserve_memtype,
630 * this func also keeps identity mapping (if any) in sync with this new prot. 657 * this func also keeps identity mapping (if any) in sync with this new prot.
@@ -633,7 +660,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
633 int strict_prot) 660 int strict_prot)
634{ 661{
635 int is_ram = 0; 662 int is_ram = 0;
636 int id_sz, ret; 663 int ret;
637 unsigned long flags; 664 unsigned long flags;
638 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK); 665 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
639 666
@@ -670,23 +697,8 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
670 flags); 697 flags);
671 } 698 }
672 699
673 /* Need to keep identity mapping in sync */ 700 if (kernel_map_sync_memtype(paddr, size, flags) < 0) {
674 if (paddr >= __pa(high_memory))
675 return 0;
676
677 id_sz = (__pa(high_memory) < paddr + size) ?
678 __pa(high_memory) - paddr :
679 size;
680
681 if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
682 free_memtype(paddr, paddr + size); 701 free_memtype(paddr, paddr + size);
683 printk(KERN_ERR
684 "%s:%d reserve_pfn_range ioremap_change_attr failed %s "
685 "for %Lx-%Lx\n",
686 current->comm, current->pid,
687 cattr_name(flags),
688 (unsigned long long)paddr,
689 (unsigned long long)(paddr + size));
690 return -EINVAL; 702 return -EINVAL;
691 } 703 }
692 return 0; 704 return 0;