Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755202AbbBHUpO (ORCPT ); Sun, 8 Feb 2015 15:45:14 -0500 Received: from mail-lb0-f177.google.com ([209.85.217.177]:46932 "EHLO mail-lb0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751690AbbBHUpL (ORCPT ); Sun, 8 Feb 2015 15:45:11 -0500 From: Rabin Vincent To: jesper.nilsson@axis.com Cc: linux-cris-kernel@axis.com, viro@zeniv.linux.org.uk, linux-kernel@vger.kernel.org, Rabin Vincent Subject: [PATCH 1/3] CRISv32: don't attempt syscall restart on irq exit Date: Sun, 8 Feb 2015 21:45:02 +0100 Message-Id: <1423428304-26586-1-git-send-email-rabin@rab.in> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2248 Lines: 76 r9 is used to determine whether syscall restarting must be performed or not. Unfortunately, r9 is never set to zero in the non-syscall path, and r9 is on top of that a callee-saved register which can be set to non-zero by the C functions that are called during IRQ handling. This means that if r10 (used for the syscall return value) is one of the -ERESTART* values when a hardware interrupt occurs which leads to a signal being delivered to the process, the kernel will "restart" a syscall which never occurred. This will lead to the PC being moved back by 2 on return to user space. Fix the problem by setting r9 to zero in the interrupt path. Test case (should loop forever but ends up executing the break 8 trap instruction): #include #include #include void f(int n) { register int r9 asm ("r9") = 1; register int r10 asm ("r10") = n; __asm__ __volatile__( "ba 1f \n" "nop \n" "break 8 \n" "1: ba . \n" "nop \n" : : "r" (r9), "r" (r10) : "memory"); } void handler1(int sig) { } int main(int argc, char *argv[]) { struct itimerval t1 = { .it_value = {1} }; signal(SIGALRM, handler1); setitimer(ITIMER_REAL, &t1, NULL); f(-513); /* -ERESTARTNOINTR */ return 0; } Signed-off-by: Rabin Vincent --- arch/cris/arch-v32/kernel/entry.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 2f19ac6..d4c088b 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -99,6 +99,8 @@ ret_from_kernel_thread: .type ret_from_intr,@function ret_from_intr: + moveq 0, $r9 ; not a syscall + ;; Check for resched if preemptive kernel, or if we're going back to ;; user-mode. This test matches the user_regs(regs) macro. Don't simply ;; test CCS since that doesn't necessarily reflect what mode we'll -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/