s390/time: return with irqs disabled from psw_idle
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 23 Aug 2013 12:45:58 +0000 (14:45 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 28 Aug 2013 07:19:23 +0000 (09:19 +0200)
Modify the psw_idle waiting logic in entry[64].S to return with
interrupts disabled. This avoids potential issues with udelay
and interrupt loops as interrupts are not reenabled after
clock comparator interrupts.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/process.c
arch/s390/kernel/time.c
arch/s390/lib/delay.c

index 5ca70b4..cc30d1f 100644 (file)
@@ -886,13 +886,13 @@ cleanup_idle:
        stm     %r9,%r10,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
        # prepare return psw
-       n       %r8,BASED(cleanup_idle_wait)    # clear wait state bit
+       n       %r8,BASED(cleanup_idle_wait)    # clear irq & wait state bits
        l       %r9,24(%r11)                    # return from psw_idle
        br      %r14
 cleanup_idle_insn:
        .long   psw_idle_lpsw + 0x80000000
 cleanup_idle_wait:
-       .long   0xfffdffff
+       .long   0xfcfdffff
 
 /*
  * Integer constants
index 980c7aa..2b2188b 100644 (file)
@@ -929,7 +929,7 @@ cleanup_idle:
        stg     %r9,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
        # prepare return psw
-       nihh    %r8,0xfffd              # clear wait state bit
+       nihh    %r8,0xfcfd              # clear irq & wait state bits
        lg      %r9,48(%r11)            # return from psw_idle
        br      %r14
 cleanup_idle_insn:
index 2bc3edd..c5dbb33 100644 (file)
@@ -71,6 +71,7 @@ void arch_cpu_idle(void)
        }
        /* Halt the cpu and keep track of cpu time accounting. */
        vtime_stop_cpu();
+       local_irq_enable();
 }
 
 void arch_cpu_idle_exit(void)
index 876546b..064c308 100644 (file)
@@ -92,7 +92,6 @@ void clock_comparator_work(void)
        struct clock_event_device *cd;
 
        S390_lowcore.clock_comparator = -1ULL;
-       set_clock_comparator(S390_lowcore.clock_comparator);
        cd = &__get_cpu_var(comparators);
        cd->event_handler(cd);
 }
index c61b9fa..57c87d7 100644 (file)
@@ -44,7 +44,6 @@ static void __udelay_disabled(unsigned long long usecs)
        do {
                set_clock_comparator(end);
                vtime_stop_cpu();
-               local_irq_disable();
        } while (get_tod_clock() < end);
        lockdep_on();
        __ctl_load(cr0, 0, 0);
@@ -64,7 +63,6 @@ static void __udelay_enabled(unsigned long long usecs)
                        set_clock_comparator(end);
                }
                vtime_stop_cpu();
-               local_irq_disable();
                if (clock_saved)
                        local_tick_enable(clock_saved);
        } while (get_tod_clock() < end);