diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2010-09-13 11:03:21 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-04 11:44:31 -0400 |
commit | 247055aa21ffef1c49dd64710d5e94c2aee19b58 (patch) | |
tree | e9e026b96597d080de4c16bb88c17b0495c61904 /arch/arm/mm | |
parent | ff8b16d7e15a8ba2a6086645614a483e048e3fbf (diff) |
ARM: 6384/1: Remove the domain switching on ARMv6k/v7 CPUs
This patch removes the domain switching functionality via the set_fs and
__switch_to functions on cores that have a TLS register.
Currently, the ioremap and vmalloc areas share the same level 1 page
tables and therefore have the same domain (DOMAIN_KERNEL). When the
kernel domain is modified from Client to Manager (via the __set_fs or in
the __switch_to function), the XN (eXecute Never) bit is overridden and
newer CPUs can speculatively prefetch the ioremap'ed memory.
Linux performs the kernel domain switching to allow user-specific
functions (copy_to/from_user, get/put_user etc.) to access kernel
memory. In order for these functions to work with the kernel domain set
to Client, the patch modifies the LDRT/STRT and related instructions to
the LDR/STR ones.
The user pages access rights are also modified for kernel read-only
access rather than read/write so that the copy-on-write mechanism still
works. CPU_USE_DOMAINS gets disabled only if the hardware has a TLS register
(CPU_32v6K is defined) since writing the TLS value to the high vectors page
isn't possible.
The user addresses passed to the kernel are checked by the access_ok()
function so that they do not point to the kernel space.
Tested-by: Anton Vorontsov <cbouatmailru@gmail.com>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 6 | ||||
-rw-r--r-- | arch/arm/mm/proc-macros.S | 7 | ||||
-rw-r--r-- | arch/arm/mm/proc-v7.S | 5 |
4 files changed, 21 insertions, 5 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 4414a01e1e8a..6d05f79a8cd2 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -599,6 +599,14 @@ config CPU_CP15_MPU | |||
599 | help | 599 | help |
600 | Processor has the CP15 register, which has MPU related registers. | 600 | Processor has the CP15 register, which has MPU related registers. |
601 | 601 | ||
602 | config CPU_USE_DOMAINS | ||
603 | bool | ||
604 | depends on MMU | ||
605 | default y if !CPU_32v6K | ||
606 | help | ||
607 | This option enables or disables the use of domain switching | ||
608 | via the set_fs() function. | ||
609 | |||
602 | # | 610 | # |
603 | # CPU supports 36-bit I/O | 611 | # CPU supports 36-bit I/O |
604 | # | 612 | # |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 72ad3e1f56cf..79c01f540cbe 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/smp_plat.h> | 24 | #include <asm/smp_plat.h> |
25 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
26 | #include <asm/highmem.h> | 26 | #include <asm/highmem.h> |
27 | #include <asm/traps.h> | ||
27 | 28 | ||
28 | #include <asm/mach/arch.h> | 29 | #include <asm/mach/arch.h> |
29 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
@@ -914,12 +915,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
914 | { | 915 | { |
915 | struct map_desc map; | 916 | struct map_desc map; |
916 | unsigned long addr; | 917 | unsigned long addr; |
917 | void *vectors; | ||
918 | 918 | ||
919 | /* | 919 | /* |
920 | * Allocate the vector page early. | 920 | * Allocate the vector page early. |
921 | */ | 921 | */ |
922 | vectors = early_alloc(PAGE_SIZE); | 922 | vectors_page = early_alloc(PAGE_SIZE); |
923 | 923 | ||
924 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) | 924 | for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) |
925 | pmd_clear(pmd_off_k(addr)); | 925 | pmd_clear(pmd_off_k(addr)); |
@@ -959,7 +959,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) | |||
959 | * location (0xffff0000). If we aren't using high-vectors, also | 959 | * location (0xffff0000). If we aren't using high-vectors, also |
960 | * create a mapping at the low-vectors virtual address. | 960 | * create a mapping at the low-vectors virtual address. |
961 | */ | 961 | */ |
962 | map.pfn = __phys_to_pfn(virt_to_phys(vectors)); | 962 | map.pfn = __phys_to_pfn(virt_to_phys(vectors_page)); |
963 | map.virtual = 0xffff0000; | 963 | map.virtual = 0xffff0000; |
964 | map.length = PAGE_SIZE; | 964 | map.length = PAGE_SIZE; |
965 | map.type = MT_HIGH_VECTORS; | 965 | map.type = MT_HIGH_VECTORS; |
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 7d63beaf9745..337f10256cd6 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S | |||
@@ -99,6 +99,10 @@ | |||
99 | * 110x 0 1 0 r/w r/o | 99 | * 110x 0 1 0 r/w r/o |
100 | * 11x0 0 1 0 r/w r/o | 100 | * 11x0 0 1 0 r/w r/o |
101 | * 1111 0 1 1 r/w r/w | 101 | * 1111 0 1 1 r/w r/w |
102 | * | ||
103 | * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed: | ||
104 | * 110x 1 1 1 r/o r/o | ||
105 | * 11x0 1 1 1 r/o r/o | ||
102 | */ | 106 | */ |
103 | .macro armv6_mt_table pfx | 107 | .macro armv6_mt_table pfx |
104 | \pfx\()_mt_table: | 108 | \pfx\()_mt_table: |
@@ -138,8 +142,11 @@ | |||
138 | 142 | ||
139 | tst r1, #L_PTE_USER | 143 | tst r1, #L_PTE_USER |
140 | orrne r3, r3, #PTE_EXT_AP1 | 144 | orrne r3, r3, #PTE_EXT_AP1 |
145 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
146 | @ allow kernel read/write access to read-only user pages | ||
141 | tstne r3, #PTE_EXT_APX | 147 | tstne r3, #PTE_EXT_APX |
142 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 148 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
149 | #endif | ||
143 | 150 | ||
144 | tst r1, #L_PTE_EXEC | 151 | tst r1, #L_PTE_EXEC |
145 | orreq r3, r3, #PTE_EXT_XN | 152 | orreq r3, r3, #PTE_EXT_XN |
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 53cbe2225153..cfc11afab1fb 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S | |||
@@ -148,8 +148,11 @@ ENTRY(cpu_v7_set_pte_ext) | |||
148 | 148 | ||
149 | tst r1, #L_PTE_USER | 149 | tst r1, #L_PTE_USER |
150 | orrne r3, r3, #PTE_EXT_AP1 | 150 | orrne r3, r3, #PTE_EXT_AP1 |
151 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
152 | @ allow kernel read/write access to read-only user pages | ||
151 | tstne r3, #PTE_EXT_APX | 153 | tstne r3, #PTE_EXT_APX |
152 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 | 154 | bicne r3, r3, #PTE_EXT_APX | PTE_EXT_AP0 |
155 | #endif | ||
153 | 156 | ||
154 | tst r1, #L_PTE_EXEC | 157 | tst r1, #L_PTE_EXEC |
155 | orreq r3, r3, #PTE_EXT_XN | 158 | orreq r3, r3, #PTE_EXT_XN |
@@ -273,8 +276,6 @@ __v7_setup: | |||
273 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) | 276 | ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) |
274 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) | 277 | ALT_UP(orr r4, r4, #TTB_FLAGS_UP) |
275 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 278 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
276 | mov r10, #0x1f @ domains 0, 1 = manager | ||
277 | mcr p15, 0, r10, c3, c0, 0 @ load domain access register | ||
278 | /* | 279 | /* |
279 | * Memory region attributes with SCTLR.TRE=1 | 280 | * Memory region attributes with SCTLR.TRE=1 |
280 | * | 281 | * |