]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 20:03:05 +0000 (16:03 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Apr 2015 20:03:05 +0000 (16:03 -0400)
Pull arch/tile updates from Chris Metcalf:
 "These are mostly nohz_full changes, plus a smattering of minor fixes
  (notably a couple for ftrace)"

* git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile:
  tile: nohz: warn if nohz_full uses hypervisor shared cores
  tile: ftrace: fix function_graph tracer issues
  tile: map data region shadow of kernel as R/W
  tile: support CONTEXT_TRACKING and thus NOHZ_FULL
  tile: support arch_irq_work_raise
  arch: tile: fix null pointer dereference on pt_regs pointer
  tile/elf: reorganize notify_exec()
  tile: use si_int instead of si_ptr for compat_siginfo

21 files changed:
arch/tile/Kconfig
arch/tile/include/asm/Kbuild
arch/tile/include/asm/ftrace.h
arch/tile/include/asm/irq_work.h [new file with mode: 0644]
arch/tile/include/asm/smp.h
arch/tile/include/asm/thread_info.h
arch/tile/include/hv/hypervisor.h
arch/tile/kernel/compat_signal.c
arch/tile/kernel/ftrace.c
arch/tile/kernel/mcount_64.S
arch/tile/kernel/process.c
arch/tile/kernel/ptrace.c
arch/tile/kernel/setup.c
arch/tile/kernel/single_step.c
arch/tile/kernel/smp.c
arch/tile/kernel/stack.c
arch/tile/kernel/traps.c
arch/tile/kernel/unaligned.c
arch/tile/mm/elf.c
arch/tile/mm/fault.c
arch/tile/mm/init.c

index 0142d578b5a84d5277e7bdf81510aba80dc9ff9a..a07e31b50d3f783e92ee1ccfab11293308d40472 100644 (file)
@@ -27,6 +27,7 @@ config TILE
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select HAVE_DEBUG_STACKOVERFLOW
        select ARCH_WANT_FRAME_POINTERS
+       select HAVE_CONTEXT_TRACKING
 
 # FIXME: investigate whether we need/want these options.
 #      select HAVE_IOREMAP_PROT
index b4c488b657456f3e5a4fa4b74c40a3a427b5cc28..f5433e0e34e0bc5dc6e176490388141ea71db011 100644 (file)
@@ -16,7 +16,6 @@ generic-y += ioctl.h
 generic-y += ioctls.h
 generic-y += ipcbuf.h
 generic-y += irq_regs.h
-generic-y += irq_work.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
index 13a9bb81a8ab4754ff93da4c8f17da8a134ce4ec..738d239b792f0aab7a974f75600bd7adad676b4f 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef __ASSEMBLY__
 extern void __mcount(void);
 
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
diff --git a/arch/tile/include/asm/irq_work.h b/arch/tile/include/asm/irq_work.h
new file mode 100644 (file)
index 0000000..48af33a
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ASM_IRQ_WORK_H
+#define __ASM_IRQ_WORK_H
+
+static inline bool arch_irq_work_has_interrupt(void)
+{
+#ifdef CONFIG_SMP
+       extern bool self_interrupt_ok;
+       return self_interrupt_ok;
+#else
+       return false;
+#endif
+}
+
+#endif /* __ASM_IRQ_WORK_H */
index 9a326b64f7aeae059ad7de57d2744a3270f6e18b..735e7f14473360617a78071f7d2c7dc059c847f2 100644 (file)
@@ -69,6 +69,7 @@ static inline int xy_to_cpu(int x, int y)
 #define MSG_TAG_STOP_CPU               2
 #define MSG_TAG_CALL_FUNCTION_MANY     3
 #define MSG_TAG_CALL_FUNCTION_SINGLE   4
+#define MSG_TAG_IRQ_WORK               5
 
 /* Hook for the generic smp_call_function_many() routine. */
 static inline void arch_send_call_function_ipi_mask(struct cpumask *mask)
index 98ee10a0ae89e8434e1ac45c68e9140d7027fcc8..f804c39a5e4d63998b9a9d75f9ba65fdc2bb0aff 100644 (file)
@@ -124,6 +124,7 @@ extern void _cpu_idle(void);
 #define TIF_NOTIFY_RESUME      8       /* callback before returning to user */
 #define TIF_SYSCALL_TRACEPOINT 9       /* syscall tracepoint instrumentation */
 #define TIF_POLLING_NRFLAG     10      /* idle is polling for TIF_NEED_RESCHED */
+#define TIF_NOHZ               11      /* in adaptive nohz mode */
 
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
@@ -136,14 +137,16 @@ extern void _cpu_idle(void);
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+#define _TIF_NOHZ              (1<<TIF_NOHZ)
 
 /* Work to do on any return to user space. */
 #define _TIF_ALLWORK_MASK \
-  (_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SINGLESTEP|\
-   _TIF_ASYNC_TLB|_TIF_NOTIFY_RESUME)
+       (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP | \
+        _TIF_ASYNC_TLB | _TIF_NOTIFY_RESUME | _TIF_NOHZ)
 
 /* Work to do at syscall entry. */
-#define _TIF_SYSCALL_ENTRY_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SYSCALL_ENTRY_WORK \
+       (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_NOHZ)
 
 /* Work to do at syscall exit. */
 #define _TIF_SYSCALL_EXIT_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT)
index dfcdeb61ba34d91e19446f0305971002fc1f8916..e0e6af4e783b077ca01968ae54af1a2a622834fb 100644 (file)
@@ -961,7 +961,11 @@ typedef enum {
   HV_INQ_TILES_HFH_CACHE       = 2,
 
   /** The set of tiles that can be legally used as a LOTAR for a PTE. */
-  HV_INQ_TILES_LOTAR           = 3
+  HV_INQ_TILES_LOTAR           = 3,
+
+  /** The set of "shared" driver tiles that the hypervisor may
+   *  periodically interrupt. */
+  HV_INQ_TILES_SHARED          = 4
 } HV_InqTileSet;
 
 /** Returns specific information about various sets of tiles within the
index 5cbc864398d310924356897880ad332084aa301f..e8c2c04143cda81db9b51018a449b611263ab68d 100644 (file)
@@ -68,7 +68,7 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr
        if (from->si_code < 0) {
                err |= __put_user(from->si_pid, &to->si_pid);
                err |= __put_user(from->si_uid, &to->si_uid);
-               err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
+               err |= __put_user(from->si_int, &to->si_int);
        } else {
                /*
                 * First 32bits of unions are always present:
@@ -93,8 +93,7 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr
                        break;
                case __SI_TIMER >> 16:
                        err |= __put_user(from->si_overrun, &to->si_overrun);
-                       err |= __put_user(ptr_to_compat(from->si_ptr),
-                                         &to->si_ptr);
+                       err |= __put_user(from->si_int, &to->si_int);
                        break;
                         /* This is not generated by the kernel as of now.  */
                case __SI_RT >> 16:
@@ -110,19 +109,19 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *fr
 int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 {
        int err;
-       u32 ptr32;
 
        if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
                return -EFAULT;
 
+       memset(to, 0, sizeof(*to));
+
        err = __get_user(to->si_signo, &from->si_signo);
        err |= __get_user(to->si_errno, &from->si_errno);
        err |= __get_user(to->si_code, &from->si_code);
 
        err |= __get_user(to->si_pid, &from->si_pid);
        err |= __get_user(to->si_uid, &from->si_uid);
-       err |= __get_user(ptr32, &from->si_ptr);
-       to->si_ptr = compat_ptr(ptr32);
+       err |= __get_user(to->si_int, &from->si_int);
 
        return err;
 }
index 8d52d83cc51617b8d8e055dba3672cdcbdd46f3a..0c0996175b1ed613cf6fe4d3e89cec85ea5c6a6f 100644 (file)
@@ -74,7 +74,11 @@ static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
                        create_JumpOff_X1(pcrel_by_instr);
        }
 
-       if (addr == FTRACE_ADDR) {
+       /*
+        * Also put { move r10, lr; jal ftrace_stub } in a bundle, which
+        * is used to replace the instruction in address ftrace_call.
+        */
+       if (addr == FTRACE_ADDR || addr == (unsigned long)ftrace_stub) {
                /* opcode: or r10, lr, zero */
                opcode_x0 =
                        create_Dest_X0(10) |
index 3c2b8d5e1d1a02feb744da440a3bab224b125d6d..6c6702451962360cefa822f403c18628a31bb2e7 100644 (file)
@@ -81,7 +81,12 @@ STD_ENTRY(ftrace_caller)
 
        /* arg1: self return address */
        /* arg2: parent's return address */
-       { move  r0, lr; move    r1, r10 }
+       /* arg3: ftrace_ops */
+       /* arg4: regs (but make it NULL) */
+       { move  r0, lr;  moveli        r2, hw2_last(function_trace_op) }
+       { move  r1, r10; shl16insli    r2, r2, hw1(function_trace_op) }
+       { movei r3, 0;   shl16insli    r2, r2, hw0(function_trace_op) }
+       ld      r2,r2
 
        .global ftrace_call
 ftrace_call:
index 48e5773dd0b7728fdcb2d3500580f4c1b11e1ab6..b403c2e3e26344b7468a9d775c177bbcfd702118 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/tracehook.h>
 #include <linux/signal.h>
+#include <linux/context_tracking.h>
 #include <asm/stack.h>
 #include <asm/switch_to.h>
 #include <asm/homecache.h>
@@ -474,6 +475,8 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
        if (!user_mode(regs))
                return 0;
 
+       user_exit();
+
        /* Enable interrupts; they are disabled again on return to caller. */
        local_irq_enable();
 
@@ -496,11 +499,12 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
                tracehook_notify_resume(regs);
                return 1;
        }
-       if (thread_info_flags & _TIF_SINGLESTEP) {
+       if (thread_info_flags & _TIF_SINGLESTEP)
                single_step_once(regs);
-               return 0;
-       }
-       panic("work_pending: bad flags %#x\n", thread_info_flags);
+
+       user_enter();
+
+       return 0;
 }
 
 unsigned long get_wchan(struct task_struct *p)
index de98c6ddf136dbeebee00b7d8b1c553cc8bf56c1..f84eed8243da54f00f816b877d42d9c4f70db54b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/regset.h>
 #include <linux/elf.h>
 #include <linux/tracehook.h>
+#include <linux/context_tracking.h>
 #include <asm/traps.h>
 #include <arch/chip.h>
 
@@ -252,12 +253,21 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 int do_syscall_trace_enter(struct pt_regs *regs)
 {
-       if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+       u32 work = ACCESS_ONCE(current_thread_info()->flags);
+
+       /*
+        * If TIF_NOHZ is set, we are required to call user_exit() before
+        * doing anything that could touch RCU.
+        */
+       if (work & _TIF_NOHZ)
+               user_exit();
+
+       if (work & _TIF_SYSCALL_TRACE) {
                if (tracehook_report_syscall_entry(regs))
                        regs->regs[TREG_SYSCALL_NR] = -1;
        }
 
-       if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+       if (work & _TIF_SYSCALL_TRACEPOINT)
                trace_sys_enter(regs, regs->regs[TREG_SYSCALL_NR]);
 
        return regs->regs[TREG_SYSCALL_NR];
@@ -267,6 +277,12 @@ void do_syscall_trace_exit(struct pt_regs *regs)
 {
        long errno;
 
+       /*
+        * We may come here right after calling schedule_user()
+        * in which case we can be in RCU user mode.
+        */
+       user_exit();
+
        /*
         * The standard tile calling convention returns the value (or negative
         * errno) in r0, and zero (or positive errno) in r1.
@@ -303,5 +319,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs)
 /* Handle synthetic interrupt delivered only by the simulator. */
 void __kprobes do_breakpoint(struct pt_regs* regs, int fault_num)
 {
+       enum ctx_state prev_state = exception_enter();
        send_sigtrap(current, regs);
+       exception_exit(prev_state);
 }
index f1f57991495235dc2578048caca0b6c5be3c0beb..7833b2ccdfbcda44bce821384d37532e32d663e7 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/hugetlb.h>
 #include <linux/start_kernel.h>
 #include <linux/screen_info.h>
+#include <linux/tick.h>
 #include <asm/setup.h>
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
@@ -1390,6 +1391,28 @@ static int __init dataplane(char *str)
 
 early_param("dataplane", dataplane);
 
+#ifdef CONFIG_NO_HZ_FULL
+/* Warn if hypervisor shared cpus are marked as nohz_full. */
+static int __init check_nohz_full_cpus(void)
+{
+       struct cpumask shared;
+       int cpu;
+
+       if (hv_inquire_tiles(HV_INQ_TILES_SHARED,
+                            (HV_VirtAddr) shared.bits, sizeof(shared)) < 0) {
+               pr_warn("WARNING: No support for inquiring hv shared tiles\n");
+               return 0;
+       }
+       for_each_cpu(cpu, &shared) {
+               if (tick_nohz_full_cpu(cpu))
+                       pr_warn("WARNING: nohz_full cpu %d receives hypervisor interrupts!\n",
+                              cpu);
+       }
+       return 0;
+}
+arch_initcall(check_nohz_full_cpus);
+#endif
+
 #ifdef CONFIG_CMDLINE_BOOL
 static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
 #endif
index 862973074bf91823cea501ee710811cf1b973a31..53f7b9def07b0cbf43b4094e9d667986ad96ebc1 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/err.h>
 #include <linux/prctl.h>
+#include <linux/context_tracking.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
@@ -738,6 +739,7 @@ static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
 
 void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
 {
+       enum ctx_state prev_state = exception_enter();
        unsigned long *ss_pc = this_cpu_ptr(&ss_saved_pc);
        struct thread_info *info = (void *)current_thread_info();
        int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
@@ -754,6 +756,7 @@ void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
                __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
                send_sigtrap(current, regs);
        }
+       exception_exit(prev_state);
 }
 
 
index d3c4ed780ce2244cfcab4da5068fb29442ac5786..07e3ff5cc74010170ca43f7df20acb060df2727b 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irq_work.h>
 #include <linux/module.h>
 #include <asm/cacheflush.h>
 #include <asm/homecache.h>
@@ -33,6 +34,8 @@ EXPORT_SYMBOL(smp_topology);
 static unsigned long __iomem *ipi_mappings[NR_CPUS];
 #endif
 
+/* Does messaging work correctly to the local cpu? */
+bool self_interrupt_ok;
 
 /*
  * Top-level send_IPI*() functions to send messages to other cpus.
@@ -147,6 +150,10 @@ void evaluate_message(int tag)
                generic_smp_call_function_single_interrupt();
                break;
 
+       case MSG_TAG_IRQ_WORK: /* Invoke IRQ work */
+               irq_work_run();
+               break;
+
        default:
                panic("Unknown IPI message tag %d", tag);
                break;
@@ -186,6 +193,15 @@ void flush_icache_range(unsigned long start, unsigned long end)
 EXPORT_SYMBOL(flush_icache_range);
 
 
+#ifdef CONFIG_IRQ_WORK
+void arch_irq_work_raise(void)
+{
+       if (arch_irq_work_has_interrupt())
+               send_IPI_single(smp_processor_id(), MSG_TAG_IRQ_WORK);
+}
+#endif
+
+
 /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
 static irqreturn_t handle_reschedule_ipi(int irq, void *token)
 {
@@ -203,8 +219,22 @@ static struct irqaction resched_action = {
 
 void __init ipi_init(void)
 {
+       int cpu = smp_processor_id();
+       HV_Recipient recip = { .y = cpu_y(cpu), .x = cpu_x(cpu),
+                              .state = HV_TO_BE_SENT };
+       int tag = MSG_TAG_CALL_FUNCTION_SINGLE;
+
+       /*
+        * Test if we can message ourselves for arch_irq_work_raise.
+        * This functionality is only available in the Tilera hypervisor
+        * in versions 4.3.4 and following.
+        */
+       if (hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag)) == 1)
+               self_interrupt_ok = true;
+       else
+               pr_warn("Older hypervisor: disabling fast irq_work_raise\n");
+
 #if CHIP_HAS_IPI()
-       int cpu;
        /* Map IPI trigger MMIO addresses. */
        for_each_possible_cpu(cpu) {
                HV_Coord tile;
index 7ff5afdbd3aa6f70a6384e2f24d2b38414369482..c42dce50acd81c94b26285410a9ce6e70d2e6e98 100644 (file)
@@ -108,14 +108,15 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
                   p->sp < PAGE_OFFSET && p->sp != 0) {
                if (kbt->verbose)
                        pr_err("  <%s while in user mode>\n", fault);
-       } else if (kbt->verbose) {
-               pr_err("  (odd fault: pc %#lx, sp %#lx, ex1 %#lx?)\n",
-                      p->pc, p->sp, p->ex1);
-               p = NULL;
+       } else {
+               if (kbt->verbose)
+                       pr_err("  (odd fault: pc %#lx, sp %#lx, ex1 %#lx?)\n",
+                              p->pc, p->sp, p->ex1);
+               return NULL;
        }
-       if (!kbt->profile || ((1ULL << p->faultnum) & QUEUED_INTERRUPTS) == 0)
-               return p;
-       return NULL;
+       if (kbt->profile && ((1ULL << p->faultnum) & QUEUED_INTERRUPTS) != 0)
+               return NULL;
+       return p;
 }
 
 /* Is the pc pointing to a sigreturn trampoline? */
index bf841ca517bb5eafa14d918cd47343de23e2da89..312fc134c1cb12dc610b7b8bfea3c856b9752674 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/ptrace.h>
+#include <linux/context_tracking.h>
 #include <asm/stack.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
@@ -253,6 +254,7 @@ static int do_bpt(struct pt_regs *regs)
 void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                       unsigned long reason)
 {
+       enum ctx_state prev_state = exception_enter();
        siginfo_t info = { 0 };
        int signo, code;
        unsigned long address = 0;
@@ -261,7 +263,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 
        /* Handle breakpoints, etc. */
        if (is_kernel && fault_num == INT_ILL && do_bpt(regs))
-               return;
+               goto done;
 
        /* Re-enable interrupts, if they were previously enabled. */
        if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
@@ -275,7 +277,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                const char *name;
                char buf[100];
                if (fixup_exception(regs))  /* ILL_TRANS or UNALIGN_DATA */
-                       return;
+                       goto done;
                if (fault_num >= 0 &&
                    fault_num < ARRAY_SIZE(int_name) &&
                    int_name[fault_num] != NULL)
@@ -294,7 +296,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                         fault_num, name, regs->pc, buf);
                show_regs(regs);
                do_exit(SIGKILL);  /* FIXME: implement i386 die() */
-               return;
        }
 
        switch (fault_num) {
@@ -308,7 +309,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                        pr_err("Unreadable instruction for INT_ILL: %#lx\n",
                               regs->pc);
                        do_exit(SIGKILL);
-                       return;
                }
                if (!special_ill(instr, &signo, &code)) {
                        signo = SIGILL;
@@ -319,7 +319,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
        case INT_GPV:
 #if CHIP_HAS_TILE_DMA()
                if (retry_gpv(reason))
-                       return;
+                       goto done;
 #endif
                /*FALLTHROUGH*/
        case INT_UDN_ACCESS:
@@ -346,7 +346,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                        if (!state ||
                            (void __user *)(regs->pc) != state->buffer) {
                                single_step_once(regs);
-                               return;
+                               goto done;
                        }
                }
 #endif
@@ -380,7 +380,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
 #endif
        default:
                panic("Unexpected do_trap interrupt number %d", fault_num);
-               return;
        }
 
        info.si_signo = signo;
@@ -391,6 +390,9 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
        if (signo != SIGTRAP)
                trace_unhandled_signal("trap", regs, address, signo);
        force_sig_info(signo, &info, current);
+
+done:
+       exception_exit(prev_state);
 }
 
 void kernel_double_fault(int dummy, ulong pc, ulong lr, ulong sp, ulong r52)
index 7d9a83be0aca32eb7269579cec2a59c8a77d3431..d075f92ccee04eb5e89e7acab9b38b0558521d66 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/prctl.h>
+#include <linux/context_tracking.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 #include <asm/uaccess.h>
@@ -1448,6 +1449,7 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
 
 void do_unaligned(struct pt_regs *regs, int vecnum)
 {
+       enum ctx_state prev_state = exception_enter();
        tilegx_bundle_bits __user  *pc;
        tilegx_bundle_bits bundle;
        struct thread_info *info = current_thread_info();
@@ -1487,12 +1489,11 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
                                                (int)unaligned_fixup,
                                                (unsigned long long)regs->ex1,
                                                (unsigned long long)regs->pc);
-                               return;
+                       } else {
+                               /* Not fixable. Go panic. */
+                               panic("Unalign exception in Kernel. pc=%lx",
+                                     regs->pc);
                        }
-                       /* Not fixable. Go panic. */
-                       panic("Unalign exception in Kernel. pc=%lx",
-                             regs->pc);
-                       return;
                } else {
                        /*
                         * Try to fix the exception. If we can't, panic the
@@ -1501,8 +1502,8 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
                        bundle = GX_INSN_BSWAP(
                                *((tilegx_bundle_bits *)(regs->pc)));
                        jit_bundle_gen(regs, bundle, align_ctl);
-                       return;
                }
+               goto done;
        }
 
        /*
@@ -1526,7 +1527,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
 
                trace_unhandled_signal("unaligned fixup trap", regs, 0, SIGBUS);
                force_sig_info(info.si_signo, &info, current);
-               return;
+               goto done;
        }
 
 
@@ -1543,7 +1544,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
                trace_unhandled_signal("segfault in unalign fixup", regs,
                                       (unsigned long)info.si_addr, SIGSEGV);
                force_sig_info(info.si_signo, &info, current);
-               return;
+               goto done;
        }
 
        if (!info->unalign_jit_base) {
@@ -1578,7 +1579,7 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
 
                if (IS_ERR((void __force *)user_page)) {
                        pr_err("Out of kernel pages trying do_mmap\n");
-                       return;
+                       goto done;
                }
 
                /* Save the address in the thread_info struct */
@@ -1591,6 +1592,9 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
 
        /* Generate unalign JIT */
        jit_bundle_gen(regs, GX_INSN_BSWAP(bundle), align_ctl);
+
+done:
+       exception_exit(prev_state);
 }
 
 #endif /* __tilegx__ */
index 23f044e8a7ab0e1f06c425655f1f8ecf11f9996e..f7ddae3725a4aedc686b834efe05237dd1517310 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/binfmts.h>
 #include <linux/compat.h>
 #include <linux/mman.h>
+#include <linux/file.h>
 #include <linux/elf.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -39,30 +40,34 @@ static void sim_notify_exec(const char *binary_name)
 
 static int notify_exec(struct mm_struct *mm)
 {
+       int ret = 0;
        char *buf, *path;
        struct vm_area_struct *vma;
+       struct file *exe_file;
 
        if (!sim_is_simulator())
                return 1;
 
-       if (mm->exe_file == NULL)
-               return 0;
-
-       for (vma = current->mm->mmap; ; vma = vma->vm_next) {
-               if (vma == NULL)
-                       return 0;
-               if (vma->vm_file == mm->exe_file)
-                       break;
-       }
-
        buf = (char *) __get_free_page(GFP_KERNEL);
        if (buf == NULL)
                return 0;
 
-       path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE);
-       if (IS_ERR(path)) {
-               free_page((unsigned long)buf);
-               return 0;
+       exe_file = get_mm_exe_file(mm);
+       if (exe_file == NULL)
+               goto done_free;
+
+       path = d_path(&exe_file->f_path, buf, PAGE_SIZE);
+       if (IS_ERR(path))
+               goto done_put;
+
+       down_read(&mm->mmap_sem);
+       for (vma = current->mm->mmap; ; vma = vma->vm_next) {
+               if (vma == NULL) {
+                       up_read(&mm->mmap_sem);
+                       goto done_put;
+               }
+               if (vma->vm_file == exe_file)
+                       break;
        }
 
        /*
@@ -80,14 +85,20 @@ static int notify_exec(struct mm_struct *mm)
                        __insn_mtspr(SPR_SIM_CONTROL,
                                     (SIM_CONTROL_DLOPEN
                                      | (c << _SIM_CONTROL_OPERATOR_BITS)));
-                       if (c == '\0')
+                       if (c == '\0') {
+                               ret = 1; /* success */
                                break;
+                       }
                }
        }
+       up_read(&mm->mmap_sem);
 
        sim_notify_exec(path);
+done_put:
+       fput(exe_file);
+done_free:
        free_page((unsigned long)buf);
-       return 1;
+       return ret;
 }
 
 /* Notify a running simulator, if any, that we loaded an interpreter. */
@@ -109,8 +120,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
        struct mm_struct *mm = current->mm;
        int retval = 0;
 
-       down_write(&mm->mmap_sem);
-
        /*
         * Notify the simulator that an exec just occurred.
         * If we can't find the filename of the mapping, just use
@@ -119,6 +128,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
        if (!notify_exec(mm))
                sim_notify_exec(bprm->filename);
 
+       down_write(&mm->mmap_sem);
+
        retval = setup_vdso_pages();
 
 #ifndef __tilegx__
index 0f61a73534e6d7c41ccf56ee71244f926908f6d0..e83cc999da029b469fde1f2e7f2b4d0f5a96dbb6 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <linux/kdebug.h>
+#include <linux/context_tracking.h>
 
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
@@ -702,6 +703,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
                   unsigned long address, unsigned long write)
 {
        int is_page_fault;
+       enum ctx_state prev_state = exception_enter();
 
 #ifdef CONFIG_KPROBES
        /*
@@ -711,7 +713,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
         */
        if (notify_die(DIE_PAGE_FAULT, "page fault", regs, -1,
                       regs->faultnum, SIGSEGV) == NOTIFY_STOP)
-               return;
+               goto done;
 #endif
 
 #ifdef __tilegx__
@@ -750,7 +752,6 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
                                 current->comm, current->pid, pc, address);
                        show_regs(regs);
                        do_group_exit(SIGKILL);
-                       return;
                }
        }
 #else
@@ -834,12 +835,15 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
                        async->is_fault = is_page_fault;
                        async->is_write = write;
                        async->address = address;
-                       return;
+                       goto done;
                }
        }
 #endif
 
        handle_page_fault(regs, fault_num, is_page_fault, address, write);
+
+done:
+       exception_exit(prev_state);
 }
 
 
index ace32d7d3864c480cb0e51b1694f01e1559d947f..5bd252e3fdc506a6aa393419252a94261768d400 100644 (file)
@@ -233,9 +233,12 @@ static pgprot_t __init init_pgprot(ulong address)
        if (kdata_huge)
                return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH);
 
-       /* We map the aliased pages of permanent text inaccessible. */
+       /*
+        * We map the aliased pages of permanent text so we can
+        * update them if necessary, for ftrace, etc.
+        */
        if (address < (ulong) _sinittext - CODE_DELTA)
-               return PAGE_NONE;
+               return construct_pgprot(PAGE_KERNEL, PAGE_HOME_HASH);
 
        /* We map read-only data non-coherent for performance. */
        if ((address >= (ulong) __start_rodata &&