aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/pat.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-21 10:37:27 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-21 10:37:27 -0500
commit77835492ed489c0b870f82f4c50687bd267acc0a (patch)
treed80903ce1b8dd30aa44ccfc756616ad4d6c74d63 /arch/x86/mm/pat.c
parentaf37501c792107c2bde1524bdae38d9a247b841a (diff)
parent1de9e8e70f5acc441550ca75433563d91b269bbe (diff)
Merge commit 'v2.6.29-rc2' into perfcounters/core
Conflicts: include/linux/syscalls.h
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 3be399013de6..c9488513fd70 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -522,35 +522,6 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
522} 522}
523#endif /* CONFIG_STRICT_DEVMEM */ 523#endif /* CONFIG_STRICT_DEVMEM */
524 524
525/*
526 * Change the memory type for the physial address range in kernel identity
527 * mapping space if that range is a part of identity map.
528 */
529static int kernel_map_sync_memtype(u64 base, unsigned long size,
530 unsigned long flags)
531{
532 unsigned long id_sz;
533 int ret;
534
535 if (!pat_enabled || base >= __pa(high_memory))
536 return 0;
537
538 id_sz = (__pa(high_memory) < base + size) ?
539 __pa(high_memory) - base :
540 size;
541
542 ret = ioremap_change_attr((unsigned long)__va(base), id_sz, flags);
543 /*
544 * -EFAULT return means that the addr was not valid and did not have
545 * any identity mapping. That case is a success for
546 * kernel_map_sync_memtype.
547 */
548 if (ret == -EFAULT)
549 ret = 0;
550
551 return ret;
552}
553
554int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, 525int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
555 unsigned long size, pgprot_t *vma_prot) 526 unsigned long size, pgprot_t *vma_prot)
556{ 527{
@@ -601,7 +572,9 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
601 if (retval < 0) 572 if (retval < 0)
602 return 0; 573 return 0;
603 574
604 if (kernel_map_sync_memtype(offset, size, flags)) { 575 if (((pfn < max_low_pfn_mapped) ||
576 (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) &&
577 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
605 free_memtype(offset, offset + size); 578 free_memtype(offset, offset + size);
606 printk(KERN_INFO 579 printk(KERN_INFO
607 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", 580 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
@@ -649,7 +622,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
649 int strict_prot) 622 int strict_prot)
650{ 623{
651 int is_ram = 0; 624 int is_ram = 0;
652 int ret; 625 int id_sz, ret;
653 unsigned long flags; 626 unsigned long flags;
654 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK); 627 unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
655 628
@@ -690,7 +663,15 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
690 flags); 663 flags);
691 } 664 }
692 665
693 if (kernel_map_sync_memtype(paddr, size, flags)) { 666 /* Need to keep identity mapping in sync */
667 if (paddr >= __pa(high_memory))
668 return 0;
669
670 id_sz = (__pa(high_memory) < paddr + size) ?
671 __pa(high_memory) - paddr :
672 size;
673
674 if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
694 free_memtype(paddr, paddr + size); 675 free_memtype(paddr, paddr + size);
695 printk(KERN_ERR 676 printk(KERN_ERR
696 "%s:%d reserve_pfn_range ioremap_change_attr failed %s " 677 "%s:%d reserve_pfn_range ioremap_change_attr failed %s "