diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-12 18:26:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-12 18:26:48 -0500 |
commit | 26ceb127f7bcf473db926c6a026b18ddd6f274e8 (patch) | |
tree | a8944a9c0730c409b0cfb17c541085face068556 /arch/arm/mm/init.c | |
parent | 8d14066755592a2906b4f2378aeb5471b602d3cb (diff) | |
parent | e9f2d6d66037cdf97487491e04053f411abc5d16 (diff) |
Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King:
"The major updates included in this update are:
- Clang compatible stack pointer accesses by Behan Webster.
- SA11x0 updates from Dmitry Eremin-Solenikov.
- kgdb handling of breakpoints with read-only text/modules
- Support for Privileged-no-execute feature on ARMv7 to prevent
userspace code execution by the kernel.
- AMBA primecell bus handling of irq-safe runtime PM
- Unwinding support for memset/memzero/memmove/memcpy functions
- VFP fixes for Krait CPUs and improvements in detecting the VFP
architecture
- A number of code cleanups (using pr_*, removing or reducing the
severity of a couple of kernel messages, splitting ftrace asm code
out to a separate file, etc.)
- Add machine name to stack dump output"
* 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: (62 commits)
ARM: 8247/2: pcmcia: sa1100: make use of device clock
ARM: 8246/2: pcmcia: sa1111: provide device clock
ARM: 8245/1: pcmcia: soc-common: enable/disable socket clocks
ARM: 8244/1: fbdev: sa1100fb: make use of device clock
ARM: 8243/1: sa1100: add a clock alias for sa1111 pcmcia device
ARM: 8242/1: sa1100: add cpu clock
ARM: 8221/1: PJ4: allow building in Thumb-2 mode
ARM: 8234/1: sa1100: reorder IRQ handling code
ARM: 8233/1: sa1100: switch to hwirq usage
ARM: 8232/1: sa1100: merge GPIO multiplexer IRQ to "normal" irq domain
ARM: 8231/1: sa1100: introduce irqdomains support
ARM: 8230/1: sa1100: shift IRQs by one
ARM: 8229/1: sa1100: replace irq numbers with names in irq driver
ARM: 8228/1: sa1100: drop entry-macro.S
ARM: 8227/1: sa1100: switch to MULTI_IRQ_HANDLER
ARM: 8241/1: Update processor_modes for hyp and monitor mode
ARM: 8240/1: MCPM: document mcpm_sync_init()
ARM: 8239/1: Introduce {set,clear}_pte_bit
ARM: 8238/1: mm: Refine set_memory_* functions
ARM: 8237/1: fix flush_pfn_alias
...
Diffstat (limited to 'arch/arm/mm/init.c')
-rw-r--r-- | arch/arm/mm/init.c | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 9481f85c56e6..98ad9c79ea0e 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
31 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
32 | #include <asm/system_info.h> | ||
32 | #include <asm/tlb.h> | 33 | #include <asm/tlb.h> |
33 | #include <asm/fixmap.h> | 34 | #include <asm/fixmap.h> |
34 | 35 | ||
@@ -67,7 +68,7 @@ early_param("initrd", early_initrd); | |||
67 | 68 | ||
68 | static int __init parse_tag_initrd(const struct tag *tag) | 69 | static int __init parse_tag_initrd(const struct tag *tag) |
69 | { | 70 | { |
70 | printk(KERN_WARNING "ATAG_INITRD is deprecated; " | 71 | pr_warn("ATAG_INITRD is deprecated; " |
71 | "please update your bootloader.\n"); | 72 | "please update your bootloader.\n"); |
72 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); | 73 | phys_initrd_start = __virt_to_phys(tag->u.initrd.start); |
73 | phys_initrd_size = tag->u.initrd.size; | 74 | phys_initrd_size = tag->u.initrd.size; |
@@ -544,7 +545,7 @@ void __init mem_init(void) | |||
544 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 | 545 | #define MLM(b, t) b, t, ((t) - (b)) >> 20 |
545 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) | 546 | #define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K) |
546 | 547 | ||
547 | printk(KERN_NOTICE "Virtual kernel memory layout:\n" | 548 | pr_notice("Virtual kernel memory layout:\n" |
548 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" | 549 | " vector : 0x%08lx - 0x%08lx (%4ld kB)\n" |
549 | #ifdef CONFIG_HAVE_TCM | 550 | #ifdef CONFIG_HAVE_TCM |
550 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" | 551 | " DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n" |
@@ -570,7 +571,7 @@ void __init mem_init(void) | |||
570 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), | 571 | MLK(DTCM_OFFSET, (unsigned long) dtcm_end), |
571 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), | 572 | MLK(ITCM_OFFSET, (unsigned long) itcm_end), |
572 | #endif | 573 | #endif |
573 | MLK(FIXADDR_START, FIXADDR_TOP), | 574 | MLK(FIXADDR_START, FIXADDR_END), |
574 | MLM(VMALLOC_START, VMALLOC_END), | 575 | MLM(VMALLOC_START, VMALLOC_END), |
575 | MLM(PAGE_OFFSET, (unsigned long)high_memory), | 576 | MLM(PAGE_OFFSET, (unsigned long)high_memory), |
576 | #ifdef CONFIG_HIGHMEM | 577 | #ifdef CONFIG_HIGHMEM |
@@ -615,7 +616,145 @@ void __init mem_init(void) | |||
615 | } | 616 | } |
616 | } | 617 | } |
617 | 618 | ||
618 | void free_initmem(void) | 619 | #ifdef CONFIG_ARM_KERNMEM_PERMS |
620 | struct section_perm { | ||
621 | unsigned long start; | ||
622 | unsigned long end; | ||
623 | pmdval_t mask; | ||
624 | pmdval_t prot; | ||
625 | pmdval_t clear; | ||
626 | }; | ||
627 | |||
628 | static struct section_perm nx_perms[] = { | ||
629 | /* Make pages tables, etc before _stext RW (set NX). */ | ||
630 | { | ||
631 | .start = PAGE_OFFSET, | ||
632 | .end = (unsigned long)_stext, | ||
633 | .mask = ~PMD_SECT_XN, | ||
634 | .prot = PMD_SECT_XN, | ||
635 | }, | ||
636 | /* Make init RW (set NX). */ | ||
637 | { | ||
638 | .start = (unsigned long)__init_begin, | ||
639 | .end = (unsigned long)_sdata, | ||
640 | .mask = ~PMD_SECT_XN, | ||
641 | .prot = PMD_SECT_XN, | ||
642 | }, | ||
643 | #ifdef CONFIG_DEBUG_RODATA | ||
644 | /* Make rodata NX (set RO in ro_perms below). */ | ||
645 | { | ||
646 | .start = (unsigned long)__start_rodata, | ||
647 | .end = (unsigned long)__init_begin, | ||
648 | .mask = ~PMD_SECT_XN, | ||
649 | .prot = PMD_SECT_XN, | ||
650 | }, | ||
651 | #endif | ||
652 | }; | ||
653 | |||
654 | #ifdef CONFIG_DEBUG_RODATA | ||
655 | static struct section_perm ro_perms[] = { | ||
656 | /* Make kernel code and rodata RX (set RO). */ | ||
657 | { | ||
658 | .start = (unsigned long)_stext, | ||
659 | .end = (unsigned long)__init_begin, | ||
660 | #ifdef CONFIG_ARM_LPAE | ||
661 | .mask = ~PMD_SECT_RDONLY, | ||
662 | .prot = PMD_SECT_RDONLY, | ||
663 | #else | ||
664 | .mask = ~(PMD_SECT_APX | PMD_SECT_AP_WRITE), | ||
665 | .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, | ||
666 | .clear = PMD_SECT_AP_WRITE, | ||
667 | #endif | ||
668 | }, | ||
669 | }; | ||
670 | #endif | ||
671 | |||
672 | /* | ||
673 | * Updates section permissions only for the current mm (sections are | ||
674 | * copied into each mm). During startup, this is the init_mm. Is only | ||
675 | * safe to be called with preemption disabled, as under stop_machine(). | ||
676 | */ | ||
677 | static inline void section_update(unsigned long addr, pmdval_t mask, | ||
678 | pmdval_t prot) | ||
679 | { | ||
680 | struct mm_struct *mm; | ||
681 | pmd_t *pmd; | ||
682 | |||
683 | mm = current->active_mm; | ||
684 | pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); | ||
685 | |||
686 | #ifdef CONFIG_ARM_LPAE | ||
687 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
688 | #else | ||
689 | if (addr & SECTION_SIZE) | ||
690 | pmd[1] = __pmd((pmd_val(pmd[1]) & mask) | prot); | ||
691 | else | ||
692 | pmd[0] = __pmd((pmd_val(pmd[0]) & mask) | prot); | ||
693 | #endif | ||
694 | flush_pmd_entry(pmd); | ||
695 | local_flush_tlb_kernel_range(addr, addr + SECTION_SIZE); | ||
696 | } | ||
697 | |||
698 | /* Make sure extended page tables are in use. */ | ||
699 | static inline bool arch_has_strict_perms(void) | ||
700 | { | ||
701 | if (cpu_architecture() < CPU_ARCH_ARMv6) | ||
702 | return false; | ||
703 | |||
704 | return !!(get_cr() & CR_XP); | ||
705 | } | ||
706 | |||
707 | #define set_section_perms(perms, field) { \ | ||
708 | size_t i; \ | ||
709 | unsigned long addr; \ | ||
710 | \ | ||
711 | if (!arch_has_strict_perms()) \ | ||
712 | return; \ | ||
713 | \ | ||
714 | for (i = 0; i < ARRAY_SIZE(perms); i++) { \ | ||
715 | if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) || \ | ||
716 | !IS_ALIGNED(perms[i].end, SECTION_SIZE)) { \ | ||
717 | pr_err("BUG: section %lx-%lx not aligned to %lx\n", \ | ||
718 | perms[i].start, perms[i].end, \ | ||
719 | SECTION_SIZE); \ | ||
720 | continue; \ | ||
721 | } \ | ||
722 | \ | ||
723 | for (addr = perms[i].start; \ | ||
724 | addr < perms[i].end; \ | ||
725 | addr += SECTION_SIZE) \ | ||
726 | section_update(addr, perms[i].mask, \ | ||
727 | perms[i].field); \ | ||
728 | } \ | ||
729 | } | ||
730 | |||
731 | static inline void fix_kernmem_perms(void) | ||
732 | { | ||
733 | set_section_perms(nx_perms, prot); | ||
734 | } | ||
735 | |||
736 | #ifdef CONFIG_DEBUG_RODATA | ||
737 | void mark_rodata_ro(void) | ||
738 | { | ||
739 | set_section_perms(ro_perms, prot); | ||
740 | } | ||
741 | |||
742 | void set_kernel_text_rw(void) | ||
743 | { | ||
744 | set_section_perms(ro_perms, clear); | ||
745 | } | ||
746 | |||
747 | void set_kernel_text_ro(void) | ||
748 | { | ||
749 | set_section_perms(ro_perms, prot); | ||
750 | } | ||
751 | #endif /* CONFIG_DEBUG_RODATA */ | ||
752 | |||
753 | #else | ||
754 | static inline void fix_kernmem_perms(void) { } | ||
755 | #endif /* CONFIG_ARM_KERNMEM_PERMS */ | ||
756 | |||
757 | void free_tcmmem(void) | ||
619 | { | 758 | { |
620 | #ifdef CONFIG_HAVE_TCM | 759 | #ifdef CONFIG_HAVE_TCM |
621 | extern char __tcm_start, __tcm_end; | 760 | extern char __tcm_start, __tcm_end; |
@@ -623,6 +762,12 @@ void free_initmem(void) | |||
623 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); | 762 | poison_init_mem(&__tcm_start, &__tcm_end - &__tcm_start); |
624 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); | 763 | free_reserved_area(&__tcm_start, &__tcm_end, -1, "TCM link"); |
625 | #endif | 764 | #endif |
765 | } | ||
766 | |||
767 | void free_initmem(void) | ||
768 | { | ||
769 | fix_kernmem_perms(); | ||
770 | free_tcmmem(); | ||
626 | 771 | ||
627 | poison_init_mem(__init_begin, __init_end - __init_begin); | 772 | poison_init_mem(__init_begin, __init_end - __init_begin); |
628 | if (!machine_is_integrator() && !machine_is_cintegrator()) | 773 | if (!machine_is_integrator() && !machine_is_cintegrator()) |