Commit 5a62b192 authored by Heiko Carstens's avatar Heiko Carstens

[S390] Convert s390 to GENERIC_CLOCKEVENTS.

This way we get rid of s390's NO_IDLE_HZ and use the generic dynticks
variant instead. In addition we get high resolution timers for free.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent d7b90689
......@@ -43,6 +43,9 @@ config GENERIC_HWEIGHT
config GENERIC_TIME
def_bool y
config GENERIC_CLOCKEVENTS
def_bool y
config GENERIC_BUG
bool
depends on BUG
......@@ -73,6 +76,8 @@ menu "Base setup"
comment "Processor type and features"
source "kernel/time/Kconfig"
config 64BIT
bool "64 bit kernel"
help
......@@ -487,25 +492,6 @@ config APPLDATA_NET_SUM
source kernel/Kconfig.hz
config NO_IDLE_HZ
bool "No HZ timer ticks in idle"
help
Switches the regular HZ timer off when the system is going idle.
This helps z/VM to detect that the Linux system is idle. VM can
then "swap-out" this guest which reduces memory usage. It also
reduces the overhead of idle systems.
The HZ timer can be switched on/off via /proc/sys/kernel/hz_timer.
hz_timer=0 means HZ timer is disabled. hz_timer=1 means HZ
timer is active.
config NO_IDLE_HZ_INIT
bool "HZ timer in idle off by default"
depends on NO_IDLE_HZ
help
The HZ timer is switched off in idle by default. That means the
HZ timer is already disabled at boot time.
config S390_HYPFS_FS
bool "s390 hypervisor file system support"
select SYS_HYPERVISOR
......
......@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/utsname.h>
#include <linux/tick.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
......@@ -167,9 +168,10 @@ static void default_idle(void)
void cpu_idle(void)
{
for (;;) {
tick_nohz_stop_sched_tick();
while (!need_resched())
default_idle();
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
......
......@@ -120,12 +120,9 @@ void do_extint(struct pt_regs *regs, unsigned short code)
old_regs = set_irq_regs(regs);
irq_enter();
s390_idle_check();
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
/**
* Make sure that the i/o interrupt did not "overtake"
* the last HZ timer interrupt.
*/
account_ticks(S390_lowcore.int_clock);
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */
clock_comparator_work();
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) {
......
......@@ -428,7 +428,7 @@ setup_lowcore(void)
lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
lc->jiffy_timer = -1LL;
lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long)
__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
......
This diff is collapsed.
......@@ -34,7 +34,7 @@ void __delay(unsigned long loops)
*/
void __udelay(unsigned long usecs)
{
u64 end, time, jiffy_timer = 0;
u64 end, time, old_cc = 0;
unsigned long flags, cr0, mask, dummy;
int irq_context;
......@@ -43,8 +43,8 @@ void __udelay(unsigned long usecs)
local_bh_disable();
local_irq_save(flags);
if (raw_irqs_disabled_flags(flags)) {
jiffy_timer = S390_lowcore.jiffy_timer;
S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
old_cc = S390_lowcore.clock_comparator;
S390_lowcore.clock_comparator = -1ULL;
__ctl_store(cr0, 0, 0);
dummy = (cr0 & 0xffff00e0) | 0x00000800;
__ctl_load(dummy , 0, 0);
......@@ -55,8 +55,8 @@ void __udelay(unsigned long usecs)
end = get_clock() + ((u64) usecs << 12);
do {
time = end < S390_lowcore.jiffy_timer ?
end : S390_lowcore.jiffy_timer;
time = end < S390_lowcore.clock_comparator ?
end : S390_lowcore.clock_comparator;
set_clock_comparator(time);
trace_hardirqs_on();
__load_psw_mask(mask);
......@@ -65,10 +65,10 @@ void __udelay(unsigned long usecs)
if (raw_irqs_disabled_flags(flags)) {
__ctl_load(cr0, 0, 0);
S390_lowcore.jiffy_timer = jiffy_timer;
S390_lowcore.clock_comparator = old_cc;
}
if (!irq_context)
_local_bh_enable();
set_clock_comparator(S390_lowcore.jiffy_timer);
set_clock_comparator(S390_lowcore.clock_comparator);
local_irq_restore(flags);
}
......@@ -651,12 +651,9 @@ do_IRQ (struct pt_regs *regs)
old_regs = set_irq_regs(regs);
irq_enter();
s390_idle_check();
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
/**
* Make sure that the i/o interrupt did not "overtake"
* the last HZ timer interrupt.
*/
account_ticks(S390_lowcore.int_clock);
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */
clock_comparator_work();
/*
* Get interrupt information from lowcore
*/
......
......@@ -32,6 +32,6 @@ typedef struct {
#define HARDIRQ_BITS 8
extern void account_ticks(u64 time);
void clock_comparator_work(void);
#endif /* __ASM_HARDIRQ_H */
......@@ -80,7 +80,6 @@
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
#define __LC_JIFFY_TIMER 0xC80
#define __LC_CURRENT 0xC90
#define __LC_INT_CLOCK 0xC98
#else /* __s390x__ */
......@@ -103,7 +102,6 @@
#define __LC_CPUID 0xD80
#define __LC_CPUADDR 0xD88
#define __LC_IPLDEV 0xDB8
#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8
#define __LC_INT_CLOCK 0xDE8
#endif /* __s390x__ */
......@@ -276,7 +274,7 @@ struct _lowcore
/* entry.S sensitive area end */
/* SMP info area: defined by DJB */
__u64 jiffy_timer; /* 0xc80 */
__u64 clock_comparator; /* 0xc80 */
__u32 ext_call_fast; /* 0xc88 */
__u32 percpu_offset; /* 0xc8c */
__u32 current_task; /* 0xc90 */
......@@ -368,7 +366,7 @@ struct _lowcore
/* entry.S sensitive area end */
/* SMP info area: defined by DJB */
__u64 jiffy_timer; /* 0xdc0 */
__u64 clock_comparator; /* 0xdc0 */
__u64 ext_call_fast; /* 0xdc8 */
__u64 percpu_offset; /* 0xdd0 */
__u64 current_task; /* 0xdd8 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment