s390/time: return with irqs disabled from psw_idle

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>
This commit is contained in:
Martin Schwidefsky 2013-08-23 14:45:58 +02:00
parent 6b169ac9b4
commit 0587d409ec
5 changed files with 4 additions and 6 deletions

View file

@ -886,13 +886,13 @@ cleanup_idle:
stm %r9,%r10,__LC_SYSTEM_TIMER stm %r9,%r10,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2) mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
# prepare return psw # 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 l %r9,24(%r11) # return from psw_idle
br %r14 br %r14
cleanup_idle_insn: cleanup_idle_insn:
.long psw_idle_lpsw + 0x80000000 .long psw_idle_lpsw + 0x80000000
cleanup_idle_wait: cleanup_idle_wait:
.long 0xfffdffff .long 0xfcfdffff
/* /*
* Integer constants * Integer constants

View file

@ -929,7 +929,7 @@ cleanup_idle:
stg %r9,__LC_SYSTEM_TIMER stg %r9,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2) mvc __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
# prepare return psw # 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 lg %r9,48(%r11) # return from psw_idle
br %r14 br %r14
cleanup_idle_insn: cleanup_idle_insn:

View file

@ -71,6 +71,7 @@ void arch_cpu_idle(void)
} }
/* Halt the cpu and keep track of cpu time accounting. */ /* Halt the cpu and keep track of cpu time accounting. */
vtime_stop_cpu(); vtime_stop_cpu();
local_irq_enable();
} }
void arch_cpu_idle_exit(void) void arch_cpu_idle_exit(void)

View file

@ -92,7 +92,6 @@ void clock_comparator_work(void)
struct clock_event_device *cd; struct clock_event_device *cd;
S390_lowcore.clock_comparator = -1ULL; S390_lowcore.clock_comparator = -1ULL;
set_clock_comparator(S390_lowcore.clock_comparator);
cd = &__get_cpu_var(comparators); cd = &__get_cpu_var(comparators);
cd->event_handler(cd); cd->event_handler(cd);
} }

View file

@ -44,7 +44,6 @@ static void __udelay_disabled(unsigned long long usecs)
do { do {
set_clock_comparator(end); set_clock_comparator(end);
vtime_stop_cpu(); vtime_stop_cpu();
local_irq_disable();
} while (get_tod_clock() < end); } while (get_tod_clock() < end);
lockdep_on(); lockdep_on();
__ctl_load(cr0, 0, 0); __ctl_load(cr0, 0, 0);
@ -64,7 +63,6 @@ static void __udelay_enabled(unsigned long long usecs)
set_clock_comparator(end); set_clock_comparator(end);
} }
vtime_stop_cpu(); vtime_stop_cpu();
local_irq_disable();
if (clock_saved) if (clock_saved)
local_tick_enable(clock_saved); local_tick_enable(clock_saved);
} while (get_tod_clock() < end); } while (get_tod_clock() < end);