diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/dis.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 7 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 2 | ||||
-rw-r--r-- | arch/s390/kernel/ftrace.c | 38 | ||||
-rw-r--r-- | arch/s390/kernel/ipl.c | 15 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 18 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 12 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 25 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 35 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 16 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/clock_gettime.S | 11 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 27 |
15 files changed, 128 insertions, 87 deletions
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 002c70d3cb75..9ab188d67a3d 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -461,9 +461,6 @@ asmlinkage long sys32_execve(void) | |||
461 | result = rc; | 461 | result = rc; |
462 | goto out_putname; | 462 | goto out_putname; |
463 | } | 463 | } |
464 | task_lock(current); | ||
465 | current->ptrace &= ~PT_DTRACE; | ||
466 | task_unlock(current); | ||
467 | current->thread.fp_regs.fpc=0; | 464 | current->thread.fp_regs.fpc=0; |
468 | asm volatile("sfpc %0,0" : : "d" (0)); | 465 | asm volatile("sfpc %0,0" : : "d" (0)); |
469 | result = regs->gprs[2]; | 466 | result = regs->gprs[2]; |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index d2f270c995d9..db943a7ec513 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/smp_lock.h> | ||
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index f9b144049dc9..cae14c499511 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -208,9 +208,12 @@ static noinline __init void detect_machine_type(void) | |||
208 | machine_flags |= MACHINE_FLAG_KVM; | 208 | machine_flags |= MACHINE_FLAG_KVM; |
209 | else | 209 | else |
210 | machine_flags |= MACHINE_FLAG_VM; | 210 | machine_flags |= MACHINE_FLAG_VM; |
211 | |||
212 | /* Store machine flags for setting up lowcore early */ | ||
213 | S390_lowcore.machine_flags = machine_flags; | ||
211 | } | 214 | } |
212 | 215 | ||
213 | static void early_pgm_check_handler(void) | 216 | static __init void early_pgm_check_handler(void) |
214 | { | 217 | { |
215 | unsigned long addr; | 218 | unsigned long addr; |
216 | const struct exception_table_entry *fixup; | 219 | const struct exception_table_entry *fixup; |
@@ -222,7 +225,7 @@ static void early_pgm_check_handler(void) | |||
222 | S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 225 | S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; |
223 | } | 226 | } |
224 | 227 | ||
225 | void setup_lowcore_early(void) | 228 | static noinline __init void setup_lowcore_early(void) |
226 | { | 229 | { |
227 | psw_t psw; | 230 | psw_t psw; |
228 | 231 | ||
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index c4c80a22bc1f..5d40fce878a5 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -54,7 +54,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
55 | _TIF_MCCK_PENDING) | 55 | _TIF_MCCK_PENDING) |
56 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | 56 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
57 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8) | 57 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8) |
58 | 58 | ||
59 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 59 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
60 | STACK_SIZE = 1 << STACK_SHIFT | 60 | STACK_SIZE = 1 << STACK_SHIFT |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index f6618e9e15ef..3ceb53c9c493 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -57,7 +57,7 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
58 | _TIF_MCCK_PENDING) | 58 | _TIF_MCCK_PENDING) |
59 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ | 59 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
60 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8) | 60 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8) |
61 | 61 | ||
62 | #define BASED(name) name-system_call(%r13) | 62 | #define BASED(name) name-system_call(%r13) |
63 | 63 | ||
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 82ddfd3a75af..57bdcb1e3cdf 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c | |||
@@ -190,7 +190,7 @@ unsigned long prepare_ftrace_return(unsigned long ip, unsigned long parent) | |||
190 | goto out; | 190 | goto out; |
191 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | 191 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) |
192 | goto out; | 192 | goto out; |
193 | if (ftrace_push_return_trace(parent, ip, &trace.depth) == -EBUSY) | 193 | if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY) |
194 | goto out; | 194 | goto out; |
195 | trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN; | 195 | trace.func = ftrace_mcount_call_adjust(ip) & PSW_ADDR_INSN; |
196 | /* Only trace if the calling function expects to. */ | 196 | /* Only trace if the calling function expects to. */ |
@@ -220,6 +220,29 @@ struct syscall_metadata *syscall_nr_to_meta(int nr) | |||
220 | return syscalls_metadata[nr]; | 220 | return syscalls_metadata[nr]; |
221 | } | 221 | } |
222 | 222 | ||
223 | int syscall_name_to_nr(char *name) | ||
224 | { | ||
225 | int i; | ||
226 | |||
227 | if (!syscalls_metadata) | ||
228 | return -1; | ||
229 | for (i = 0; i < NR_syscalls; i++) | ||
230 | if (syscalls_metadata[i]) | ||
231 | if (!strcmp(syscalls_metadata[i]->name, name)) | ||
232 | return i; | ||
233 | return -1; | ||
234 | } | ||
235 | |||
236 | void set_syscall_enter_id(int num, int id) | ||
237 | { | ||
238 | syscalls_metadata[num]->enter_id = id; | ||
239 | } | ||
240 | |||
241 | void set_syscall_exit_id(int num, int id) | ||
242 | { | ||
243 | syscalls_metadata[num]->exit_id = id; | ||
244 | } | ||
245 | |||
223 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | 246 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) |
224 | { | 247 | { |
225 | struct syscall_metadata *start; | 248 | struct syscall_metadata *start; |
@@ -237,24 +260,19 @@ static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | |||
237 | return NULL; | 260 | return NULL; |
238 | } | 261 | } |
239 | 262 | ||
240 | void arch_init_ftrace_syscalls(void) | 263 | static int __init arch_init_ftrace_syscalls(void) |
241 | { | 264 | { |
242 | struct syscall_metadata *meta; | 265 | struct syscall_metadata *meta; |
243 | int i; | 266 | int i; |
244 | static atomic_t refs; | ||
245 | |||
246 | if (atomic_inc_return(&refs) != 1) | ||
247 | goto out; | ||
248 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls, | 267 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls, |
249 | GFP_KERNEL); | 268 | GFP_KERNEL); |
250 | if (!syscalls_metadata) | 269 | if (!syscalls_metadata) |
251 | goto out; | 270 | return -ENOMEM; |
252 | for (i = 0; i < NR_syscalls; i++) { | 271 | for (i = 0; i < NR_syscalls; i++) { |
253 | meta = find_syscall_meta((unsigned long)sys_call_table[i]); | 272 | meta = find_syscall_meta((unsigned long)sys_call_table[i]); |
254 | syscalls_metadata[i] = meta; | 273 | syscalls_metadata[i] = meta; |
255 | } | 274 | } |
256 | return; | 275 | return 0; |
257 | out: | ||
258 | atomic_dec(&refs); | ||
259 | } | 276 | } |
277 | arch_initcall(arch_init_ftrace_syscalls); | ||
260 | #endif | 278 | #endif |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index b8bf4b140065..371a2d88f4ac 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -70,6 +70,7 @@ struct shutdown_action { | |||
70 | char *name; | 70 | char *name; |
71 | void (*fn) (struct shutdown_trigger *trigger); | 71 | void (*fn) (struct shutdown_trigger *trigger); |
72 | int (*init) (void); | 72 | int (*init) (void); |
73 | int init_rc; | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | static char *ipl_type_str(enum ipl_type type) | 76 | static char *ipl_type_str(enum ipl_type type) |
@@ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, | |||
1486 | int i; | 1487 | int i; |
1487 | 1488 | ||
1488 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1489 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1489 | if (!shutdown_actions_list[i]) | ||
1490 | continue; | ||
1491 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { | 1490 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { |
1492 | trigger->action = shutdown_actions_list[i]; | 1491 | if (shutdown_actions_list[i]->init_rc) { |
1493 | return len; | 1492 | return shutdown_actions_list[i]->init_rc; |
1493 | } else { | ||
1494 | trigger->action = shutdown_actions_list[i]; | ||
1495 | return len; | ||
1496 | } | ||
1494 | } | 1497 | } |
1495 | } | 1498 | } |
1496 | return -EINVAL; | 1499 | return -EINVAL; |
@@ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void) | |||
1640 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1643 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1641 | if (!shutdown_actions_list[i]->init) | 1644 | if (!shutdown_actions_list[i]->init) |
1642 | continue; | 1645 | continue; |
1643 | if (shutdown_actions_list[i]->init()) | 1646 | shutdown_actions_list[i]->init_rc = |
1644 | shutdown_actions_list[i] = NULL; | 1647 | shutdown_actions_list[i]->init(); |
1645 | } | 1648 | } |
1646 | } | 1649 | } |
1647 | 1650 | ||
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 9bb2f6241d9f..86783efa24ee 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -154,39 +154,35 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) | |||
154 | 154 | ||
155 | static int __kprobes swap_instruction(void *aref) | 155 | static int __kprobes swap_instruction(void *aref) |
156 | { | 156 | { |
157 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
158 | unsigned long status = kcb->kprobe_status; | ||
157 | struct ins_replace_args *args = aref; | 159 | struct ins_replace_args *args = aref; |
160 | int rc; | ||
158 | 161 | ||
159 | return probe_kernel_write(args->ptr, &args->new, sizeof(args->new)); | 162 | kcb->kprobe_status = KPROBE_SWAP_INST; |
163 | rc = probe_kernel_write(args->ptr, &args->new, sizeof(args->new)); | ||
164 | kcb->kprobe_status = status; | ||
165 | return rc; | ||
160 | } | 166 | } |
161 | 167 | ||
162 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 168 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
163 | { | 169 | { |
164 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
165 | unsigned long status = kcb->kprobe_status; | ||
166 | struct ins_replace_args args; | 170 | struct ins_replace_args args; |
167 | 171 | ||
168 | args.ptr = p->addr; | 172 | args.ptr = p->addr; |
169 | args.old = p->opcode; | 173 | args.old = p->opcode; |
170 | args.new = BREAKPOINT_INSTRUCTION; | 174 | args.new = BREAKPOINT_INSTRUCTION; |
171 | |||
172 | kcb->kprobe_status = KPROBE_SWAP_INST; | ||
173 | stop_machine(swap_instruction, &args, NULL); | 175 | stop_machine(swap_instruction, &args, NULL); |
174 | kcb->kprobe_status = status; | ||
175 | } | 176 | } |
176 | 177 | ||
177 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 178 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
178 | { | 179 | { |
179 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
180 | unsigned long status = kcb->kprobe_status; | ||
181 | struct ins_replace_args args; | 180 | struct ins_replace_args args; |
182 | 181 | ||
183 | args.ptr = p->addr; | 182 | args.ptr = p->addr; |
184 | args.old = BREAKPOINT_INSTRUCTION; | 183 | args.old = BREAKPOINT_INSTRUCTION; |
185 | args.new = p->opcode; | 184 | args.new = p->opcode; |
186 | |||
187 | kcb->kprobe_status = KPROBE_SWAP_INST; | ||
188 | stop_machine(swap_instruction, &args, NULL); | 185 | stop_machine(swap_instruction, &args, NULL); |
189 | kcb->kprobe_status = status; | ||
190 | } | 186 | } |
191 | 187 | ||
192 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 188 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 355f7a30c3f1..5a43f27eec13 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -266,9 +266,6 @@ SYSCALL_DEFINE0(vfork) | |||
266 | 266 | ||
267 | asmlinkage void execve_tail(void) | 267 | asmlinkage void execve_tail(void) |
268 | { | 268 | { |
269 | task_lock(current); | ||
270 | current->ptrace &= ~PT_DTRACE; | ||
271 | task_unlock(current); | ||
272 | current->thread.fp_regs.fpc = 0; | 269 | current->thread.fp_regs.fpc = 0; |
273 | if (MACHINE_HAS_IEEE) | 270 | if (MACHINE_HAS_IEEE) |
274 | asm volatile("sfpc %0,%0" : : "d" (0)); | 271 | asm volatile("sfpc %0,%0" : : "d" (0)); |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 490b39934d65..f3ddd7ac06c5 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/smp.h> | 28 | #include <linux/smp.h> |
29 | #include <linux/smp_lock.h> | ||
30 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
31 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
32 | #include <linux/user.h> | 31 | #include <linux/user.h> |
@@ -52,6 +51,9 @@ | |||
52 | #include "compat_ptrace.h" | 51 | #include "compat_ptrace.h" |
53 | #endif | 52 | #endif |
54 | 53 | ||
54 | #define CREATE_TRACE_POINTS | ||
55 | #include <trace/events/syscalls.h> | ||
56 | |||
55 | enum s390_regset { | 57 | enum s390_regset { |
56 | REGSET_GENERAL, | 58 | REGSET_GENERAL, |
57 | REGSET_FP, | 59 | REGSET_FP, |
@@ -662,8 +664,8 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) | |||
662 | ret = -1; | 664 | ret = -1; |
663 | } | 665 | } |
664 | 666 | ||
665 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | 667 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
666 | ftrace_syscall_enter(regs); | 668 | trace_sys_enter(regs, regs->gprs[2]); |
667 | 669 | ||
668 | if (unlikely(current->audit_context)) | 670 | if (unlikely(current->audit_context)) |
669 | audit_syscall_entry(is_compat_task() ? | 671 | audit_syscall_entry(is_compat_task() ? |
@@ -680,8 +682,8 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) | |||
680 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), | 682 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), |
681 | regs->gprs[2]); | 683 | regs->gprs[2]); |
682 | 684 | ||
683 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | 685 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
684 | ftrace_syscall_exit(regs); | 686 | trace_sys_exit(regs, regs->gprs[2]); |
685 | 687 | ||
686 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 688 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
687 | tracehook_report_syscall_exit(regs, 0); | 689 | tracehook_report_syscall_exit(regs, 0); |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 9717717c6fea..cbb897bc50bd 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -154,6 +154,20 @@ static int __init condev_setup(char *str) | |||
154 | 154 | ||
155 | __setup("condev=", condev_setup); | 155 | __setup("condev=", condev_setup); |
156 | 156 | ||
157 | static void __init set_preferred_console(void) | ||
158 | { | ||
159 | if (MACHINE_IS_KVM) { | ||
160 | add_preferred_console("hvc", 0, NULL); | ||
161 | s390_virtio_console_init(); | ||
162 | return; | ||
163 | } | ||
164 | |||
165 | if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP) | ||
166 | add_preferred_console("ttyS", 0, NULL); | ||
167 | if (CONSOLE_IS_3270) | ||
168 | add_preferred_console("tty3270", 0, NULL); | ||
169 | } | ||
170 | |||
157 | static int __init conmode_setup(char *str) | 171 | static int __init conmode_setup(char *str) |
158 | { | 172 | { |
159 | #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE) | 173 | #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE) |
@@ -168,6 +182,7 @@ static int __init conmode_setup(char *str) | |||
168 | if (strncmp(str, "3270", 5) == 0) | 182 | if (strncmp(str, "3270", 5) == 0) |
169 | SET_CONSOLE_3270; | 183 | SET_CONSOLE_3270; |
170 | #endif | 184 | #endif |
185 | set_preferred_console(); | ||
171 | return 1; | 186 | return 1; |
172 | } | 187 | } |
173 | 188 | ||
@@ -780,9 +795,6 @@ static void __init setup_hwcaps(void) | |||
780 | void __init | 795 | void __init |
781 | setup_arch(char **cmdline_p) | 796 | setup_arch(char **cmdline_p) |
782 | { | 797 | { |
783 | /* set up preferred console */ | ||
784 | add_preferred_console("ttyS", 0, NULL); | ||
785 | |||
786 | /* | 798 | /* |
787 | * print what head.S has found out about the machine | 799 | * print what head.S has found out about the machine |
788 | */ | 800 | */ |
@@ -802,11 +814,9 @@ setup_arch(char **cmdline_p) | |||
802 | if (MACHINE_IS_VM) | 814 | if (MACHINE_IS_VM) |
803 | pr_info("Linux is running as a z/VM " | 815 | pr_info("Linux is running as a z/VM " |
804 | "guest operating system in 64-bit mode\n"); | 816 | "guest operating system in 64-bit mode\n"); |
805 | else if (MACHINE_IS_KVM) { | 817 | else if (MACHINE_IS_KVM) |
806 | pr_info("Linux is running under KVM in 64-bit mode\n"); | 818 | pr_info("Linux is running under KVM in 64-bit mode\n"); |
807 | add_preferred_console("hvc", 0, NULL); | 819 | else |
808 | s390_virtio_console_init(); | ||
809 | } else | ||
810 | pr_info("Linux is running natively in 64-bit mode\n"); | 820 | pr_info("Linux is running natively in 64-bit mode\n"); |
811 | #endif /* CONFIG_64BIT */ | 821 | #endif /* CONFIG_64BIT */ |
812 | 822 | ||
@@ -851,6 +861,7 @@ setup_arch(char **cmdline_p) | |||
851 | 861 | ||
852 | /* Setup default console */ | 862 | /* Setup default console */ |
853 | conmode_default(); | 863 | conmode_default(); |
864 | set_preferred_console(); | ||
854 | 865 | ||
855 | /* Setup zfcpdump support */ | 866 | /* Setup zfcpdump support */ |
856 | setup_zfcpdump(console_devno); | 867 | setup_zfcpdump(console_devno); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index fd8e3111a4e8..be2cae083406 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -687,13 +687,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
687 | #ifndef CONFIG_64BIT | 687 | #ifndef CONFIG_64BIT |
688 | if (MACHINE_HAS_IEEE) | 688 | if (MACHINE_HAS_IEEE) |
689 | lowcore->extended_save_area_addr = (u32) save_area; | 689 | lowcore->extended_save_area_addr = (u32) save_area; |
690 | #else | ||
691 | if (vdso_alloc_per_cpu(smp_processor_id(), lowcore)) | ||
692 | BUG(); | ||
693 | #endif | 690 | #endif |
694 | set_prefix((u32)(unsigned long) lowcore); | 691 | set_prefix((u32)(unsigned long) lowcore); |
695 | local_mcck_enable(); | 692 | local_mcck_enable(); |
696 | local_irq_enable(); | 693 | local_irq_enable(); |
694 | #ifdef CONFIG_64BIT | ||
695 | if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore)) | ||
696 | BUG(); | ||
697 | #endif | ||
697 | for_each_possible_cpu(cpu) | 698 | for_each_possible_cpu(cpu) |
698 | if (cpu != smp_processor_id()) | 699 | if (cpu != smp_processor_id()) |
699 | smp_create_idle(cpu); | 700 | smp_create_idle(cpu); |
@@ -856,13 +857,20 @@ static ssize_t show_idle_count(struct sys_device *dev, | |||
856 | { | 857 | { |
857 | struct s390_idle_data *idle; | 858 | struct s390_idle_data *idle; |
858 | unsigned long long idle_count; | 859 | unsigned long long idle_count; |
860 | unsigned int sequence; | ||
859 | 861 | ||
860 | idle = &per_cpu(s390_idle, dev->id); | 862 | idle = &per_cpu(s390_idle, dev->id); |
861 | spin_lock(&idle->lock); | 863 | repeat: |
864 | sequence = idle->sequence; | ||
865 | smp_rmb(); | ||
866 | if (sequence & 1) | ||
867 | goto repeat; | ||
862 | idle_count = idle->idle_count; | 868 | idle_count = idle->idle_count; |
863 | if (idle->idle_enter) | 869 | if (idle->idle_enter) |
864 | idle_count++; | 870 | idle_count++; |
865 | spin_unlock(&idle->lock); | 871 | smp_rmb(); |
872 | if (idle->sequence != sequence) | ||
873 | goto repeat; | ||
866 | return sprintf(buf, "%llu\n", idle_count); | 874 | return sprintf(buf, "%llu\n", idle_count); |
867 | } | 875 | } |
868 | static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); | 876 | static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); |
@@ -872,15 +880,22 @@ static ssize_t show_idle_time(struct sys_device *dev, | |||
872 | { | 880 | { |
873 | struct s390_idle_data *idle; | 881 | struct s390_idle_data *idle; |
874 | unsigned long long now, idle_time, idle_enter; | 882 | unsigned long long now, idle_time, idle_enter; |
883 | unsigned int sequence; | ||
875 | 884 | ||
876 | idle = &per_cpu(s390_idle, dev->id); | 885 | idle = &per_cpu(s390_idle, dev->id); |
877 | spin_lock(&idle->lock); | ||
878 | now = get_clock(); | 886 | now = get_clock(); |
887 | repeat: | ||
888 | sequence = idle->sequence; | ||
889 | smp_rmb(); | ||
890 | if (sequence & 1) | ||
891 | goto repeat; | ||
879 | idle_time = idle->idle_time; | 892 | idle_time = idle->idle_time; |
880 | idle_enter = idle->idle_enter; | 893 | idle_enter = idle->idle_enter; |
881 | if (idle_enter != 0ULL && idle_enter < now) | 894 | if (idle_enter != 0ULL && idle_enter < now) |
882 | idle_time += now - idle_enter; | 895 | idle_time += now - idle_enter; |
883 | spin_unlock(&idle->lock); | 896 | smp_rmb(); |
897 | if (idle->sequence != sequence) | ||
898 | goto repeat; | ||
884 | return sprintf(buf, "%llu\n", idle_time >> 12); | 899 | return sprintf(buf, "%llu\n", idle_time >> 12); |
885 | } | 900 | } |
886 | static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); | 901 | static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); |
@@ -908,11 +923,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
908 | case CPU_ONLINE: | 923 | case CPU_ONLINE: |
909 | case CPU_ONLINE_FROZEN: | 924 | case CPU_ONLINE_FROZEN: |
910 | idle = &per_cpu(s390_idle, cpu); | 925 | idle = &per_cpu(s390_idle, cpu); |
911 | spin_lock_irq(&idle->lock); | 926 | memset(idle, 0, sizeof(struct s390_idle_data)); |
912 | idle->idle_enter = 0; | ||
913 | idle->idle_time = 0; | ||
914 | idle->idle_count = 0; | ||
915 | spin_unlock_irq(&idle->lock); | ||
916 | if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) | 927 | if (sysfs_create_group(&s->kobj, &cpu_online_attr_group)) |
917 | return NOTIFY_BAD; | 928 | return NOTIFY_BAD; |
918 | break; | 929 | break; |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 215330a2c128..d4c8e9c47c81 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/notifier.h> | 36 | #include <linux/notifier.h> |
37 | #include <linux/clocksource.h> | 37 | #include <linux/clocksource.h> |
38 | #include <linux/clockchips.h> | 38 | #include <linux/clockchips.h> |
39 | #include <linux/bootmem.h> | ||
40 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
41 | #include <asm/delay.h> | 40 | #include <asm/delay.h> |
42 | #include <asm/s390_ext.h> | 41 | #include <asm/s390_ext.h> |
@@ -62,9 +61,6 @@ | |||
62 | 61 | ||
63 | u64 sched_clock_base_cc = -1; /* Force to data section. */ | 62 | u64 sched_clock_base_cc = -1; /* Force to data section. */ |
64 | 63 | ||
65 | static ext_int_info_t ext_int_info_cc; | ||
66 | static ext_int_info_t ext_int_etr_cc; | ||
67 | |||
68 | static DEFINE_PER_CPU(struct clock_event_device, comparators); | 64 | static DEFINE_PER_CPU(struct clock_event_device, comparators); |
69 | 65 | ||
70 | /* | 66 | /* |
@@ -255,15 +251,11 @@ void __init time_init(void) | |||
255 | stp_reset(); | 251 | stp_reset(); |
256 | 252 | ||
257 | /* request the clock comparator external interrupt */ | 253 | /* request the clock comparator external interrupt */ |
258 | if (register_early_external_interrupt(0x1004, | 254 | if (register_external_interrupt(0x1004, clock_comparator_interrupt)) |
259 | clock_comparator_interrupt, | ||
260 | &ext_int_info_cc) != 0) | ||
261 | panic("Couldn't request external interrupt 0x1004"); | 255 | panic("Couldn't request external interrupt 0x1004"); |
262 | 256 | ||
263 | /* request the timing alert external interrupt */ | 257 | /* request the timing alert external interrupt */ |
264 | if (register_early_external_interrupt(0x1406, | 258 | if (register_external_interrupt(0x1406, timing_alert_interrupt)) |
265 | timing_alert_interrupt, | ||
266 | &ext_int_etr_cc) != 0) | ||
267 | panic("Couldn't request external interrupt 0x1406"); | 259 | panic("Couldn't request external interrupt 0x1406"); |
268 | 260 | ||
269 | if (clocksource_register(&clocksource_tod) != 0) | 261 | if (clocksource_register(&clocksource_tod) != 0) |
@@ -1445,14 +1437,14 @@ static void __init stp_reset(void) | |||
1445 | { | 1437 | { |
1446 | int rc; | 1438 | int rc; |
1447 | 1439 | ||
1448 | stp_page = alloc_bootmem_pages(PAGE_SIZE); | 1440 | stp_page = (void *) get_zeroed_page(GFP_ATOMIC); |
1449 | rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); | 1441 | rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); |
1450 | if (rc == 0) | 1442 | if (rc == 0) |
1451 | set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); | 1443 | set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags); |
1452 | else if (stp_online) { | 1444 | else if (stp_online) { |
1453 | pr_warning("The real or virtual hardware system does " | 1445 | pr_warning("The real or virtual hardware system does " |
1454 | "not provide an STP interface\n"); | 1446 | "not provide an STP interface\n"); |
1455 | free_bootmem((unsigned long) stp_page, PAGE_SIZE); | 1447 | free_page((unsigned long) stp_page); |
1456 | stp_page = NULL; | 1448 | stp_page = NULL; |
1457 | stp_online = 0; | 1449 | stp_online = 0; |
1458 | } | 1450 | } |
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S index 79dbfee831ec..49106c6e6f88 100644 --- a/arch/s390/kernel/vdso64/clock_gettime.S +++ b/arch/s390/kernel/vdso64/clock_gettime.S | |||
@@ -88,10 +88,17 @@ __kernel_clock_gettime: | |||
88 | llilh %r4,0x0100 | 88 | llilh %r4,0x0100 |
89 | sar %a4,%r4 | 89 | sar %a4,%r4 |
90 | lghi %r4,0 | 90 | lghi %r4,0 |
91 | epsw %r5,0 | ||
91 | sacf 512 /* Magic ectg instruction */ | 92 | sacf 512 /* Magic ectg instruction */ |
92 | .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4 | 93 | .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4 |
93 | sacf 0 | 94 | tml %r5,0x4000 |
94 | sar %a4,%r2 | 95 | jo 11f |
96 | tml %r5,0x8000 | ||
97 | jno 10f | ||
98 | sacf 256 | ||
99 | j 11f | ||
100 | 10: sacf 0 | ||
101 | 11: sar %a4,%r2 | ||
95 | algr %r1,%r0 /* r1 = cputime as TOD value */ | 102 | algr %r1,%r0 /* r1 = cputime as TOD value */ |
96 | mghi %r1,1000 /* convert to nanoseconds */ | 103 | mghi %r1,1000 /* convert to nanoseconds */ |
97 | srlg %r1,%r1,12 /* r1 = cputime in nanosec */ | 104 | srlg %r1,%r1,12 /* r1 = cputime in nanosec */ |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index c8eb7255332b..c41bb0d416e1 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -25,13 +25,9 @@ | |||
25 | #include <asm/irq_regs.h> | 25 | #include <asm/irq_regs.h> |
26 | #include <asm/cputime.h> | 26 | #include <asm/cputime.h> |
27 | 27 | ||
28 | static ext_int_info_t ext_int_info_timer; | ||
29 | |||
30 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); | 28 | static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); |
31 | 29 | ||
32 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { | 30 | DEFINE_PER_CPU(struct s390_idle_data, s390_idle); |
33 | .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) | ||
34 | }; | ||
35 | 31 | ||
36 | static inline __u64 get_vtimer(void) | 32 | static inline __u64 get_vtimer(void) |
37 | { | 33 | { |
@@ -153,11 +149,13 @@ void vtime_start_cpu(void) | |||
153 | vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; | 149 | vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; |
154 | } | 150 | } |
155 | 151 | ||
156 | spin_lock(&idle->lock); | 152 | idle->sequence++; |
153 | smp_wmb(); | ||
157 | idle->idle_time += idle_time; | 154 | idle->idle_time += idle_time; |
158 | idle->idle_enter = 0ULL; | 155 | idle->idle_enter = 0ULL; |
159 | idle->idle_count++; | 156 | idle->idle_count++; |
160 | spin_unlock(&idle->lock); | 157 | smp_wmb(); |
158 | idle->sequence++; | ||
161 | } | 159 | } |
162 | 160 | ||
163 | void vtime_stop_cpu(void) | 161 | void vtime_stop_cpu(void) |
@@ -244,15 +242,23 @@ cputime64_t s390_get_idle_time(int cpu) | |||
244 | { | 242 | { |
245 | struct s390_idle_data *idle; | 243 | struct s390_idle_data *idle; |
246 | unsigned long long now, idle_time, idle_enter; | 244 | unsigned long long now, idle_time, idle_enter; |
245 | unsigned int sequence; | ||
247 | 246 | ||
248 | idle = &per_cpu(s390_idle, cpu); | 247 | idle = &per_cpu(s390_idle, cpu); |
249 | spin_lock(&idle->lock); | 248 | |
250 | now = get_clock(); | 249 | now = get_clock(); |
250 | repeat: | ||
251 | sequence = idle->sequence; | ||
252 | smp_rmb(); | ||
253 | if (sequence & 1) | ||
254 | goto repeat; | ||
251 | idle_time = 0; | 255 | idle_time = 0; |
252 | idle_enter = idle->idle_enter; | 256 | idle_enter = idle->idle_enter; |
253 | if (idle_enter != 0ULL && idle_enter < now) | 257 | if (idle_enter != 0ULL && idle_enter < now) |
254 | idle_time = now - idle_enter; | 258 | idle_time = now - idle_enter; |
255 | spin_unlock(&idle->lock); | 259 | smp_rmb(); |
260 | if (idle->sequence != sequence) | ||
261 | goto repeat; | ||
256 | return idle_time; | 262 | return idle_time; |
257 | } | 263 | } |
258 | 264 | ||
@@ -557,8 +563,7 @@ void init_cpu_vtimer(void) | |||
557 | void __init vtime_init(void) | 563 | void __init vtime_init(void) |
558 | { | 564 | { |
559 | /* request the cpu timer external interrupt */ | 565 | /* request the cpu timer external interrupt */ |
560 | if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt, | 566 | if (register_external_interrupt(0x1005, do_cpu_timer_interrupt)) |
561 | &ext_int_info_timer) != 0) | ||
562 | panic("Couldn't request external interrupt 0x1005"); | 567 | panic("Couldn't request external interrupt 0x1005"); |
563 | 568 | ||
564 | /* Enable cpu timer interrupts on the boot cpu. */ | 569 | /* Enable cpu timer interrupts on the boot cpu. */ |