diff options
Diffstat (limited to 'arch/x86/mm/pat.c')
-rw-r--r-- | arch/x86/mm/pat.c | 45 |
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 | */ | ||
512 | static 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 | |||
537 | int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, | 508 | int 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 " |