aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-01 04:57:57 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-09 03:14:03 -0400
commitb5f87f15e20092c060f465b283b07a76af7f2e5f (patch)
treef6a7b227a09ce5fd47e28113e0f48208654dd82c /arch/s390
parentfe0f49768d807a8fe6336b097feb8c4441951710 (diff)
s390/idle: consolidate idle functions and definitions
Move the C functions and definitions related to the idle state handling to arch/s390/include/asm/idle.h and arch/s390/kernel/idle.c. The function s390_get_idle_time is renamed to arch_cpu_idle_time and vtime_stop_cpu to enabled_wait. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/cputime.h18
-rw-r--r--arch/s390/include/asm/idle.h26
-rw-r--r--arch/s390/include/asm/processor.h7
-rw-r--r--arch/s390/include/asm/vtimer.h2
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/entry.h2
-rw-r--r--arch/s390/kernel/idle.c124
-rw-r--r--arch/s390/kernel/process.c24
-rw-r--r--arch/s390/kernel/smp.c39
-rw-r--r--arch/s390/kernel/vtime.c60
-rw-r--r--arch/s390/lib/delay.c4
12 files changed, 166 insertions, 144 deletions
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 01887b1fade5..1c016a5fa97e 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -8,8 +8,6 @@
8#define _S390_CPUTIME_H 8#define _S390_CPUTIME_H
9 9
10#include <linux/types.h> 10#include <linux/types.h>
11#include <linux/percpu.h>
12#include <linux/spinlock.h>
13#include <asm/div64.h> 11#include <asm/div64.h>
14 12
15 13
@@ -165,20 +163,8 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime)
165 return clock; 163 return clock;
166} 164}
167 165
168struct s390_idle_data { 166cputime64_t arch_cpu_idle_time(int cpu);
169 unsigned int sequence;
170 unsigned long long idle_count;
171 unsigned long long idle_time;
172 unsigned long long clock_idle_enter;
173 unsigned long long clock_idle_exit;
174 unsigned long long timer_idle_enter;
175 unsigned long long timer_idle_exit;
176};
177 167
178DECLARE_PER_CPU(struct s390_idle_data, s390_idle); 168#define arch_idle_time(cpu) arch_cpu_idle_time(cpu)
179
180cputime64_t s390_get_idle_time(int cpu);
181
182#define arch_idle_time(cpu) s390_get_idle_time(cpu)
183 169
184#endif /* _S390_CPUTIME_H */ 170#endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/idle.h b/arch/s390/include/asm/idle.h
new file mode 100644
index 000000000000..6af037f574b8
--- /dev/null
+++ b/arch/s390/include/asm/idle.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright IBM Corp. 2014
3 *
4 * Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
5 */
6
7#ifndef _S390_IDLE_H
8#define _S390_IDLE_H
9
10#include <linux/types.h>
11#include <linux/device.h>
12
13struct s390_idle_data {
14 unsigned int sequence;
15 unsigned long long idle_count;
16 unsigned long long idle_time;
17 unsigned long long clock_idle_enter;
18 unsigned long long clock_idle_exit;
19 unsigned long long timer_idle_enter;
20 unsigned long long timer_idle_exit;
21};
22
23extern struct device_attribute dev_attr_idle_count;
24extern struct device_attribute dev_attr_idle_time_us;
25
26#endif /* _S390_IDLE_H */
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index bc796d73129b..3d0871058306 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -289,7 +289,12 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
289 return (psw.addr - ilc) & mask; 289 return (psw.addr - ilc) & mask;
290#endif 290#endif
291} 291}
292 292
293/*
294 * Function to stop a processor until the next interrupt occurs
295 */
296void enabled_wait(void);
297
293/* 298/*
294 * Function to drop a processor into disabled wait state 299 * Function to drop a processor into disabled wait state
295 */ 300 */
diff --git a/arch/s390/include/asm/vtimer.h b/arch/s390/include/asm/vtimer.h
index bfe25d513ad2..10a179af62d8 100644
--- a/arch/s390/include/asm/vtimer.h
+++ b/arch/s390/include/asm/vtimer.h
@@ -28,6 +28,4 @@ extern int del_virt_timer(struct vtimer_list *timer);
28extern void init_cpu_vtimer(void); 28extern void init_cpu_vtimer(void);
29extern void vtime_init(void); 29extern void vtime_init(void);
30 30
31extern void vtime_stop_cpu(void);
32
33#endif /* _ASM_S390_TIMER_H */ 31#endif /* _ASM_S390_TIMER_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 3249e1f36d55..c249785669f3 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -28,7 +28,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
28 28
29CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w 29CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
30 30
31obj-y := traps.o time.o process.o base.o early.o setup.o vtime.o 31obj-y := traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
32obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o 32obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
33obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o 33obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
34obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o 34obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 3e9e479d9b49..ef279a136801 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -9,7 +9,7 @@
9#include <linux/kbuild.h> 9#include <linux/kbuild.h>
10#include <linux/kvm_host.h> 10#include <linux/kvm_host.h>
11#include <linux/sched.h> 11#include <linux/sched.h>
12#include <asm/cputime.h> 12#include <asm/idle.h>
13#include <asm/vdso.h> 13#include <asm/vdso.h>
14#include <asm/pgtable.h> 14#include <asm/pgtable.h>
15 15
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 58541633b8d6..cd68869f9504 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -4,7 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/signal.h> 5#include <linux/signal.h>
6#include <asm/ptrace.h> 6#include <asm/ptrace.h>
7#include <asm/cputime.h> 7#include <asm/idle.h>
8 8
9extern void *restart_stack; 9extern void *restart_stack;
10extern unsigned long suspend_zero_pages; 10extern unsigned long suspend_zero_pages;
diff --git a/arch/s390/kernel/idle.c b/arch/s390/kernel/idle.c
new file mode 100644
index 000000000000..c846aee7372f
--- /dev/null
+++ b/arch/s390/kernel/idle.c
@@ -0,0 +1,124 @@
1/*
2 * Idle functions for s390.
3 *
4 * Copyright IBM Corp. 2014
5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8
9#include <linux/kernel.h>
10#include <linux/kernel_stat.h>
11#include <linux/kprobes.h>
12#include <linux/notifier.h>
13#include <linux/init.h>
14#include <linux/cpu.h>
15#include <asm/cputime.h>
16#include <asm/nmi.h>
17#include <asm/smp.h>
18#include "entry.h"
19
20static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
21
22void __kprobes enabled_wait(void)
23{
24 struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
25 unsigned long long idle_time;
26 unsigned long psw_mask;
27
28 trace_hardirqs_on();
29
30 /* Wait for external, I/O or machine check interrupt. */
31 psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
32 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
33 clear_cpu_flag(CIF_NOHZ_DELAY);
34
35 /* Call the assembler magic in entry.S */
36 psw_idle(idle, psw_mask);
37
38 /* Account time spent with enabled wait psw loaded as idle time. */
39 idle->sequence++;
40 smp_wmb();
41 idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
42 idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
43 idle->idle_time += idle_time;
44 idle->idle_count++;
45 account_idle_time(idle_time);
46 smp_wmb();
47 idle->sequence++;
48}
49
50static ssize_t show_idle_count(struct device *dev,
51 struct device_attribute *attr, char *buf)
52{
53 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
54 unsigned long long idle_count;
55 unsigned int sequence;
56
57 do {
58 sequence = ACCESS_ONCE(idle->sequence);
59 idle_count = ACCESS_ONCE(idle->idle_count);
60 if (ACCESS_ONCE(idle->clock_idle_enter))
61 idle_count++;
62 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
63 return sprintf(buf, "%llu\n", idle_count);
64}
65DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
66
67static ssize_t show_idle_time(struct device *dev,
68 struct device_attribute *attr, char *buf)
69{
70 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
71 unsigned long long now, idle_time, idle_enter, idle_exit;
72 unsigned int sequence;
73
74 do {
75 now = get_tod_clock();
76 sequence = ACCESS_ONCE(idle->sequence);
77 idle_time = ACCESS_ONCE(idle->idle_time);
78 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
79 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
80 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
81 idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
82 return sprintf(buf, "%llu\n", idle_time >> 12);
83}
84DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
85
86cputime64_t arch_cpu_idle_time(int cpu)
87{
88 struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
89 unsigned long long now, idle_enter, idle_exit;
90 unsigned int sequence;
91
92 do {
93 now = get_tod_clock();
94 sequence = ACCESS_ONCE(idle->sequence);
95 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
96 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
97 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
98 return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
99}
100
101void arch_cpu_idle_enter(void)
102{
103 local_mcck_disable();
104}
105
106void arch_cpu_idle(void)
107{
108 if (!test_cpu_flag(CIF_MCCK_PENDING))
109 /* Halt the cpu and keep track of cpu time accounting. */
110 enabled_wait();
111 local_irq_enable();
112}
113
114void arch_cpu_idle_exit(void)
115{
116 local_mcck_enable();
117 if (test_cpu_flag(CIF_MCCK_PENDING))
118 s390_handle_mcck();
119}
120
121void arch_cpu_idle_dead(void)
122{
123 cpu_die();
124}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 93b9ca42e5c0..ed84cc224899 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -61,30 +61,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
61 return sf->gprs[8]; 61 return sf->gprs[8];
62} 62}
63 63
64void arch_cpu_idle(void)
65{
66 local_mcck_disable();
67 if (test_cpu_flag(CIF_MCCK_PENDING)) {
68 local_mcck_enable();
69 local_irq_enable();
70 return;
71 }
72 /* Halt the cpu and keep track of cpu time accounting. */
73 vtime_stop_cpu();
74 local_irq_enable();
75}
76
77void arch_cpu_idle_exit(void)
78{
79 if (test_cpu_flag(CIF_MCCK_PENDING))
80 s390_handle_mcck();
81}
82
83void arch_cpu_idle_dead(void)
84{
85 cpu_die();
86}
87
88extern void __kprobes kernel_thread_starter(void); 64extern void __kprobes kernel_thread_starter(void);
89 65
90/* 66/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 46317d6951c4..bba0e2469254 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -45,6 +45,7 @@
45#include <asm/debug.h> 45#include <asm/debug.h>
46#include <asm/os_info.h> 46#include <asm/os_info.h>
47#include <asm/sigp.h> 47#include <asm/sigp.h>
48#include <asm/idle.h>
48#include "entry.h" 49#include "entry.h"
49 50
50enum { 51enum {
@@ -661,7 +662,7 @@ static void smp_start_secondary(void *cpuvoid)
661 cpu_init(); 662 cpu_init();
662 preempt_disable(); 663 preempt_disable();
663 init_cpu_timer(); 664 init_cpu_timer();
664 init_cpu_vtimer(); 665 vtime_init();
665 pfault_init(); 666 pfault_init();
666 notify_cpu_starting(smp_processor_id()); 667 notify_cpu_starting(smp_processor_id());
667 set_cpu_online(smp_processor_id(), true); 668 set_cpu_online(smp_processor_id(), true);
@@ -893,42 +894,6 @@ static struct attribute_group cpu_common_attr_group = {
893 .attrs = cpu_common_attrs, 894 .attrs = cpu_common_attrs,
894}; 895};
895 896
896static ssize_t show_idle_count(struct device *dev,
897 struct device_attribute *attr, char *buf)
898{
899 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
900 unsigned long long idle_count;
901 unsigned int sequence;
902
903 do {
904 sequence = ACCESS_ONCE(idle->sequence);
905 idle_count = ACCESS_ONCE(idle->idle_count);
906 if (ACCESS_ONCE(idle->clock_idle_enter))
907 idle_count++;
908 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
909 return sprintf(buf, "%llu\n", idle_count);
910}
911static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
912
913static ssize_t show_idle_time(struct device *dev,
914 struct device_attribute *attr, char *buf)
915{
916 struct s390_idle_data *idle = &per_cpu(s390_idle, dev->id);
917 unsigned long long now, idle_time, idle_enter, idle_exit;
918 unsigned int sequence;
919
920 do {
921 now = get_tod_clock();
922 sequence = ACCESS_ONCE(idle->sequence);
923 idle_time = ACCESS_ONCE(idle->idle_time);
924 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
925 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
926 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
927 idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
928 return sprintf(buf, "%llu\n", idle_time >> 12);
929}
930static DEVICE_ATTR(idle_time_us, 0444, show_idle_time, NULL);
931
932static struct attribute *cpu_online_attrs[] = { 897static struct attribute *cpu_online_attrs[] = {
933 &dev_attr_idle_count.attr, 898 &dev_attr_idle_count.attr,
934 &dev_attr_idle_time_us.attr, 899 &dev_attr_idle_time_us.attr,
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 40709821abde..416f2a323ba5 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -6,27 +6,18 @@
6 */ 6 */
7 7
8#include <linux/kernel_stat.h> 8#include <linux/kernel_stat.h>
9#include <linux/notifier.h>
10#include <linux/kprobes.h>
11#include <linux/export.h> 9#include <linux/export.h>
12#include <linux/kernel.h> 10#include <linux/kernel.h>
13#include <linux/timex.h> 11#include <linux/timex.h>
14#include <linux/types.h> 12#include <linux/types.h>
15#include <linux/time.h> 13#include <linux/time.h>
16#include <linux/cpu.h>
17#include <linux/smp.h>
18 14
19#include <asm/irq_regs.h>
20#include <asm/cputime.h> 15#include <asm/cputime.h>
21#include <asm/vtimer.h> 16#include <asm/vtimer.h>
22#include <asm/vtime.h> 17#include <asm/vtime.h>
23#include <asm/irq.h>
24#include "entry.h"
25 18
26static void virt_timer_expire(void); 19static void virt_timer_expire(void);
27 20
28DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
29
30static LIST_HEAD(virt_timer_list); 21static LIST_HEAD(virt_timer_list);
31static DEFINE_SPINLOCK(virt_timer_lock); 22static DEFINE_SPINLOCK(virt_timer_lock);
32static atomic64_t virt_timer_current; 23static atomic64_t virt_timer_current;
@@ -152,49 +143,6 @@ void vtime_account_system(struct task_struct *tsk)
152__attribute__((alias("vtime_account_irq_enter"))); 143__attribute__((alias("vtime_account_irq_enter")));
153EXPORT_SYMBOL_GPL(vtime_account_system); 144EXPORT_SYMBOL_GPL(vtime_account_system);
154 145
155void __kprobes vtime_stop_cpu(void)
156{
157 struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
158 unsigned long long idle_time;
159 unsigned long psw_mask;
160
161 trace_hardirqs_on();
162
163 /* Wait for external, I/O or machine check interrupt. */
164 psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
165 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
166 clear_cpu_flag(CIF_NOHZ_DELAY);
167
168 /* Call the assembler magic in entry.S */
169 psw_idle(idle, psw_mask);
170
171 /* Account time spent with enabled wait psw loaded as idle time. */
172 idle->sequence++;
173 smp_wmb();
174 idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
175 idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
176 idle->idle_time += idle_time;
177 idle->idle_count++;
178 account_idle_time(idle_time);
179 smp_wmb();
180 idle->sequence++;
181}
182
183cputime64_t s390_get_idle_time(int cpu)
184{
185 struct s390_idle_data *idle = &per_cpu(s390_idle, cpu);
186 unsigned long long now, idle_enter, idle_exit;
187 unsigned int sequence;
188
189 do {
190 now = get_tod_clock();
191 sequence = ACCESS_ONCE(idle->sequence);
192 idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
193 idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
194 } while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
195 return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
196}
197
198/* 146/*
199 * Sorted add to a list. List is linear searched until first bigger 147 * Sorted add to a list. List is linear searched until first bigger
200 * element is found. 148 * element is found.
@@ -372,14 +320,8 @@ EXPORT_SYMBOL(del_virt_timer);
372/* 320/*
373 * Start the virtual CPU timer on the current CPU. 321 * Start the virtual CPU timer on the current CPU.
374 */ 322 */
375void init_cpu_vtimer(void) 323void vtime_init(void)
376{ 324{
377 /* set initial cpu timer */ 325 /* set initial cpu timer */
378 set_vtimer(VTIMER_MAX_SLICE); 326 set_vtimer(VTIMER_MAX_SLICE);
379} 327}
380
381void __init vtime_init(void)
382{
383 /* Enable cpu timer interrupts on the boot cpu. */
384 init_cpu_vtimer();
385}
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index a9f3d0042d58..16dc42d83f93 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -43,7 +43,7 @@ static void __udelay_disabled(unsigned long long usecs)
43 lockdep_off(); 43 lockdep_off();
44 do { 44 do {
45 set_clock_comparator(end); 45 set_clock_comparator(end);
46 vtime_stop_cpu(); 46 enabled_wait();
47 } while (get_tod_clock_fast() < end); 47 } while (get_tod_clock_fast() < end);
48 lockdep_on(); 48 lockdep_on();
49 __ctl_load(cr0, 0, 0); 49 __ctl_load(cr0, 0, 0);
@@ -62,7 +62,7 @@ static void __udelay_enabled(unsigned long long usecs)
62 clock_saved = local_tick_disable(); 62 clock_saved = local_tick_disable();
63 set_clock_comparator(end); 63 set_clock_comparator(end);
64 } 64 }
65 vtime_stop_cpu(); 65 enabled_wait();
66 if (clock_saved) 66 if (clock_saved)
67 local_tick_enable(clock_saved); 67 local_tick_enable(clock_saved);
68 } while (get_tod_clock_fast() < end); 68 } while (get_tod_clock_fast() < end);