aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-08-19 16:23:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-08-21 08:55:49 -0400
commit1eef5d2f1b461c120bcd82077edee5ec706ac53b (patch)
treeb95a7132189a44d9a826e7b44fbbe5cae74d75fb
parentd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff)
ARM: domains: switch to keeping domain value in register
Rather than modifying both the domain access control register and our per-thread copy, modify only the domain access control register, and use the per-thread copy to save and restore the register over context switches. We can also avoid the explicit initialisation of the init thread_info structure. This allows us to avoid needing to gain access to the thread information at the uaccess control sites. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/domain.h20
-rw-r--r--arch/arm/include/asm/thread_info.h3
-rw-r--r--arch/arm/kernel/entry-armv.S2
-rw-r--r--arch/arm/kernel/process.c13
4 files changed, 27 insertions, 11 deletions
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index 6ddbe446425e..7f2941905714 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -59,6 +59,17 @@
59 59
60#ifndef __ASSEMBLY__ 60#ifndef __ASSEMBLY__
61 61
62static inline unsigned int get_domain(void)
63{
64 unsigned int domain;
65
66 asm(
67 "mrc p15, 0, %0, c3, c0 @ get domain"
68 : "=r" (domain));
69
70 return domain;
71}
72
62#ifdef CONFIG_CPU_USE_DOMAINS 73#ifdef CONFIG_CPU_USE_DOMAINS
63static inline void set_domain(unsigned val) 74static inline void set_domain(unsigned val)
64{ 75{
@@ -70,11 +81,10 @@ static inline void set_domain(unsigned val)
70 81
71#define modify_domain(dom,type) \ 82#define modify_domain(dom,type) \
72 do { \ 83 do { \
73 struct thread_info *thread = current_thread_info(); \ 84 unsigned int domain = get_domain(); \
74 unsigned int domain = thread->cpu_domain; \ 85 domain &= ~domain_val(dom, DOMAIN_MANAGER); \
75 domain &= ~domain_val(dom, DOMAIN_MANAGER); \ 86 domain = domain | domain_val(dom, type); \
76 thread->cpu_domain = domain | domain_val(dom, type); \ 87 set_domain(domain); \
77 set_domain(thread->cpu_domain); \
78 } while (0) 88 } while (0)
79 89
80#else 90#else
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index bd32eded3e50..0a0aec410d8c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -74,9 +74,6 @@ struct thread_info {
74 .flags = 0, \ 74 .flags = 0, \
75 .preempt_count = INIT_PREEMPT_COUNT, \ 75 .preempt_count = INIT_PREEMPT_COUNT, \
76 .addr_limit = KERNEL_DS, \ 76 .addr_limit = KERNEL_DS, \
77 .cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
78 domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
79 domain_val(DOMAIN_IO, DOMAIN_CLIENT), \
80} 77}
81 78
82#define init_thread_info (init_thread_union.thread_info) 79#define init_thread_info (init_thread_union.thread_info)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7dac3086e361..d19adcf6c580 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -770,6 +770,8 @@ ENTRY(__switch_to)
770 ldr r4, [r2, #TI_TP_VALUE] 770 ldr r4, [r2, #TI_TP_VALUE]
771 ldr r5, [r2, #TI_TP_VALUE + 4] 771 ldr r5, [r2, #TI_TP_VALUE + 4]
772#ifdef CONFIG_CPU_USE_DOMAINS 772#ifdef CONFIG_CPU_USE_DOMAINS
773 mrc p15, 0, r6, c3, c0, 0 @ Get domain register
774 str r6, [r1, #TI_CPU_DOMAIN] @ Save old domain register
773 ldr r6, [r2, #TI_CPU_DOMAIN] 775 ldr r6, [r2, #TI_CPU_DOMAIN]
774#endif 776#endif
775 switch_tls r1, r4, r5, r3, r7 777 switch_tls r1, r4, r5, r3, r7
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index f192a2a41719..e722f9b3c9b1 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -146,10 +146,9 @@ void __show_regs(struct pt_regs *regs)
146 buf[0] = '\0'; 146 buf[0] = '\0';
147#ifdef CONFIG_CPU_CP15_MMU 147#ifdef CONFIG_CPU_CP15_MMU
148 { 148 {
149 unsigned int transbase, dac; 149 unsigned int transbase, dac = get_domain();
150 asm("mrc p15, 0, %0, c2, c0\n\t" 150 asm("mrc p15, 0, %0, c2, c0\n\t"
151 "mrc p15, 0, %1, c3, c0\n" 151 : "=r" (transbase));
152 : "=r" (transbase), "=r" (dac));
153 snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", 152 snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x",
154 transbase, dac); 153 transbase, dac);
155 } 154 }
@@ -210,6 +209,14 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
210 209
211 memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); 210 memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
212 211
212 /*
213 * Copy the initial value of the domain access control register
214 * from the current thread: thread->addr_limit will have been
215 * copied from the current thread via setup_thread_stack() in
216 * kernel/fork.c
217 */
218 thread->cpu_domain = get_domain();
219
213 if (likely(!(p->flags & PF_KTHREAD))) { 220 if (likely(!(p->flags & PF_KTHREAD))) {
214 *childregs = *current_pt_regs(); 221 *childregs = *current_pt_regs();
215 childregs->ARM_r0 = 0; 222 childregs->ARM_r0 = 0;