aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 17:29:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-20 17:29:37 -0500
commit6db167dfc013b0e114c81077ac091ba26a69f4ed (patch)
tree1978b8a2774e0fdb3690065625b0b5eb84475552 /arch/arm/mm
parent32f9aab8ebd886211a7b3e552753af014c3e5225 (diff)
parent9cb543124a2d31af42ce61a4c30765ecc8e5f1fa (diff)
Merge branch 'for-linus-2' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM updates (part two) from Russell King: - breakpoint and perf updates from Will Deacon. - hypervisor boot mode updates from Will. - support for Power State Coordination Interface via the Hypervisor - core ARM support for KVM * 'for-linus-2' of git://git.linaro.org/people/rmk/linux-arm: (32 commits) KVM: ARM: Add maintainer entry for KVM/ARM KVM: ARM: Power State Coordination Interface implementation KVM: ARM: Handle I/O aborts KVM: ARM: Handle guest faults in KVM KVM: ARM: VFP userspace interface KVM: ARM: Demux CCSIDR in the userspace API KVM: ARM: User space API for getting/setting co-proc registers KVM: ARM: Emulation framework and CP15 emulation KVM: ARM: World-switch implementation KVM: ARM: Inject IRQs and FIQs from userspace KVM: ARM: Memory virtualization setup KVM: ARM: Hypervisor initialization KVM: ARM: Initial skeleton to compile KVM support ARM: Section based HYP idmap ARM: Add page table and page defines needed by KVM ARM: perf: simplify __hw_perf_event_init err handling ARM: perf: remove unnecessary checks for idx < 0 ARM: perf: handle armpmu_register failing ARM: perf: don't pretend to support counting of L1I writes ARM: perf: remove redundant NULL check on cpu_pmu ...
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/Kconfig10
-rw-r--r--arch/arm/mm/idmap.c55
-rw-r--r--arch/arm/mm/mmu.c22
3 files changed, 69 insertions, 18 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 3fd629d5a513..025d17328730 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -629,8 +629,9 @@ config ARM_THUMBEE
629 make use of it. Say N for code that can run on CPUs without ThumbEE. 629 make use of it. Say N for code that can run on CPUs without ThumbEE.
630 630
631config ARM_VIRT_EXT 631config ARM_VIRT_EXT
632 bool "Native support for the ARM Virtualization Extensions" 632 bool
633 depends on MMU && CPU_V7 633 depends on MMU
634 default y if CPU_V7
634 help 635 help
635 Enable the kernel to make use of the ARM Virtualization 636 Enable the kernel to make use of the ARM Virtualization
636 Extensions to install hypervisors without run-time firmware 637 Extensions to install hypervisors without run-time firmware
@@ -640,11 +641,6 @@ config ARM_VIRT_EXT
640 use of this feature. Refer to Documentation/arm/Booting for 641 use of this feature. Refer to Documentation/arm/Booting for
641 details. 642 details.
642 643
643 It is safe to enable this option even if the kernel may not be
644 booted in HYP mode, may not have support for the
645 virtualization extensions, or may be booted with a
646 non-compliant bootloader.
647
648config SWP_EMULATE 644config SWP_EMULATE
649 bool "Emulate SWP/SWPB instructions" 645 bool "Emulate SWP/SWPB instructions"
650 depends on !CPU_USE_DOMAINS && CPU_V7 646 depends on !CPU_USE_DOMAINS && CPU_V7
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index 99db769307ec..2dffc010cc41 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -1,4 +1,6 @@
1#include <linux/module.h>
1#include <linux/kernel.h> 2#include <linux/kernel.h>
3#include <linux/slab.h>
2 4
3#include <asm/cputype.h> 5#include <asm/cputype.h>
4#include <asm/idmap.h> 6#include <asm/idmap.h>
@@ -6,6 +8,7 @@
6#include <asm/pgtable.h> 8#include <asm/pgtable.h>
7#include <asm/sections.h> 9#include <asm/sections.h>
8#include <asm/system_info.h> 10#include <asm/system_info.h>
11#include <asm/virt.h>
9 12
10pgd_t *idmap_pgd; 13pgd_t *idmap_pgd;
11 14
@@ -59,11 +62,17 @@ static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
59 } while (pud++, addr = next, addr != end); 62 } while (pud++, addr = next, addr != end);
60} 63}
61 64
62static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) 65static void identity_mapping_add(pgd_t *pgd, const char *text_start,
66 const char *text_end, unsigned long prot)
63{ 67{
64 unsigned long prot, next; 68 unsigned long addr, end;
69 unsigned long next;
70
71 addr = virt_to_phys(text_start);
72 end = virt_to_phys(text_end);
73
74 prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
65 75
66 prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
67 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) 76 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
68 prot |= PMD_BIT4; 77 prot |= PMD_BIT4;
69 78
@@ -74,28 +83,52 @@ static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long e
74 } while (pgd++, addr = next, addr != end); 83 } while (pgd++, addr = next, addr != end);
75} 84}
76 85
86#if defined(CONFIG_ARM_VIRT_EXT) && defined(CONFIG_ARM_LPAE)
87pgd_t *hyp_pgd;
88
89extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[];
90
91static int __init init_static_idmap_hyp(void)
92{
93 hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
94 if (!hyp_pgd)
95 return -ENOMEM;
96
97 pr_info("Setting up static HYP identity map for 0x%p - 0x%p\n",
98 __hyp_idmap_text_start, __hyp_idmap_text_end);
99 identity_mapping_add(hyp_pgd, __hyp_idmap_text_start,
100 __hyp_idmap_text_end, PMD_SECT_AP1);
101
102 return 0;
103}
104#else
105static int __init init_static_idmap_hyp(void)
106{
107 return 0;
108}
109#endif
110
77extern char __idmap_text_start[], __idmap_text_end[]; 111extern char __idmap_text_start[], __idmap_text_end[];
78 112
79static int __init init_static_idmap(void) 113static int __init init_static_idmap(void)
80{ 114{
81 phys_addr_t idmap_start, idmap_end; 115 int ret;
82 116
83 idmap_pgd = pgd_alloc(&init_mm); 117 idmap_pgd = pgd_alloc(&init_mm);
84 if (!idmap_pgd) 118 if (!idmap_pgd)
85 return -ENOMEM; 119 return -ENOMEM;
86 120
87 /* Add an identity mapping for the physical address of the section. */ 121 pr_info("Setting up static identity map for 0x%p - 0x%p\n",
88 idmap_start = virt_to_phys((void *)__idmap_text_start); 122 __idmap_text_start, __idmap_text_end);
89 idmap_end = virt_to_phys((void *)__idmap_text_end); 123 identity_mapping_add(idmap_pgd, __idmap_text_start,
124 __idmap_text_end, 0);
90 125
91 pr_info("Setting up static identity map for 0x%llx - 0x%llx\n", 126 ret = init_static_idmap_hyp();
92 (long long)idmap_start, (long long)idmap_end);
93 identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
94 127
95 /* Flush L1 for the hardware to see this page table content */ 128 /* Flush L1 for the hardware to see this page table content */
96 flush_cache_louis(); 129 flush_cache_louis();
97 130
98 return 0; 131 return ret;
99} 132}
100early_initcall(init_static_idmap); 133early_initcall(init_static_idmap);
101 134
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 69bb735474fe..e95a996ab78f 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -57,6 +57,9 @@ static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
57static unsigned int ecc_mask __initdata = 0; 57static unsigned int ecc_mask __initdata = 0;
58pgprot_t pgprot_user; 58pgprot_t pgprot_user;
59pgprot_t pgprot_kernel; 59pgprot_t pgprot_kernel;
60pgprot_t pgprot_hyp_device;
61pgprot_t pgprot_s2;
62pgprot_t pgprot_s2_device;
60 63
61EXPORT_SYMBOL(pgprot_user); 64EXPORT_SYMBOL(pgprot_user);
62EXPORT_SYMBOL(pgprot_kernel); 65EXPORT_SYMBOL(pgprot_kernel);
@@ -66,34 +69,46 @@ struct cachepolicy {
66 unsigned int cr_mask; 69 unsigned int cr_mask;
67 pmdval_t pmd; 70 pmdval_t pmd;
68 pteval_t pte; 71 pteval_t pte;
72 pteval_t pte_s2;
69}; 73};
70 74
75#ifdef CONFIG_ARM_LPAE
76#define s2_policy(policy) policy
77#else
78#define s2_policy(policy) 0
79#endif
80
71static struct cachepolicy cache_policies[] __initdata = { 81static struct cachepolicy cache_policies[] __initdata = {
72 { 82 {
73 .policy = "uncached", 83 .policy = "uncached",
74 .cr_mask = CR_W|CR_C, 84 .cr_mask = CR_W|CR_C,
75 .pmd = PMD_SECT_UNCACHED, 85 .pmd = PMD_SECT_UNCACHED,
76 .pte = L_PTE_MT_UNCACHED, 86 .pte = L_PTE_MT_UNCACHED,
87 .pte_s2 = s2_policy(L_PTE_S2_MT_UNCACHED),
77 }, { 88 }, {
78 .policy = "buffered", 89 .policy = "buffered",
79 .cr_mask = CR_C, 90 .cr_mask = CR_C,
80 .pmd = PMD_SECT_BUFFERED, 91 .pmd = PMD_SECT_BUFFERED,
81 .pte = L_PTE_MT_BUFFERABLE, 92 .pte = L_PTE_MT_BUFFERABLE,
93 .pte_s2 = s2_policy(L_PTE_S2_MT_UNCACHED),
82 }, { 94 }, {
83 .policy = "writethrough", 95 .policy = "writethrough",
84 .cr_mask = 0, 96 .cr_mask = 0,
85 .pmd = PMD_SECT_WT, 97 .pmd = PMD_SECT_WT,
86 .pte = L_PTE_MT_WRITETHROUGH, 98 .pte = L_PTE_MT_WRITETHROUGH,
99 .pte_s2 = s2_policy(L_PTE_S2_MT_WRITETHROUGH),
87 }, { 100 }, {
88 .policy = "writeback", 101 .policy = "writeback",
89 .cr_mask = 0, 102 .cr_mask = 0,
90 .pmd = PMD_SECT_WB, 103 .pmd = PMD_SECT_WB,
91 .pte = L_PTE_MT_WRITEBACK, 104 .pte = L_PTE_MT_WRITEBACK,
105 .pte_s2 = s2_policy(L_PTE_S2_MT_WRITEBACK),
92 }, { 106 }, {
93 .policy = "writealloc", 107 .policy = "writealloc",
94 .cr_mask = 0, 108 .cr_mask = 0,
95 .pmd = PMD_SECT_WBWA, 109 .pmd = PMD_SECT_WBWA,
96 .pte = L_PTE_MT_WRITEALLOC, 110 .pte = L_PTE_MT_WRITEALLOC,
111 .pte_s2 = s2_policy(L_PTE_S2_MT_WRITEBACK),
97 } 112 }
98}; 113};
99 114
@@ -310,6 +325,7 @@ static void __init build_mem_type_table(void)
310 struct cachepolicy *cp; 325 struct cachepolicy *cp;
311 unsigned int cr = get_cr(); 326 unsigned int cr = get_cr();
312 pteval_t user_pgprot, kern_pgprot, vecs_pgprot; 327 pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
328 pteval_t hyp_device_pgprot, s2_pgprot, s2_device_pgprot;
313 int cpu_arch = cpu_architecture(); 329 int cpu_arch = cpu_architecture();
314 int i; 330 int i;
315 331
@@ -421,6 +437,8 @@ static void __init build_mem_type_table(void)
421 */ 437 */
422 cp = &cache_policies[cachepolicy]; 438 cp = &cache_policies[cachepolicy];
423 vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; 439 vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
440 s2_pgprot = cp->pte_s2;
441 hyp_device_pgprot = s2_device_pgprot = mem_types[MT_DEVICE].prot_pte;
424 442
425 /* 443 /*
426 * ARMv6 and above have extended page tables. 444 * ARMv6 and above have extended page tables.
@@ -444,6 +462,7 @@ static void __init build_mem_type_table(void)
444 user_pgprot |= L_PTE_SHARED; 462 user_pgprot |= L_PTE_SHARED;
445 kern_pgprot |= L_PTE_SHARED; 463 kern_pgprot |= L_PTE_SHARED;
446 vecs_pgprot |= L_PTE_SHARED; 464 vecs_pgprot |= L_PTE_SHARED;
465 s2_pgprot |= L_PTE_SHARED;
447 mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S; 466 mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
448 mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED; 467 mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
449 mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S; 468 mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
@@ -498,6 +517,9 @@ static void __init build_mem_type_table(void)
498 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot); 517 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
499 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | 518 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
500 L_PTE_DIRTY | kern_pgprot); 519 L_PTE_DIRTY | kern_pgprot);
520 pgprot_s2 = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | s2_pgprot);
521 pgprot_s2_device = __pgprot(s2_device_pgprot);
522 pgprot_hyp_device = __pgprot(hyp_device_pgprot);
501 523
502 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask; 524 mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
503 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask; 525 mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;