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 ...@@ -43,6 +43,9 @@ config GENERIC_HWEIGHT
config GENERIC_TIME config GENERIC_TIME
def_bool y def_bool y
config GENERIC_CLOCKEVENTS
def_bool y
config GENERIC_BUG config GENERIC_BUG
bool bool
depends on BUG depends on BUG
...@@ -73,6 +76,8 @@ menu "Base setup" ...@@ -73,6 +76,8 @@ menu "Base setup"
comment "Processor type and features" comment "Processor type and features"
source "kernel/time/Kconfig"
config 64BIT config 64BIT
bool "64 bit kernel" bool "64 bit kernel"
help help
...@@ -487,25 +492,6 @@ config APPLDATA_NET_SUM ...@@ -487,25 +492,6 @@ config APPLDATA_NET_SUM
source kernel/Kconfig.hz 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 config S390_HYPFS_FS
bool "s390 hypervisor file system support" bool "s390 hypervisor file system support"
select SYS_HYPERVISOR select SYS_HYPERVISOR
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/tick.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -167,9 +168,10 @@ static void default_idle(void) ...@@ -167,9 +168,10 @@ static void default_idle(void)
void cpu_idle(void) void cpu_idle(void)
{ {
for (;;) { for (;;) {
tick_nohz_stop_sched_tick();
while (!need_resched()) while (!need_resched())
default_idle(); default_idle();
tick_nohz_restart_sched_tick();
preempt_enable_no_resched(); preempt_enable_no_resched();
schedule(); schedule();
preempt_disable(); preempt_disable();
......
...@@ -120,12 +120,9 @@ void do_extint(struct pt_regs *regs, unsigned short code) ...@@ -120,12 +120,9 @@ void do_extint(struct pt_regs *regs, unsigned short code)
old_regs = set_irq_regs(regs); old_regs = set_irq_regs(regs);
irq_enter(); irq_enter();
s390_idle_check(); s390_idle_check();
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer) if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/** /* Serve timer interrupts first. */
* Make sure that the i/o interrupt did not "overtake" clock_comparator_work();
* the last HZ timer interrupt.
*/
account_ticks(S390_lowcore.int_clock);
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
index = ext_hash(code); index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) { for (p = ext_int_hash[index]; p; p = p->next) {
......
...@@ -428,7 +428,7 @@ setup_lowcore(void) ...@@ -428,7 +428,7 @@ setup_lowcore(void)
lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.mask = psw_kernel_bits;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device; 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->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long) lc->async_stack = (unsigned long)
__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
......
This diff is collapsed.
...@@ -34,7 +34,7 @@ void __delay(unsigned long loops) ...@@ -34,7 +34,7 @@ void __delay(unsigned long loops)
*/ */
void __udelay(unsigned long usecs) void __udelay(unsigned long usecs)
{ {
u64 end, time, jiffy_timer = 0; u64 end, time, old_cc = 0;
unsigned long flags, cr0, mask, dummy; unsigned long flags, cr0, mask, dummy;
int irq_context; int irq_context;
...@@ -43,8 +43,8 @@ void __udelay(unsigned long usecs) ...@@ -43,8 +43,8 @@ void __udelay(unsigned long usecs)
local_bh_disable(); local_bh_disable();
local_irq_save(flags); local_irq_save(flags);
if (raw_irqs_disabled_flags(flags)) { if (raw_irqs_disabled_flags(flags)) {
jiffy_timer = S390_lowcore.jiffy_timer; old_cc = S390_lowcore.clock_comparator;
S390_lowcore.jiffy_timer = -1ULL - (4096 << 12); S390_lowcore.clock_comparator = -1ULL;
__ctl_store(cr0, 0, 0); __ctl_store(cr0, 0, 0);
dummy = (cr0 & 0xffff00e0) | 0x00000800; dummy = (cr0 & 0xffff00e0) | 0x00000800;
__ctl_load(dummy , 0, 0); __ctl_load(dummy , 0, 0);
...@@ -55,8 +55,8 @@ void __udelay(unsigned long usecs) ...@@ -55,8 +55,8 @@ void __udelay(unsigned long usecs)
end = get_clock() + ((u64) usecs << 12); end = get_clock() + ((u64) usecs << 12);
do { do {
time = end < S390_lowcore.jiffy_timer ? time = end < S390_lowcore.clock_comparator ?
end : S390_lowcore.jiffy_timer; end : S390_lowcore.clock_comparator;
set_clock_comparator(time); set_clock_comparator(time);
trace_hardirqs_on(); trace_hardirqs_on();
__load_psw_mask(mask); __load_psw_mask(mask);
...@@ -65,10 +65,10 @@ void __udelay(unsigned long usecs) ...@@ -65,10 +65,10 @@ void __udelay(unsigned long usecs)
if (raw_irqs_disabled_flags(flags)) { if (raw_irqs_disabled_flags(flags)) {
__ctl_load(cr0, 0, 0); __ctl_load(cr0, 0, 0);
S390_lowcore.jiffy_timer = jiffy_timer; S390_lowcore.clock_comparator = old_cc;
} }
if (!irq_context) if (!irq_context)
_local_bh_enable(); _local_bh_enable();
set_clock_comparator(S390_lowcore.jiffy_timer); set_clock_comparator(S390_lowcore.clock_comparator);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -651,12 +651,9 @@ do_IRQ (struct pt_regs *regs) ...@@ -651,12 +651,9 @@ do_IRQ (struct pt_regs *regs)
old_regs = set_irq_regs(regs); old_regs = set_irq_regs(regs);
irq_enter(); irq_enter();
s390_idle_check(); s390_idle_check();
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer) if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/** /* Serve timer interrupts first. */
* Make sure that the i/o interrupt did not "overtake" clock_comparator_work();
* the last HZ timer interrupt.
*/
account_ticks(S390_lowcore.int_clock);
/* /*
* Get interrupt information from lowcore * Get interrupt information from lowcore
*/ */
......
...@@ -32,6 +32,6 @@ typedef struct { ...@@ -32,6 +32,6 @@ typedef struct {
#define HARDIRQ_BITS 8 #define HARDIRQ_BITS 8
extern void account_ticks(u64 time); void clock_comparator_work(void);
#endif /* __ASM_HARDIRQ_H */ #endif /* __ASM_HARDIRQ_H */
...@@ -80,7 +80,6 @@ ...@@ -80,7 +80,6 @@
#define __LC_CPUID 0xC60 #define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68 #define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C #define __LC_IPLDEV 0xC7C
#define __LC_JIFFY_TIMER 0xC80
#define __LC_CURRENT 0xC90 #define __LC_CURRENT 0xC90
#define __LC_INT_CLOCK 0xC98 #define __LC_INT_CLOCK 0xC98
#else /* __s390x__ */ #else /* __s390x__ */
...@@ -103,7 +102,6 @@ ...@@ -103,7 +102,6 @@
#define __LC_CPUID 0xD80 #define __LC_CPUID 0xD80
#define __LC_CPUADDR 0xD88 #define __LC_CPUADDR 0xD88
#define __LC_IPLDEV 0xDB8 #define __LC_IPLDEV 0xDB8
#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8 #define __LC_CURRENT 0xDD8
#define __LC_INT_CLOCK 0xDE8 #define __LC_INT_CLOCK 0xDE8
#endif /* __s390x__ */ #endif /* __s390x__ */
...@@ -276,7 +274,7 @@ struct _lowcore ...@@ -276,7 +274,7 @@ struct _lowcore
/* entry.S sensitive area end */ /* entry.S sensitive area end */
/* SMP info area: defined by DJB */ /* SMP info area: defined by DJB */
__u64 jiffy_timer; /* 0xc80 */ __u64 clock_comparator; /* 0xc80 */
__u32 ext_call_fast; /* 0xc88 */ __u32 ext_call_fast; /* 0xc88 */
__u32 percpu_offset; /* 0xc8c */ __u32 percpu_offset; /* 0xc8c */
__u32 current_task; /* 0xc90 */ __u32 current_task; /* 0xc90 */
...@@ -368,7 +366,7 @@ struct _lowcore ...@@ -368,7 +366,7 @@ struct _lowcore
/* entry.S sensitive area end */ /* entry.S sensitive area end */
/* SMP info area: defined by DJB */ /* SMP info area: defined by DJB */
__u64 jiffy_timer; /* 0xdc0 */ __u64 clock_comparator; /* 0xdc0 */
__u64 ext_call_fast; /* 0xdc8 */ __u64 ext_call_fast; /* 0xdc8 */
__u64 percpu_offset; /* 0xdd0 */ __u64 percpu_offset; /* 0xdd0 */
__u64 current_task; /* 0xdd8 */ __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