From 4f8048ee734dab7c463574797b820c0c68c80791 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Oct 2009 15:04:09 +0100 Subject: [S390] smp: fix prefix handling of offlined cpus Offlined cpus still have valid prefix register contents. Dumpers will store the register contents of a cpu to the location where its prefix register points to. For offlined cpus the area (lowcore) has been freed and the dumper would write the uninteresting contents of the offline cpu to a memory location which might be in use by some other component and destroy valueable information. To fix this set the prefix register of offline cpus to absolute address zero again. This prevents the current dumpers to write to random memory locations. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/s390') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index c932caa5e850..c699ac538c49 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -638,6 +638,8 @@ void __cpu_die(unsigned int cpu) /* Wait until target cpu is down */ while (!cpu_stopped(cpu)) cpu_relax(); + while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy) + udelay(10); smp_free_lowcore(cpu); pr_info("Processor %d stopped\n", cpu); } -- cgit v1.2.2 From 70f5dc514c0b183ee813dc3b3983b04891fd1e7a Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Oct 2009 15:04:12 +0100 Subject: [S390] cputime: fix overflow on 31 bit systems The cputime_to_msecs / cputime_to_clock_t and cputime64_to_clock_t cause fixpoint divide exceptions if the cputime is too large. On a machine that collected 49.7 days worth of idle time reading from /proc/stat will generate oopses like this: Kernel BUG at 001b0c92 [verbose debug info unavailable] fixpoint divide exception: 0009 [#13] SMP Modules linked in: ipv6 CPU: 1 Tainted: G D 2.6.27.10 #5 Process cat (pid: 21352, task: 1fb34138, ksp: 1d2a3d98) Krnl PSW : 070c2000 801b0c92 (show_stat+0x2ca/0x68c) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 Krnl GPRS: 00000001 00001388 00000bb8 0015d2a1 00000000 00000000 000003e8 0001fd91 00000000 00000000 0000129d eecd2ff0 1cc533b9 0036f780 801b0bce 1d2a3cc0 Krnl Code: 801b0c86: f18890abf198 mvo 171(9,%r9),408(9,%r15) 801b0c8c: 98abf170 lm %r10,%r11,368(%r15) 801b0c90: 1da1 dr %r10,%r1 >801b0c92: 90abf170 stm %r10,%r11,368(%r15) 801b0c96: 98abf190 lm %r10,%r11,400(%r15) 801b0c9a: 1da1 dr %r10,%r1 801b0c9c: 90abf190 stm %r10,%r11,400(%r15) 801b0ca0: 18a3 lr %r10,%r3 Call Trace: ([<00000000001b09f4>] show_stat+0x2c/0x68c) [<000000000018dcee>] seq_read+0xb2/0x364 [<00000000001a9980>] proc_reg_read+0x68/0x98 [<00000000001705ee>] vfs_read+0x6e/0xe8 [<0000000000170732>] sys_read+0x36/0x78 [<000000000010f750>] sysc_do_restart+0x12/0x16 [<0000000077f3ad6a>] 0x77f3ad6a <4>---[ end trace 1436ea9559d3de9e ]--- Reported-by: Mike Frysinger Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/cputime.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 24b1244aadb9..f23961ada7fb 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -78,7 +78,7 @@ cputime64_to_jiffies64(cputime64_t cputime) static inline unsigned int cputime_to_msecs(const cputime_t cputime) { - return __div(cputime, 4096000); + return cputime_div(cputime, 4096000); } static inline cputime_t @@ -160,7 +160,7 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value) static inline clock_t cputime_to_clock_t(cputime_t cputime) { - return __div(cputime, 4096000000ULL / USER_HZ); + return cputime_div(cputime, 4096000000ULL / USER_HZ); } static inline cputime_t @@ -175,7 +175,7 @@ clock_t_to_cputime(unsigned long x) static inline clock_t cputime64_to_clock_t(cputime64_t cputime) { - return __div(cputime, 4096000000ULL / USER_HZ); + return cputime_div(cputime, 4096000000ULL / USER_HZ); } struct s390_idle_data { -- cgit v1.2.2 From f8501ba77d69c88a65e4ebbe03bdc65b1edb0b86 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Oct 2009 15:04:13 +0100 Subject: [S390] smp: fix sigp stop handling According to the architecture a cpu must not necessarily enter stopped state after completion of a sigp instruction with "stop" order code. So remove the BUG() statement after self sending sigp stop to avoid that it ever gets reached. Also add a sigp busy check to make sure that the order gets delivered. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ipl.c | 7 +++---- arch/s390/kernel/smp.c | 4 ++-- arch/s390/kernel/swsusp_asm64.S | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index ee57a42e6e93..4890ac6d7faa 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1595,10 +1595,9 @@ static void stop_run(struct shutdown_trigger *trigger) { if (strcmp(trigger->name, ON_PANIC_STR) == 0) disabled_wait((unsigned long) __builtin_return_address(0)); - else { - signal_processor(smp_processor_id(), sigp_stop); - for (;;); - } + while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) + cpu_relax(); + for (;;); } static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index c699ac538c49..c99c45b848e3 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -647,8 +647,8 @@ void __cpu_die(unsigned int cpu) void cpu_die(void) { idle_task_exit(); - signal_processor(smp_processor_id(), sigp_stop); - BUG(); + while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy) + cpu_relax(); for (;;); } diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 7c8653e27db6..0f4ef3b856d9 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -199,6 +199,7 @@ pgm_check_entry: brc 2,4b /* busy, try again */ 5: sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ + brc 2,5b /* busy, try again */ 6: j 6b restart_suspend: -- cgit v1.2.2 From b3dcf3de8e4d71d79235fc67b6c5def6506c27f8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Oct 2009 15:04:14 +0100 Subject: [S390] smp: fix sigp sense handling sigp sense only returns the status of a cpu if it is non zero. If the status of the sensed cpu is all zeros condition code 0 (accpeted) is set and no status bits are returned. The current code however assumes that a status was returned and tests bits in it. This means uninitalized data is accessed with random results. Worst case is that the code that checks if cpu is offline on cpu hotplug assumes that the target cpu is offline while it is still running. This leads potentially to memory corruption since resources that are still needed by the target cpu will be freed and could be resused while still in use. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 1 - arch/s390/kernel/swsusp_asm64.S | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/s390') diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index c99c45b848e3..93e52039321b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -76,7 +76,6 @@ static int cpu_stopped(int cpu) __u32 status; switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) { - case sigp_order_code_accepted: case sigp_status_stored: /* Check for stopped and check stop state */ if (status & 0x50) diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S index 0f4ef3b856d9..0c26cc1898ec 100644 --- a/arch/s390/kernel/swsusp_asm64.S +++ b/arch/s390/kernel/swsusp_asm64.S @@ -207,6 +207,7 @@ restart_suspend: llgh %r2,0(%r1) 7: sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */ + brc 8,7b /* accepted, status 0, still running */ brc 2,7b /* busy, try again */ tmll %r9,0x40 /* Test if resume CPU is stopped */ jz 7b -- cgit v1.2.2