diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 17:29:37 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 17:29:37 -0500 |
commit | 6db167dfc013b0e114c81077ac091ba26a69f4ed (patch) | |
tree | 1978b8a2774e0fdb3690065625b0b5eb84475552 /arch/arm/mm | |
parent | 32f9aab8ebd886211a7b3e552753af014c3e5225 (diff) | |
parent | 9cb543124a2d31af42ce61a4c30765ecc8e5f1fa (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/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/mm/idmap.c | 55 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 22 |
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 | ||
631 | config ARM_VIRT_EXT | 631 | config 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 | |||
648 | config SWP_EMULATE | 644 | config 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 | ||
10 | pgd_t *idmap_pgd; | 13 | pgd_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 | ||
62 | static void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | 65 | static 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) | ||
87 | pgd_t *hyp_pgd; | ||
88 | |||
89 | extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[]; | ||
90 | |||
91 | static 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 | ||
105 | static int __init init_static_idmap_hyp(void) | ||
106 | { | ||
107 | return 0; | ||
108 | } | ||
109 | #endif | ||
110 | |||
77 | extern char __idmap_text_start[], __idmap_text_end[]; | 111 | extern char __idmap_text_start[], __idmap_text_end[]; |
78 | 112 | ||
79 | static int __init init_static_idmap(void) | 113 | static 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 | } |
100 | early_initcall(init_static_idmap); | 133 | early_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; | |||
57 | static unsigned int ecc_mask __initdata = 0; | 57 | static unsigned int ecc_mask __initdata = 0; |
58 | pgprot_t pgprot_user; | 58 | pgprot_t pgprot_user; |
59 | pgprot_t pgprot_kernel; | 59 | pgprot_t pgprot_kernel; |
60 | pgprot_t pgprot_hyp_device; | ||
61 | pgprot_t pgprot_s2; | ||
62 | pgprot_t pgprot_s2_device; | ||
60 | 63 | ||
61 | EXPORT_SYMBOL(pgprot_user); | 64 | EXPORT_SYMBOL(pgprot_user); |
62 | EXPORT_SYMBOL(pgprot_kernel); | 65 | EXPORT_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 | |||
71 | static struct cachepolicy cache_policies[] __initdata = { | 81 | static 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; |