aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:50:07 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:50:07 -0500
commit9cb543124a2d31af42ce61a4c30765ecc8e5f1fa (patch)
tree9ac55de78161c7eb323e7358b37d9617beb4e018 /arch/arm/mm
parent6629096a5eb861b6d91fe9c2204414d9b072d161 (diff)
parentda141b67d29a05267a9a0d56bd7856b7f3f58d44 (diff)
Merge branch 'for-rmk/virt/kvm/core' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into devel-stable
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/idmap.c55
-rw-r--r--arch/arm/mm/mmu.c22
2 files changed, 66 insertions, 11 deletions
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 9f0610243bd6..1f51d712b55a 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;