Commit 1566feea authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-5.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Vasily Gorbik:

 - a few ptrace fixes mostly for strace and seccomp_bpf kernel tests
   findings

 - cleanup unused pm callbacks in virtio ccw

 - replace kmalloc + memset with kzalloc in crypto

 - use $(LD) for vDSO linkage to make clang happy

 - fix vDSO clock_getres() to preserve the same behaviour as
   posix_get_hrtimer_res()

 - fix workqueue cpumask warning when NUMA=n and nr_node_ids=2

 - reduce SLSB writes during input processing, improve warnings and
   cleanup qdio_data usage in qdio

 - a few fixes to use scnprintf() instead of snprintf()

* tag 's390-5.8-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390: fix syscall_get_error for compat processes
  s390/qdio: warn about unexpected SLSB states
  s390/qdio: clean up usage of qdio_data
  s390/numa: let NODES_SHIFT depend on NEED_MULTIPLE_NODES
  s390/vdso: fix vDSO clock_getres()
  s390/vdso: Use $(LD) instead of $(CC) to link vDSO
  s390/protvirt: use scnprintf() instead of snprintf()
  s390: use scnprintf() in sys_##_prefix##_##_name##_show
  s390/crypto: use scnprintf() instead of snprintf()
  s390/zcrypt: use kzalloc
  s390/virtio: remove unused pm callbacks
  s390/qdio: reduce SLSB writes during Input Queue processing
  selftests/seccomp: s390 shares the syscall and return value register
  s390/ptrace: fix setting syscall number
  s390/ptrace: pass invalid syscall numbers to tracing
  s390/ptrace: return -ENOSYS when invalid syscall is supplied
  s390/seccomp: pass syscall arguments via seccomp_data
  s390/qdio: fine-tune SLSB update
parents 7fdfbe08 b3583fca
...@@ -462,6 +462,7 @@ config NUMA ...@@ -462,6 +462,7 @@ config NUMA
config NODES_SHIFT config NODES_SHIFT
int int
depends on NEED_MULTIPLE_NODES
default "1" default "1"
config SCHED_SMT config SCHED_SMT
......
...@@ -693,7 +693,7 @@ static ssize_t prng_chunksize_show(struct device *dev, ...@@ -693,7 +693,7 @@ static ssize_t prng_chunksize_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size); return scnprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
} }
static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL); static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
...@@ -712,7 +712,7 @@ static ssize_t prng_counter_show(struct device *dev, ...@@ -712,7 +712,7 @@ static ssize_t prng_counter_show(struct device *dev,
counter = prng_data->prngws.byte_counter; counter = prng_data->prngws.byte_counter;
mutex_unlock(&prng_data->mutex); mutex_unlock(&prng_data->mutex);
return snprintf(buf, PAGE_SIZE, "%llu\n", counter); return scnprintf(buf, PAGE_SIZE, "%llu\n", counter);
} }
static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL); static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
...@@ -721,7 +721,7 @@ static ssize_t prng_errorflag_show(struct device *dev, ...@@ -721,7 +721,7 @@ static ssize_t prng_errorflag_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag); return scnprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
} }
static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL); static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
...@@ -731,9 +731,9 @@ static ssize_t prng_mode_show(struct device *dev, ...@@ -731,9 +731,9 @@ static ssize_t prng_mode_show(struct device *dev,
char *buf) char *buf)
{ {
if (prng_mode == PRNG_MODE_TDES) if (prng_mode == PRNG_MODE_TDES)
return snprintf(buf, PAGE_SIZE, "TDES\n"); return scnprintf(buf, PAGE_SIZE, "TDES\n");
else else
return snprintf(buf, PAGE_SIZE, "SHA512\n"); return scnprintf(buf, PAGE_SIZE, "SHA512\n");
} }
static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL); static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
...@@ -756,7 +756,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev, ...@@ -756,7 +756,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit); return scnprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
} }
static ssize_t prng_reseed_limit_store(struct device *dev, static ssize_t prng_reseed_limit_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
...@@ -787,7 +787,7 @@ static ssize_t prng_strength_show(struct device *dev, ...@@ -787,7 +787,7 @@ static ssize_t prng_strength_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "256\n"); return scnprintf(buf, PAGE_SIZE, "256\n");
} }
static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL); static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
......
...@@ -33,7 +33,17 @@ static inline void syscall_rollback(struct task_struct *task, ...@@ -33,7 +33,17 @@ static inline void syscall_rollback(struct task_struct *task,
static inline long syscall_get_error(struct task_struct *task, static inline long syscall_get_error(struct task_struct *task,
struct pt_regs *regs) struct pt_regs *regs)
{ {
return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0; unsigned long error = regs->gprs[2];
#ifdef CONFIG_COMPAT
if (test_tsk_thread_flag(task, TIF_31BIT)) {
/*
* Sign-extend the value so (int)-EFOO becomes (long)-EFOO
* and will match correctly in comparisons.
*/
error = (long)(int)error;
}
#endif
return IS_ERR_VALUE(error) ? error : 0;
} }
static inline long syscall_get_return_value(struct task_struct *task, static inline long syscall_get_return_value(struct task_struct *task,
......
...@@ -36,6 +36,7 @@ struct vdso_data { ...@@ -36,6 +36,7 @@ struct vdso_data {
__u32 tk_shift; /* Shift used for xtime_nsec 0x60 */ __u32 tk_shift; /* Shift used for xtime_nsec 0x60 */
__u32 ts_dir; /* TOD steering direction 0x64 */ __u32 ts_dir; /* TOD steering direction 0x64 */
__u64 ts_end; /* TOD steering end 0x68 */ __u64 ts_end; /* TOD steering end 0x68 */
__u32 hrtimer_res; /* hrtimer resolution 0x70 */
}; };
struct vdso_per_cpu_data { struct vdso_per_cpu_data {
......
...@@ -76,6 +76,7 @@ int main(void) ...@@ -76,6 +76,7 @@ int main(void)
OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift); OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir); OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir);
OFFSET(__VDSO_TS_END, vdso_data, ts_end); OFFSET(__VDSO_TS_END, vdso_data, ts_end);
OFFSET(__VDSO_CLOCK_REALTIME_RES, vdso_data, hrtimer_res);
OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base); OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time); OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val); OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
...@@ -86,7 +87,6 @@ int main(void) ...@@ -86,7 +87,6 @@ int main(void)
DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE); DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE); DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID); DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC); DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
BLANK(); BLANK();
/* idle data offsets */ /* idle data offsets */
......
...@@ -401,9 +401,9 @@ ENTRY(system_call) ...@@ -401,9 +401,9 @@ ENTRY(system_call)
jnz .Lsysc_nr_ok jnz .Lsysc_nr_ok
# svc 0: system call number in %r1 # svc 0: system call number in %r1
llgfr %r1,%r1 # clear high word in r1 llgfr %r1,%r1 # clear high word in r1
sth %r1,__PT_INT_CODE+2(%r11)
cghi %r1,NR_syscalls cghi %r1,NR_syscalls
jnl .Lsysc_nr_ok jnl .Lsysc_nr_ok
sth %r1,__PT_INT_CODE+2(%r11)
slag %r8,%r1,3 slag %r8,%r1,3
.Lsysc_nr_ok: .Lsysc_nr_ok:
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
......
...@@ -181,7 +181,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \ ...@@ -181,7 +181,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
struct kobj_attribute *attr, \ struct kobj_attribute *attr, \
char *page) \ char *page) \
{ \ { \
return snprintf(page, PAGE_SIZE, _format, ##args); \ return scnprintf(page, PAGE_SIZE, _format, ##args); \
} }
#define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \ #define IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk) \
......
...@@ -323,6 +323,25 @@ static inline void __poke_user_per(struct task_struct *child, ...@@ -323,6 +323,25 @@ static inline void __poke_user_per(struct task_struct *child,
child->thread.per_user.end = data; child->thread.per_user.end = data;
} }
static void fixup_int_code(struct task_struct *child, addr_t data)
{
struct pt_regs *regs = task_pt_regs(child);
int ilc = regs->int_code >> 16;
u16 insn;
if (ilc > 6)
return;
if (ptrace_access_vm(child, regs->psw.addr - (regs->int_code >> 16),
&insn, sizeof(insn), FOLL_FORCE) != sizeof(insn))
return;
/* double check that tracee stopped on svc instruction */
if ((insn >> 8) != 0xa)
return;
regs->int_code = 0x20000 | (data & 0xffff);
}
/* /*
* Write a word to the user area of a process at location addr. This * Write a word to the user area of a process at location addr. This
* operation does have an additional problem compared to peek_user. * operation does have an additional problem compared to peek_user.
...@@ -334,7 +353,9 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) ...@@ -334,7 +353,9 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
struct user *dummy = NULL; struct user *dummy = NULL;
addr_t offset; addr_t offset;
if (addr < (addr_t) &dummy->regs.acrs) { if (addr < (addr_t) &dummy->regs.acrs) {
struct pt_regs *regs = task_pt_regs(child);
/* /*
* psw and gprs are stored on the stack * psw and gprs are stored on the stack
*/ */
...@@ -352,7 +373,11 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) ...@@ -352,7 +373,11 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
/* Invalid addressing mode bits */ /* Invalid addressing mode bits */
return -EINVAL; return -EINVAL;
} }
*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
addr == offsetof(struct user, regs.gprs[2]))
fixup_int_code(child, data);
*(addr_t *)((addr_t) &regs->psw + addr) = data;
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
/* /*
...@@ -718,6 +743,10 @@ static int __poke_user_compat(struct task_struct *child, ...@@ -718,6 +743,10 @@ static int __poke_user_compat(struct task_struct *child,
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) | regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
(__u64)(tmp & PSW32_ADDR_AMODE); (__u64)(tmp & PSW32_ADDR_AMODE);
} else { } else {
if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
addr == offsetof(struct compat_user, regs.gprs[2]))
fixup_int_code(child, data);
/* gpr 0-15 */ /* gpr 0-15 */
*(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp; *(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
} }
...@@ -837,40 +866,66 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -837,40 +866,66 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{ {
unsigned long mask = -1UL; unsigned long mask = -1UL;
long ret = -1;
if (is_compat_task())
mask = 0xffffffff;
/* /*
* The sysc_tracesys code in entry.S stored the system * The sysc_tracesys code in entry.S stored the system
* call number to gprs[2]. * call number to gprs[2].
*/ */
if (test_thread_flag(TIF_SYSCALL_TRACE) && if (test_thread_flag(TIF_SYSCALL_TRACE) &&
(tracehook_report_syscall_entry(regs) || tracehook_report_syscall_entry(regs)) {
regs->gprs[2] >= NR_syscalls)) {
/* /*
* Tracing decided this syscall should not happen or the * Tracing decided this syscall should not happen. Skip
* debugger stored an invalid system call number. Skip
* the system call and the system call restart handling. * the system call and the system call restart handling.
*/ */
clear_pt_regs_flag(regs, PIF_SYSCALL); goto skip;
return -1;
} }
#ifdef CONFIG_SECCOMP
/* Do the secure computing check after ptrace. */ /* Do the secure computing check after ptrace. */
if (secure_computing()) { if (unlikely(test_thread_flag(TIF_SECCOMP))) {
/* seccomp failures shouldn't expose any additional code. */ struct seccomp_data sd;
return -1;
if (is_compat_task()) {
sd.instruction_pointer = regs->psw.addr & 0x7fffffff;
sd.arch = AUDIT_ARCH_S390;
} else {
sd.instruction_pointer = regs->psw.addr;
sd.arch = AUDIT_ARCH_S390X;
}
sd.nr = regs->int_code & 0xffff;
sd.args[0] = regs->orig_gpr2 & mask;
sd.args[1] = regs->gprs[3] & mask;
sd.args[2] = regs->gprs[4] & mask;
sd.args[3] = regs->gprs[5] & mask;
sd.args[4] = regs->gprs[6] & mask;
sd.args[5] = regs->gprs[7] & mask;
if (__secure_computing(&sd) == -1)
goto skip;
} }
#endif /* CONFIG_SECCOMP */
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_enter(regs, regs->gprs[2]); trace_sys_enter(regs, regs->int_code & 0xffff);
if (is_compat_task())
mask = 0xffffffff;
audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask, audit_syscall_entry(regs->int_code & 0xffff, regs->orig_gpr2 & mask,
regs->gprs[3] &mask, regs->gprs[4] &mask, regs->gprs[3] &mask, regs->gprs[4] &mask,
regs->gprs[5] &mask); regs->gprs[5] &mask);
if ((signed long)regs->gprs[2] >= NR_syscalls) {
regs->gprs[2] = -ENOSYS;
ret = -ENOSYS;
}
return regs->gprs[2]; return regs->gprs[2];
skip:
clear_pt_regs_flag(regs, PIF_SYSCALL);
return ret;
} }
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
......
...@@ -301,6 +301,7 @@ void update_vsyscall(struct timekeeper *tk) ...@@ -301,6 +301,7 @@ void update_vsyscall(struct timekeeper *tk)
vdso_data->tk_mult = tk->tkr_mono.mult; vdso_data->tk_mult = tk->tkr_mono.mult;
vdso_data->tk_shift = tk->tkr_mono.shift; vdso_data->tk_shift = tk->tkr_mono.shift;
vdso_data->hrtimer_res = hrtimer_resolution;
smp_wmb(); smp_wmb();
++vdso_data->tb_update_count; ++vdso_data->tb_update_count;
} }
......
...@@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible); ...@@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible);
static ssize_t uv_query_facilities(struct kobject *kobj, static ssize_t uv_query_facilities(struct kobject *kobj,
struct kobj_attribute *attr, char *page) struct kobj_attribute *attr, char *page)
{ {
return snprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n", return scnprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
uv_info.inst_calls_list[0], uv_info.inst_calls_list[0],
uv_info.inst_calls_list[1], uv_info.inst_calls_list[1],
uv_info.inst_calls_list[2], uv_info.inst_calls_list[2],
...@@ -344,7 +344,7 @@ static struct kobj_attribute uv_query_facilities_attr = ...@@ -344,7 +344,7 @@ static struct kobj_attribute uv_query_facilities_attr =
static ssize_t uv_query_max_guest_cpus(struct kobject *kobj, static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
struct kobj_attribute *attr, char *page) struct kobj_attribute *attr, char *page)
{ {
return snprintf(page, PAGE_SIZE, "%d\n", return scnprintf(page, PAGE_SIZE, "%d\n",
uv_info.max_guest_cpus); uv_info.max_guest_cpus);
} }
...@@ -354,7 +354,7 @@ static struct kobj_attribute uv_query_max_guest_cpus_attr = ...@@ -354,7 +354,7 @@ static struct kobj_attribute uv_query_max_guest_cpus_attr =
static ssize_t uv_query_max_guest_vms(struct kobject *kobj, static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
struct kobj_attribute *attr, char *page) struct kobj_attribute *attr, char *page)
{ {
return snprintf(page, PAGE_SIZE, "%d\n", return scnprintf(page, PAGE_SIZE, "%d\n",
uv_info.max_num_sec_conf); uv_info.max_num_sec_conf);
} }
...@@ -364,7 +364,7 @@ static struct kobj_attribute uv_query_max_guest_vms_attr = ...@@ -364,7 +364,7 @@ static struct kobj_attribute uv_query_max_guest_vms_attr =
static ssize_t uv_query_max_guest_addr(struct kobject *kobj, static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
struct kobj_attribute *attr, char *page) struct kobj_attribute *attr, char *page)
{ {
return snprintf(page, PAGE_SIZE, "%lx\n", return scnprintf(page, PAGE_SIZE, "%lx\n",
uv_info.max_sec_stor_addr); uv_info.max_sec_stor_addr);
} }
......
...@@ -18,8 +18,8 @@ KBUILD_AFLAGS_64 += -m64 -s ...@@ -18,8 +18,8 @@ KBUILD_AFLAGS_64 += -m64 -s
KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS)) KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ ldflags-y := -fPIC -shared -nostdlib -soname=linux-vdso64.so.1 \
-Wl,--hash-style=both --hash-style=both --build-id -T
$(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64) $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
$(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64) $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64)
...@@ -37,8 +37,8 @@ KASAN_SANITIZE := n ...@@ -37,8 +37,8 @@ KASAN_SANITIZE := n
$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
# link rule for the .so file, .lds has to be first # link rule for the .so file, .lds has to be first
$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE $(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) FORCE
$(call if_changed,vdso64ld) $(call if_changed,ld)
# strip rule for the .so file # strip rule for the .so file
$(obj)/%.so: OBJCOPYFLAGS := -S $(obj)/%.so: OBJCOPYFLAGS := -S
...@@ -50,8 +50,6 @@ $(obj-vdso64): %.o: %.S FORCE ...@@ -50,8 +50,6 @@ $(obj-vdso64): %.o: %.S FORCE
$(call if_changed_dep,vdso64as) $(call if_changed_dep,vdso64as)
# actual build commands # actual build commands
quiet_cmd_vdso64ld = VDSO64L $@
cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $(filter %.lds %.o,$^) -o $@
quiet_cmd_vdso64as = VDSO64A $@ quiet_cmd_vdso64as = VDSO64A $@
cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $< cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
......
...@@ -17,12 +17,14 @@ ...@@ -17,12 +17,14 @@
.type __kernel_clock_getres,@function .type __kernel_clock_getres,@function
__kernel_clock_getres: __kernel_clock_getres:
CFI_STARTPROC CFI_STARTPROC
larl %r1,4f larl %r1,3f
lg %r0,0(%r1)
cghi %r2,__CLOCK_REALTIME_COARSE cghi %r2,__CLOCK_REALTIME_COARSE
je 0f je 0f
cghi %r2,__CLOCK_MONOTONIC_COARSE cghi %r2,__CLOCK_MONOTONIC_COARSE
je 0f je 0f
larl %r1,3f larl %r1,_vdso_data
llgf %r0,__VDSO_CLOCK_REALTIME_RES(%r1)
cghi %r2,__CLOCK_REALTIME cghi %r2,__CLOCK_REALTIME
je 0f je 0f
cghi %r2,__CLOCK_MONOTONIC cghi %r2,__CLOCK_MONOTONIC
...@@ -36,7 +38,6 @@ __kernel_clock_getres: ...@@ -36,7 +38,6 @@ __kernel_clock_getres:
jz 2f jz 2f
0: ltgr %r3,%r3 0: ltgr %r3,%r3
jz 1f /* res == NULL */ jz 1f /* res == NULL */
lg %r0,0(%r1)
xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */ xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */
stg %r0,8(%r3) /* store tp->tv_usec */ stg %r0,8(%r3) /* store tp->tv_usec */
1: lghi %r2,0 1: lghi %r2,0
...@@ -45,6 +46,5 @@ __kernel_clock_getres: ...@@ -45,6 +46,5 @@ __kernel_clock_getres:
svc 0 svc 0
br %r14 br %r14
CFI_ENDPROC CFI_ENDPROC
3: .quad __CLOCK_REALTIME_RES 3: .quad __CLOCK_COARSE_RES
4: .quad __CLOCK_COARSE_RES
.size __kernel_clock_getres,.-__kernel_clock_getres .size __kernel_clock_getres,.-__kernel_clock_getres
...@@ -182,10 +182,9 @@ enum qdio_irq_poll_states { ...@@ -182,10 +182,9 @@ enum qdio_irq_poll_states {
}; };
struct qdio_input_q { struct qdio_input_q {
/* first ACK'ed buffer */ /* Batch of SBALs that we processed while polling the queue: */
int ack_start; unsigned int batch_start;
/* how many SBALs are acknowledged */ unsigned int batch_count;
int ack_count;
/* last time of noticing incoming data */ /* last time of noticing incoming data */
u64 timestamp; u64 timestamp;
}; };
......
...@@ -110,8 +110,8 @@ static int qstat_show(struct seq_file *m, void *v) ...@@ -110,8 +110,8 @@ static int qstat_show(struct seq_file *m, void *v)
seq_printf(m, "nr_used: %d ftc: %d\n", seq_printf(m, "nr_used: %d ftc: %d\n",
atomic_read(&q->nr_buf_used), q->first_to_check); atomic_read(&q->nr_buf_used), q->first_to_check);
if (q->is_input_q) { if (q->is_input_q) {
seq_printf(m, "ack start: %d ack count: %d\n", seq_printf(m, "batch start: %u batch count: %u\n",
q->u.in.ack_start, q->u.in.ack_count); q->u.in.batch_start, q->u.in.batch_count);
seq_printf(m, "DSCI: %x IRQs disabled: %u\n", seq_printf(m, "DSCI: %x IRQs disabled: %u\n",
*(u8 *)q->irq_ptr->dsci, *(u8 *)q->irq_ptr->dsci,
test_bit(QDIO_IRQ_DISABLED, test_bit(QDIO_IRQ_DISABLED,
......
...@@ -254,10 +254,17 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr, ...@@ -254,10 +254,17 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr,
if (is_qebsm(q)) if (is_qebsm(q))
return qdio_do_sqbs(q, state, bufnr, count); return qdio_do_sqbs(q, state, bufnr, count);
/* Ensure that all preceding changes to the SBALs are visible: */
mb();
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
xchg(&q->slsb.val[bufnr], state); WRITE_ONCE(q->slsb.val[bufnr], state);
bufnr = next_buf(bufnr); bufnr = next_buf(bufnr);
} }
/* Make our SLSB changes visible: */
mb();
return count; return count;
} }
...@@ -393,15 +400,15 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr, ...@@ -393,15 +400,15 @@ int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
static inline void qdio_stop_polling(struct qdio_q *q) static inline void qdio_stop_polling(struct qdio_q *q)
{ {
if (!q->u.in.ack_count) if (!q->u.in.batch_count)
return; return;
qperf_inc(q, stop_polling); qperf_inc(q, stop_polling);
/* show the card that we are not polling anymore */ /* show the card that we are not polling anymore */
set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, set_buf_states(q, q->u.in.batch_start, SLSB_P_INPUT_NOT_INIT,
q->u.in.ack_count); q->u.in.batch_count);
q->u.in.ack_count = 0; q->u.in.batch_count = 0;
} }
static inline void account_sbals(struct qdio_q *q, unsigned int count) static inline void account_sbals(struct qdio_q *q, unsigned int count)
...@@ -441,42 +448,13 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start, ...@@ -441,42 +448,13 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start,
static inline void inbound_handle_work(struct qdio_q *q, unsigned int start, static inline void inbound_handle_work(struct qdio_q *q, unsigned int start,
int count, bool auto_ack) int count, bool auto_ack)
{ {
int new; /* ACK the newest SBAL: */
if (!auto_ack)
if (auto_ack) { set_buf_state(q, add_buf(start, count - 1), SLSB_P_INPUT_ACK);
if (!q->u.in.ack_count) {
q->u.in.ack_count = count;
q->u.in.ack_start = start;
return;
}
/* delete the previous ACK's */
set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
q->u.in.ack_count);
q->u.in.ack_count = count;
q->u.in.ack_start = start;
return;
}
/*
* ACK the newest buffer. The ACK will be removed in qdio_stop_polling
* or by the next inbound run.
*/
new = add_buf(start, count - 1);
set_buf_state(q, new, SLSB_P_INPUT_ACK);
/* delete the previous ACKs */
if (q->u.in.ack_count)
set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
q->u.in.ack_count);
q->u.in.ack_count = 1; if (!q->u.in.batch_count)
q->u.in.ack_start = new; q->u.in.batch_start = start;
count--; q->u.in.batch_count += count;
if (!count)
return;
/* need to change ALL buffers to get more interrupts */
set_buf_states(q, start, SLSB_P_INPUT_NOT_INIT, count);
} }
static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start)
...@@ -525,15 +503,18 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) ...@@ -525,15 +503,18 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start)
account_sbals_error(q, count); account_sbals_error(q, count);
return count; return count;
case SLSB_CU_INPUT_EMPTY: case SLSB_CU_INPUT_EMPTY:
case SLSB_P_INPUT_NOT_INIT:
case SLSB_P_INPUT_ACK:
if (q->irq_ptr->perf_stat_enabled) if (q->irq_ptr->perf_stat_enabled)
q->q_stats.nr_sbal_nop++; q->q_stats.nr_sbal_nop++;
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop:%1d %#02x", DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop:%1d %#02x",
q->nr, start); q->nr, start);
return 0; return 0;
case SLSB_P_INPUT_NOT_INIT:
case SLSB_P_INPUT_ACK:
/* We should never see this state, throw a WARN: */
default: default:
WARN_ON_ONCE(1); dev_WARN_ONCE(&q->irq_ptr->cdev->dev, 1,
"found state %#x at index %u on queue %u\n",
state, start, q->nr);
return 0; return 0;
} }
} }
...@@ -738,11 +719,14 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start) ...@@ -738,11 +719,14 @@ static int get_outbound_buffer_frontier(struct qdio_q *q, unsigned int start)
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d",
q->nr); q->nr);
return 0; return 0;
case SLSB_P_OUTPUT_NOT_INIT:
case SLSB_P_OUTPUT_HALTED: case SLSB_P_OUTPUT_HALTED:
return 0; return 0;
case SLSB_P_OUTPUT_NOT_INIT:
/* We should never see this state, throw a WARN: */
default: default:
WARN_ON_ONCE(1); dev_WARN_ONCE(&q->irq_ptr->cdev->dev, 1,
"found state %#x at index %u on queue %u\n",
state, start, q->nr);
return 0; return 0;
} }
} }
...@@ -938,10 +922,10 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) ...@@ -938,10 +922,10 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
} }
} }
static void qdio_handle_activate_check(struct ccw_device *cdev, static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
unsigned long intparm, int cstat, int dstat) unsigned long intparm, int cstat,
int dstat)
{ {
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
struct qdio_q *q; struct qdio_q *q;
DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no); DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no);
...@@ -968,11 +952,9 @@ static void qdio_handle_activate_check(struct ccw_device *cdev, ...@@ -968,11 +952,9 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
lgr_info_log(); lgr_info_log();
} }
static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
int dstat) int dstat)
{ {
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq"); DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
if (cstat) if (cstat)
...@@ -1019,7 +1001,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -1019,7 +1001,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
switch (irq_ptr->state) { switch (irq_ptr->state) {
case QDIO_IRQ_STATE_INACTIVE: case QDIO_IRQ_STATE_INACTIVE:
qdio_establish_handle_irq(cdev, cstat, dstat); qdio_establish_handle_irq(irq_ptr, cstat, dstat);
break; break;
case QDIO_IRQ_STATE_CLEANUP: case QDIO_IRQ_STATE_CLEANUP:
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
...@@ -1031,7 +1013,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, ...@@ -1031,7 +1013,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
return; return;
} }
if (cstat || dstat) if (cstat || dstat)
qdio_handle_activate_check(cdev, intparm, cstat, qdio_handle_activate_check(irq_ptr, intparm, cstat,
dstat); dstat);
break; break;
case QDIO_IRQ_STATE_STOPPED: case QDIO_IRQ_STATE_STOPPED:
...@@ -1446,12 +1428,12 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, ...@@ -1446,12 +1428,12 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
qperf_inc(q, inbound_call); qperf_inc(q, inbound_call);
/* If any ACKed SBALs are returned to HW, adjust ACK tracking: */ /* If any processed SBALs are returned to HW, adjust our tracking: */
overlap = min(count - sub_buf(q->u.in.ack_start, bufnr), overlap = min_t(int, count - sub_buf(q->u.in.batch_start, bufnr),
q->u.in.ack_count); q->u.in.batch_count);
if (overlap > 0) { if (overlap > 0) {
q->u.in.ack_start = add_buf(q->u.in.ack_start, overlap); q->u.in.batch_start = add_buf(q->u.in.batch_start, overlap);
q->u.in.ack_count -= overlap; q->u.in.batch_count -= overlap;
} }
count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
...@@ -1535,12 +1517,11 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, ...@@ -1535,12 +1517,11 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
int do_QDIO(struct ccw_device *cdev, unsigned int callflags, int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
int q_nr, unsigned int bufnr, unsigned int count) int q_nr, unsigned int bufnr, unsigned int count)
{ {
struct qdio_irq *irq_ptr; struct qdio_irq *irq_ptr = cdev->private->qdio_data;
if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q) if (bufnr >= QDIO_MAX_BUFFERS_PER_Q || count > QDIO_MAX_BUFFERS_PER_Q)
return -EINVAL; return -EINVAL;
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr) if (!irq_ptr)
return -ENODEV; return -ENODEV;
......
...@@ -195,11 +195,10 @@ static inline struct ep11_cprb *alloc_cprb(size_t payload_len) ...@@ -195,11 +195,10 @@ static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
size_t len = sizeof(struct ep11_cprb) + payload_len; size_t len = sizeof(struct ep11_cprb) + payload_len;
struct ep11_cprb *cprb; struct ep11_cprb *cprb;
cprb = kmalloc(len, GFP_KERNEL); cprb = kzalloc(len, GFP_KERNEL);
if (!cprb) if (!cprb)
return NULL; return NULL;
memset(cprb, 0, len);
cprb->cprb_len = sizeof(struct ep11_cprb); cprb->cprb_len = sizeof(struct ep11_cprb);
cprb->cprb_ver_id = 0x04; cprb->cprb_ver_id = 0x04;
memcpy(cprb->func_id, "T4", 2); memcpy(cprb->func_id, "T4", 2);
......
...@@ -1372,27 +1372,6 @@ static struct ccw_device_id virtio_ids[] = { ...@@ -1372,27 +1372,6 @@ static struct ccw_device_id virtio_ids[] = {
{}, {},
}; };
#ifdef CONFIG_PM_SLEEP
static int virtio_ccw_freeze(struct ccw_device *cdev)
{
struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
return virtio_device_freeze(&vcdev->vdev);
}
static int virtio_ccw_restore(struct ccw_device *cdev)
{
struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
int ret;
ret = virtio_ccw_set_transport_rev(vcdev);
if (ret)
return ret;
return virtio_device_restore(&vcdev->vdev);
}
#endif
static struct ccw_driver virtio_ccw_driver = { static struct ccw_driver virtio_ccw_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -1405,11 +1384,6 @@ static struct ccw_driver virtio_ccw_driver = { ...@@ -1405,11 +1384,6 @@ static struct ccw_driver virtio_ccw_driver = {
.set_online = virtio_ccw_online, .set_online = virtio_ccw_online,
.notify = virtio_ccw_cio_notify, .notify = virtio_ccw_cio_notify,
.int_class = IRQIO_VIR, .int_class = IRQIO_VIR,
#ifdef CONFIG_PM_SLEEP
.freeze = virtio_ccw_freeze,
.thaw = virtio_ccw_restore,
.restore = virtio_ccw_restore,
#endif
}; };
static int __init pure_hex(char **cp, unsigned int *val, int min_digit, static int __init pure_hex(char **cp, unsigned int *val, int min_digit,
......
...@@ -1615,6 +1615,7 @@ TEST_F(TRACE_poke, getpid_runs_normally) ...@@ -1615,6 +1615,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
# define ARCH_REGS s390_regs # define ARCH_REGS s390_regs
# define SYSCALL_NUM gprs[2] # define SYSCALL_NUM gprs[2]
# define SYSCALL_RET gprs[2] # define SYSCALL_RET gprs[2]
# define SYSCALL_NUM_RET_SHARE_REG
#elif defined(__mips__) #elif defined(__mips__)
# define ARCH_REGS struct pt_regs # define ARCH_REGS struct pt_regs
# define SYSCALL_NUM regs[2] # define SYSCALL_NUM regs[2]
......
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