aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/init.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-12 18:26:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-12 18:26:48 -0500
commit26ceb127f7bcf473db926c6a026b18ddd6f274e8 (patch)
treea8944a9c0730c409b0cfb17c541085face068556 /arch/arm/mm/init.c
parent8d14066755592a2906b4f2378aeb5471b602d3cb (diff)
parente9f2d6d66037cdf97487491e04053f411abc5d16 (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.c153
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
68static int __init parse_tag_initrd(const struct tag *tag) 69static 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
618void free_initmem(void) 619#ifdef CONFIG_ARM_KERNMEM_PERMS
620struct section_perm {
621 unsigned long start;
622 unsigned long end;
623 pmdval_t mask;
624 pmdval_t prot;
625 pmdval_t clear;
626};
627
628static 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
655static 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 */
677static 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. */
699static 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
731static inline void fix_kernmem_perms(void)
732{
733 set_section_perms(nx_perms, prot);
734}
735
736#ifdef CONFIG_DEBUG_RODATA
737void mark_rodata_ro(void)
738{
739 set_section_perms(ro_perms, prot);
740}
741
742void set_kernel_text_rw(void)
743{
744 set_section_perms(ro_perms, clear);
745}
746
747void set_kernel_text_ro(void)
748{
749 set_section_perms(ro_perms, prot);
750}
751#endif /* CONFIG_DEBUG_RODATA */
752
753#else
754static inline void fix_kernmem_perms(void) { }
755#endif /* CONFIG_ARM_KERNMEM_PERMS */
756
757void 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
767void 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())