ARM: domains: switch to keeping domain value in register
authorRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 19 Aug 2015 20:23:48 +0000 (21:23 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 21 Aug 2015 12:55:49 +0000 (13:55 +0100)
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>
arch/arm/include/asm/domain.h
arch/arm/include/asm/thread_info.h
arch/arm/kernel/entry-armv.S
arch/arm/kernel/process.c

index 6ddbe446425e11524d927b5cd8b479bcd2419238..7f29419057145d92903488148a6096c14cf7c602 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+static inline unsigned int get_domain(void)
+{
+       unsigned int domain;
+
+       asm(
+       "mrc    p15, 0, %0, c3, c0      @ get domain"
+        : "=r" (domain));
+
+       return domain;
+}
+
 #ifdef CONFIG_CPU_USE_DOMAINS
 static inline void set_domain(unsigned val)
 {
@@ -70,11 +81,10 @@ static inline void set_domain(unsigned val)
 
 #define modify_domain(dom,type)                                        \
        do {                                                    \
-       struct thread_info *thread = current_thread_info();     \
-       unsigned int domain = thread->cpu_domain;               \
-       domain &= ~domain_val(dom, DOMAIN_MANAGER);             \
-       thread->cpu_domain = domain | domain_val(dom, type);    \
-       set_domain(thread->cpu_domain);                         \
+               unsigned int domain = get_domain();             \
+               domain &= ~domain_val(dom, DOMAIN_MANAGER);     \
+               domain = domain | domain_val(dom, type);        \
+               set_domain(domain);                             \
        } while (0)
 
 #else
index bd32eded3e5061b49048e3110902b7edc63e3638..0a0aec410d8c81c4b65cf920c7e2350ae346ddb8 100644 (file)
@@ -74,9 +74,6 @@ struct thread_info {
        .flags          = 0,                                            \
        .preempt_count  = INIT_PREEMPT_COUNT,                           \
        .addr_limit     = KERNEL_DS,                                    \
-       .cpu_domain     = domain_val(DOMAIN_USER, DOMAIN_MANAGER) |     \
-                         domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |   \
-                         domain_val(DOMAIN_IO, DOMAIN_CLIENT),         \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
index 7dac3086e361c8e3680d5209e5b72184c9c48cdb..d19adcf6c580c4d1f7be7a909896490cca534e30 100644 (file)
@@ -770,6 +770,8 @@ ENTRY(__switch_to)
        ldr     r4, [r2, #TI_TP_VALUE]
        ldr     r5, [r2, #TI_TP_VALUE + 4]
 #ifdef CONFIG_CPU_USE_DOMAINS
+       mrc     p15, 0, r6, c3, c0, 0           @ Get domain register
+       str     r6, [r1, #TI_CPU_DOMAIN]        @ Save old domain register
        ldr     r6, [r2, #TI_CPU_DOMAIN]
 #endif
        switch_tls r1, r4, r5, r3, r7
index f192a2a4171935720cfc702953703c78078579cc..e722f9b3c9b1063da76fbd785f98d9128aba57cb 100644 (file)
@@ -146,10 +146,9 @@ void __show_regs(struct pt_regs *regs)
                buf[0] = '\0';
 #ifdef CONFIG_CPU_CP15_MMU
                {
-                       unsigned int transbase, dac;
+                       unsigned int transbase, dac = get_domain();
                        asm("mrc p15, 0, %0, c2, c0\n\t"
-                           "mrc p15, 0, %1, c3, c0\n"
-                           : "=r" (transbase), "=r" (dac));
+                           : "=r" (transbase));
                        snprintf(buf, sizeof(buf), "  Table: %08x  DAC: %08x",
                                transbase, dac);
                }
@@ -210,6 +209,14 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
 
+       /*
+        * Copy the initial value of the domain access control register
+        * from the current thread: thread->addr_limit will have been
+        * copied from the current thread via setup_thread_stack() in
+        * kernel/fork.c
+        */
+       thread->cpu_domain = get_domain();
+
        if (likely(!(p->flags & PF_KTHREAD))) {
                *childregs = *current_pt_regs();
                childregs->ARM_r0 = 0;