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:
parent
6b169ac9b4
commit
0587d409ec
5 changed files with 4 additions and 6 deletions
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue