diff options
Diffstat (limited to 'arch/x86/mm/pat.c')
-rw-r--r-- | arch/x86/mm/pat.c | 46 |
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 | */ | ||
631 | int 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; |