Skip to content

Commit 0f689a3

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 patches from Martin Schwidefsky: "An update to the oops output with additional information about the crash. The renameat2 system call is enabled. Two patches in regard to the PTR_ERR_OR_ZERO cleanup. And a bunch of bug fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/sclp_cmd: replace PTR_RET with PTR_ERR_OR_ZERO s390/sclp: replace PTR_RET with PTR_ERR_OR_ZERO s390/sclp_vt220: Fix kernel panic due to early terminal input s390/compat: fix typo s390/uaccess: fix possible register corruption in strnlen_user_srst() s390: add 31 bit warning message s390: wire up sys_renameat2 s390: show_registers() should not map user space addresses to kernel symbols s390/mm: print control registers and page table walk on crash s390/smp: fix smp_stop_cpu() for !CONFIG_SMP s390: fix control register update
2 parents 7d38cc0 + 5896f8f commit 0f689a3

File tree

14 files changed

+223
-36
lines changed

14 files changed

+223
-36
lines changed

arch/s390/include/asm/sigp.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,23 @@
3131
#define SIGP_STATUS_INCORRECT_STATE 0x00000200UL
3232
#define SIGP_STATUS_NOT_RUNNING 0x00000400UL
3333

34+
#ifndef __ASSEMBLY__
35+
36+
static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
37+
{
38+
register unsigned int reg1 asm ("1") = parm;
39+
int cc;
40+
41+
asm volatile(
42+
" sigp %1,%2,0(%3)\n"
43+
" ipm %0\n"
44+
" srl %0,28\n"
45+
: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
46+
if (status && cc == 1)
47+
*status = reg1;
48+
return cc;
49+
}
50+
51+
#endif /* __ASSEMBLY__ */
52+
3453
#endif /* __S390_ASM_SIGP_H */

arch/s390/include/asm/smp.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#ifndef __ASM_SMP_H
88
#define __ASM_SMP_H
99

10+
#include <asm/sigp.h>
11+
1012
#ifdef CONFIG_SMP
1113

1214
#include <asm/lowcore.h>
@@ -50,9 +52,18 @@ static inline int smp_store_status(int cpu) { return 0; }
5052
static inline int smp_vcpu_scheduled(int cpu) { return 1; }
5153
static inline void smp_yield_cpu(int cpu) { }
5254
static inline void smp_yield(void) { }
53-
static inline void smp_stop_cpu(void) { }
5455
static inline void smp_fill_possible_mask(void) { }
5556

57+
static inline void smp_stop_cpu(void)
58+
{
59+
u16 pcpu = stap();
60+
61+
for (;;) {
62+
__pcpu_sigp(pcpu, SIGP_STOP, 0, NULL);
63+
cpu_relax();
64+
}
65+
}
66+
5667
#endif /* CONFIG_SMP */
5768

5869
#ifdef CONFIG_HOTPLUG_CPU

arch/s390/include/uapi/asm/unistd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@
282282
#define __NR_finit_module 344
283283
#define __NR_sched_setattr 345
284284
#define __NR_sched_getattr 346
285-
#define NR_syscalls 345
285+
#define __NR_renameat2 347
286+
#define NR_syscalls 348
286287

287288
/*
288289
* There are some system calls that are not present on 64 bit, some

arch/s390/kernel/compat_wrapper.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Compat sytem call wrappers.
2+
* Compat system call wrappers.
33
*
44
* Copyright IBM Corp. 2014
55
*/
@@ -213,3 +213,4 @@ COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, i
213213
COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
214214
COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
215215
COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
216+
COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);

arch/s390/kernel/dumpstack.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ void show_registers(struct pt_regs *regs)
144144
char *mode;
145145

146146
mode = user_mode(regs) ? "User" : "Krnl";
147-
printk("%s PSW : %p %p (%pSR)\n",
148-
mode, (void *) regs->psw.mask,
149-
(void *) regs->psw.addr,
150-
(void *) regs->psw.addr);
147+
printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
148+
if (!user_mode(regs))
149+
printk(" (%pSR)", (void *)regs->psw.addr);
150+
printk("\n");
151151
printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
152152
"P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
153153
mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),

arch/s390/kernel/ptrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void update_cr_regs(struct task_struct *task)
6464
if (task->thread.per_flags & PER_FLAG_NO_TE)
6565
cr_new &= ~(1UL << 55);
6666
if (cr_new != cr)
67-
__ctl_load(cr, 0, 0);
67+
__ctl_load(cr_new, 0, 0);
6868
/* Set or clear transaction execution TDC bits 62 and 63. */
6969
__ctl_store(cr, 2, 2);
7070
cr_new = cr & ~3UL;

arch/s390/kernel/setup.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,35 @@ void __init setup_arch(char **cmdline_p)
10271027
/* Setup zfcpdump support */
10281028
setup_zfcpdump();
10291029
}
1030+
1031+
#ifdef CONFIG_32BIT
1032+
static int no_removal_warning __initdata;
1033+
1034+
static int __init parse_no_removal_warning(char *str)
1035+
{
1036+
no_removal_warning = 1;
1037+
return 0;
1038+
}
1039+
__setup("no_removal_warning", parse_no_removal_warning);
1040+
1041+
static int __init removal_warning(void)
1042+
{
1043+
if (no_removal_warning)
1044+
return 0;
1045+
printk(KERN_ALERT "\n\n");
1046+
printk(KERN_CONT "Warning - you are using a 31 bit kernel!\n\n");
1047+
printk(KERN_CONT "We plan to remove 31 bit kernel support from the kernel sources in March 2015.\n");
1048+
printk(KERN_CONT "Currently we assume that nobody is using the 31 bit kernel on old 31 bit\n");
1049+
printk(KERN_CONT "hardware anymore. If you think that the code should not be removed and also\n");
1050+
printk(KERN_CONT "future versions of the Linux kernel should be able to run in 31 bit mode\n");
1051+
printk(KERN_CONT "please let us know. Please write to:\n");
1052+
printk(KERN_CONT "[email protected] (mail address) and/or\n");
1053+
printk(KERN_CONT "[email protected] (mailing list).\n\n");
1054+
printk(KERN_CONT "Thank you!\n\n");
1055+
printk(KERN_CONT "If this kernel runs on a 64 bit machine you may consider using a 64 bit kernel.\n");
1056+
printk(KERN_CONT "This message can be disabled with the \"no_removal_warning\" kernel parameter.\n");
1057+
schedule_timeout_uninterruptible(300 * HZ);
1058+
return 0;
1059+
}
1060+
early_initcall(removal_warning);
1061+
#endif

arch/s390/kernel/smp.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,6 @@ DEFINE_MUTEX(smp_cpu_state_mutex);
8282
/*
8383
* Signal processor helper functions.
8484
*/
85-
static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)
86-
{
87-
register unsigned int reg1 asm ("1") = parm;
88-
int cc;
89-
90-
asm volatile(
91-
" sigp %1,%2,0(%3)\n"
92-
" ipm %0\n"
93-
" srl %0,28\n"
94-
: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc");
95-
if (status && cc == 1)
96-
*status = reg1;
97-
return cc;
98-
}
99-
10085
static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
10186
{
10287
int cc;

arch/s390/kernel/syscalls.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,4 @@ SYSCALL(sys_kcmp,sys_kcmp,compat_sys_kcmp)
355355
SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
356356
SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
357357
SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
358+
SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)

arch/s390/lib/uaccess.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,6 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
338338
register unsigned long reg0 asm("0") = 0;
339339
unsigned long tmp1, tmp2;
340340

341-
if (unlikely(!size))
342-
return 0;
343-
update_primary_asce(current);
344341
asm volatile(
345342
" la %2,0(%1)\n"
346343
" la %3,0(%0,%1)\n"
@@ -359,6 +356,8 @@ static inline unsigned long strnlen_user_srst(const char __user *src,
359356

360357
unsigned long __strnlen_user(const char __user *src, unsigned long size)
361358
{
359+
if (unlikely(!size))
360+
return 0;
362361
update_primary_asce(current);
363362
return strnlen_user_srst(src, size);
364363
}

arch/s390/mm/fault.c

Lines changed: 135 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,133 @@ static inline int user_space_fault(struct pt_regs *regs)
126126
return 0;
127127
}
128128

129+
static int bad_address(void *p)
130+
{
131+
unsigned long dummy;
132+
133+
return probe_kernel_address((unsigned long *)p, dummy);
134+
}
135+
136+
#ifdef CONFIG_64BIT
137+
static void dump_pagetable(unsigned long asce, unsigned long address)
138+
{
139+
unsigned long *table = __va(asce & PAGE_MASK);
140+
141+
pr_alert("AS:%016lx ", asce);
142+
switch (asce & _ASCE_TYPE_MASK) {
143+
case _ASCE_TYPE_REGION1:
144+
table = table + ((address >> 53) & 0x7ff);
145+
if (bad_address(table))
146+
goto bad;
147+
pr_cont("R1:%016lx ", *table);
148+
if (*table & _REGION_ENTRY_INVALID)
149+
goto out;
150+
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
151+
/* fallthrough */
152+
case _ASCE_TYPE_REGION2:
153+
table = table + ((address >> 42) & 0x7ff);
154+
if (bad_address(table))
155+
goto bad;
156+
pr_cont("R2:%016lx ", *table);
157+
if (*table & _REGION_ENTRY_INVALID)
158+
goto out;
159+
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
160+
/* fallthrough */
161+
case _ASCE_TYPE_REGION3:
162+
table = table + ((address >> 31) & 0x7ff);
163+
if (bad_address(table))
164+
goto bad;
165+
pr_cont("R3:%016lx ", *table);
166+
if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
167+
goto out;
168+
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
169+
/* fallthrough */
170+
case _ASCE_TYPE_SEGMENT:
171+
table = table + ((address >> 20) & 0x7ff);
172+
if (bad_address(table))
173+
goto bad;
174+
pr_cont(KERN_CONT "S:%016lx ", *table);
175+
if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
176+
goto out;
177+
table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
178+
}
179+
table = table + ((address >> 12) & 0xff);
180+
if (bad_address(table))
181+
goto bad;
182+
pr_cont("P:%016lx ", *table);
183+
out:
184+
pr_cont("\n");
185+
return;
186+
bad:
187+
pr_cont("BAD\n");
188+
}
189+
190+
#else /* CONFIG_64BIT */
191+
192+
static void dump_pagetable(unsigned long asce, unsigned long address)
193+
{
194+
unsigned long *table = __va(asce & PAGE_MASK);
195+
196+
pr_alert("AS:%08lx ", asce);
197+
table = table + ((address >> 20) & 0x7ff);
198+
if (bad_address(table))
199+
goto bad;
200+
pr_cont("S:%08lx ", *table);
201+
if (*table & _SEGMENT_ENTRY_INVALID)
202+
goto out;
203+
table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
204+
table = table + ((address >> 12) & 0xff);
205+
if (bad_address(table))
206+
goto bad;
207+
pr_cont("P:%08lx ", *table);
208+
out:
209+
pr_cont("\n");
210+
return;
211+
bad:
212+
pr_cont("BAD\n");
213+
}
214+
215+
#endif /* CONFIG_64BIT */
216+
217+
static void dump_fault_info(struct pt_regs *regs)
218+
{
219+
unsigned long asce;
220+
221+
pr_alert("Fault in ");
222+
switch (regs->int_parm_long & 3) {
223+
case 3:
224+
pr_cont("home space ");
225+
break;
226+
case 2:
227+
pr_cont("secondary space ");
228+
break;
229+
case 1:
230+
pr_cont("access register ");
231+
break;
232+
case 0:
233+
pr_cont("primary space ");
234+
break;
235+
}
236+
pr_cont("mode while using ");
237+
if (!user_space_fault(regs)) {
238+
asce = S390_lowcore.kernel_asce;
239+
pr_cont("kernel ");
240+
}
241+
#ifdef CONFIG_PGSTE
242+
else if ((current->flags & PF_VCPU) && S390_lowcore.gmap) {
243+
struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
244+
asce = gmap->asce;
245+
pr_cont("gmap ");
246+
}
247+
#endif
248+
else {
249+
asce = S390_lowcore.user_asce;
250+
pr_cont("user ");
251+
}
252+
pr_cont("ASCE.\n");
253+
dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
254+
}
255+
129256
static inline void report_user_fault(struct pt_regs *regs, long signr)
130257
{
131258
if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
@@ -138,8 +265,9 @@ static inline void report_user_fault(struct pt_regs *regs, long signr)
138265
regs->int_code);
139266
print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
140267
printk(KERN_CONT "\n");
141-
printk(KERN_ALERT "failing address: %lX\n",
142-
regs->int_parm_long & __FAIL_ADDR_MASK);
268+
printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
269+
regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
270+
dump_fault_info(regs);
143271
show_regs(regs);
144272
}
145273

@@ -177,11 +305,13 @@ static noinline void do_no_context(struct pt_regs *regs)
177305
address = regs->int_parm_long & __FAIL_ADDR_MASK;
178306
if (!user_space_fault(regs))
179307
printk(KERN_ALERT "Unable to handle kernel pointer dereference"
180-
" at virtual kernel address %p\n", (void *)address);
308+
" in virtual kernel address space\n");
181309
else
182310
printk(KERN_ALERT "Unable to handle kernel paging request"
183-
" at virtual user address %p\n", (void *)address);
184-
311+
" in virtual user address space\n");
312+
printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
313+
regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
314+
dump_fault_info(regs);
185315
die(regs, "Oops");
186316
do_exit(SIGKILL);
187317
}

drivers/s390/char/sclp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ static __init int sclp_initcall(void)
12521252
return rc;
12531253

12541254
sclp_pdev = platform_device_register_simple("sclp", -1, NULL, 0);
1255-
rc = PTR_RET(sclp_pdev);
1255+
rc = PTR_ERR_OR_ZERO(sclp_pdev);
12561256
if (rc)
12571257
goto fail_platform_driver_unregister;
12581258

drivers/s390/char/sclp_cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ static int __init sclp_detect_standby_memory(void)
515515
if (rc)
516516
goto out;
517517
sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0);
518-
rc = PTR_RET(sclp_pdev);
518+
rc = PTR_ERR_OR_ZERO(sclp_pdev);
519519
if (rc)
520520
goto out_driver;
521521
sclp_add_standby_memory();

drivers/s390/char/sclp_vt220.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,16 @@ static void sclp_vt220_pm_event_fn(struct sclp_register *reg,
9797
static int __sclp_vt220_emit(struct sclp_vt220_request *request);
9898
static void sclp_vt220_emit_current(void);
9999

100-
/* Registration structure for our interest in SCLP event buffers */
100+
/* Registration structure for SCLP output event buffers */
101101
static struct sclp_register sclp_vt220_register = {
102102
.send_mask = EVTYP_VT220MSG_MASK,
103+
.pm_event_fn = sclp_vt220_pm_event_fn,
104+
};
105+
106+
/* Registration structure for SCLP input event buffers */
107+
static struct sclp_register sclp_vt220_register_input = {
103108
.receive_mask = EVTYP_VT220MSG_MASK,
104-
.state_change_fn = NULL,
105109
.receiver_fn = sclp_vt220_receiver_fn,
106-
.pm_event_fn = sclp_vt220_pm_event_fn,
107110
};
108111

109112

@@ -715,9 +718,14 @@ static int __init sclp_vt220_tty_init(void)
715718
rc = tty_register_driver(driver);
716719
if (rc)
717720
goto out_init;
721+
rc = sclp_register(&sclp_vt220_register_input);
722+
if (rc)
723+
goto out_reg;
718724
sclp_vt220_driver = driver;
719725
return 0;
720726

727+
out_reg:
728+
tty_unregister_driver(driver);
721729
out_init:
722730
__sclp_vt220_cleanup();
723731
out_driver:

0 commit comments

Comments
 (0)