diff options
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/pageattr.c | 10 | ||||
-rw-r--r-- | arch/x86/mm/pat.c | 45 |
2 files changed, 38 insertions, 17 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index e89d24815f26..4cf30dee8161 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -555,10 +555,12 @@ repeat: | |||
555 | if (!pte_val(old_pte)) { | 555 | if (!pte_val(old_pte)) { |
556 | if (!primary) | 556 | if (!primary) |
557 | return 0; | 557 | return 0; |
558 | WARN(1, KERN_WARNING "CPA: called for zero pte. " | 558 | |
559 | "vaddr = %lx cpa->vaddr = %lx\n", address, | 559 | /* |
560 | *cpa->vaddr); | 560 | * Special error value returned, indicating that the mapping |
561 | return -EINVAL; | 561 | * did not exist at this address. |
562 | */ | ||
563 | return -EFAULT; | ||
562 | } | 564 | } |
563 | 565 | ||
564 | if (level == PG_LEVEL_4K) { | 566 | if (level == PG_LEVEL_4K) { |
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 8b08fb955274..160c42d3eb8f 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -505,6 +505,35 @@ 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 | |||
508 | int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, | 537 | int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, |
509 | unsigned long size, pgprot_t *vma_prot) | 538 | unsigned long size, pgprot_t *vma_prot) |
510 | { | 539 | { |
@@ -555,9 +584,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, | |||
555 | if (retval < 0) | 584 | if (retval < 0) |
556 | return 0; | 585 | return 0; |
557 | 586 | ||
558 | if (((pfn < max_low_pfn_mapped) || | 587 | if (kernel_map_sync_memtype(offset, size, flags)) { |
559 | (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) && | ||
560 | ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) { | ||
561 | free_memtype(offset, offset + size); | 588 | free_memtype(offset, offset + size); |
562 | printk(KERN_INFO | 589 | printk(KERN_INFO |
563 | "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", | 590 | "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", |
@@ -605,7 +632,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, | |||
605 | int strict_prot) | 632 | int strict_prot) |
606 | { | 633 | { |
607 | int is_ram = 0; | 634 | int is_ram = 0; |
608 | int id_sz, ret; | 635 | int ret; |
609 | unsigned long flags; | 636 | unsigned long flags; |
610 | unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK); | 637 | unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK); |
611 | 638 | ||
@@ -646,15 +673,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, | |||
646 | flags); | 673 | flags); |
647 | } | 674 | } |
648 | 675 | ||
649 | /* Need to keep identity mapping in sync */ | 676 | if (kernel_map_sync_memtype(paddr, size, flags)) { |
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) { | ||
658 | free_memtype(paddr, paddr + size); | 677 | free_memtype(paddr, paddr + size); |
659 | printk(KERN_ERR | 678 | printk(KERN_ERR |
660 | "%s:%d reserve_pfn_range ioremap_change_attr failed %s " | 679 | "%s:%d reserve_pfn_range ioremap_change_attr failed %s " |