forked from luck/tmp_suning_uos_patched
s390 fixes for 5.8-rc2
- 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. - Few fixes to use scnprintf() instead of snprintf(). -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE3QHqV+H2a8xAv27vjYWKoQLXFBgFAl7uJy8ACgkQjYWKoQLX FBitMwgAovHP6O19ZS2RE2Ps20CjM+z0sLLGHF6aMrV7OqmOWrNnFzN4jT2j42Ck idSZ6sehVd3Uj6K8NnzrlSS3sjGRhVaQJEjjN+rLyw0HBwxspJJfW5HgcoMtqNH1 oo+nt+zw5jk+6MqHx4QEwTxN5rgGs6UMhiLIAIlkDu4bivgohvGUxe4RUrN/mINx cdYqomCkvovLT5sBTaWyXKNCDAdAWgNpOfdqc9MjOUXSbUg3lrUol0gUULzenPo7 wUN+sZ0di0Ox0+2+4m8LU1av/kMTLSSvnR9DW5KdpGTon1nwpZcdJnhI5o1v7uaU pIaMOYNieEHJ2DnieR9iBBSbGoNCmw== =gkgN -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
1566feea45
|
@ -462,6 +462,7 @@ config NUMA
|
|||
|
||||
config NODES_SHIFT
|
||||
int
|
||||
depends on NEED_MULTIPLE_NODES
|
||||
default "1"
|
||||
|
||||
config SCHED_SMT
|
||||
|
|
|
@ -693,7 +693,7 @@ static ssize_t prng_chunksize_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
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);
|
||||
|
||||
|
@ -712,7 +712,7 @@ static ssize_t prng_counter_show(struct device *dev,
|
|||
counter = prng_data->prngws.byte_counter;
|
||||
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);
|
||||
|
||||
|
@ -721,7 +721,7 @@ static ssize_t prng_errorflag_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
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);
|
||||
|
||||
|
@ -731,9 +731,9 @@ static ssize_t prng_mode_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
if (prng_mode == PRNG_MODE_TDES)
|
||||
return snprintf(buf, PAGE_SIZE, "TDES\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "TDES\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "SHA512\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "SHA512\n");
|
||||
}
|
||||
static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
|
||||
|
||||
|
@ -756,7 +756,7 @@ static ssize_t prng_reseed_limit_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
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,
|
||||
struct device_attribute *attr,
|
||||
|
@ -787,7 +787,7 @@ static ssize_t prng_strength_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
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);
|
||||
|
||||
|
|
|
@ -33,7 +33,17 @@ static inline void syscall_rollback(struct task_struct *task,
|
|||
static inline long syscall_get_error(struct task_struct *task,
|
||||
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,
|
||||
|
|
|
@ -36,6 +36,7 @@ struct vdso_data {
|
|||
__u32 tk_shift; /* Shift used for xtime_nsec 0x60 */
|
||||
__u32 ts_dir; /* TOD steering direction 0x64 */
|
||||
__u64 ts_end; /* TOD steering end 0x68 */
|
||||
__u32 hrtimer_res; /* hrtimer resolution 0x70 */
|
||||
};
|
||||
|
||||
struct vdso_per_cpu_data {
|
||||
|
|
|
@ -76,6 +76,7 @@ int main(void)
|
|||
OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
|
||||
OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir);
|
||||
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_USER, vdso_per_cpu_data, ectg_user_time);
|
||||
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
|
||||
|
@ -86,7 +87,6 @@ int main(void)
|
|||
DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
|
||||
DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
|
||||
DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
|
||||
DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
|
||||
DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
|
||||
BLANK();
|
||||
/* idle data offsets */
|
||||
|
|
|
@ -401,9 +401,9 @@ ENTRY(system_call)
|
|||
jnz .Lsysc_nr_ok
|
||||
# svc 0: system call number in %r1
|
||||
llgfr %r1,%r1 # clear high word in r1
|
||||
sth %r1,__PT_INT_CODE+2(%r11)
|
||||
cghi %r1,NR_syscalls
|
||||
jnl .Lsysc_nr_ok
|
||||
sth %r1,__PT_INT_CODE+2(%r11)
|
||||
slag %r8,%r1,3
|
||||
.Lsysc_nr_ok:
|
||||
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
|
||||
|
|
|
@ -181,7 +181,7 @@ static ssize_t sys_##_prefix##_##_name##_show(struct kobject *kobj, \
|
|||
struct kobj_attribute *attr, \
|
||||
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) \
|
||||
|
|
|
@ -323,6 +323,25 @@ static inline void __poke_user_per(struct task_struct *child,
|
|||
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
|
||||
* 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)
|
|||
struct user *dummy = NULL;
|
||||
addr_t offset;
|
||||
|
||||
|
||||
if (addr < (addr_t) &dummy->regs.acrs) {
|
||||
struct pt_regs *regs = task_pt_regs(child);
|
||||
/*
|
||||
* 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)
|
|||
/* Invalid addressing mode bits */
|
||||
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) ®s->psw + addr) = data;
|
||||
|
||||
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
|
||||
/*
|
||||
|
@ -718,6 +743,10 @@ static int __poke_user_compat(struct task_struct *child,
|
|||
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
|
||||
(__u64)(tmp & PSW32_ADDR_AMODE);
|
||||
} 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 */
|
||||
*(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
unsigned long mask = -1UL;
|
||||
long ret = -1;
|
||||
|
||||
if (is_compat_task())
|
||||
mask = 0xffffffff;
|
||||
|
||||
/*
|
||||
* The sysc_tracesys code in entry.S stored the system
|
||||
* call number to gprs[2].
|
||||
*/
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
(tracehook_report_syscall_entry(regs) ||
|
||||
regs->gprs[2] >= NR_syscalls)) {
|
||||
tracehook_report_syscall_entry(regs)) {
|
||||
/*
|
||||
* Tracing decided this syscall should not happen or the
|
||||
* debugger stored an invalid system call number. Skip
|
||||
* Tracing decided this syscall should not happen. Skip
|
||||
* the system call and the system call restart handling.
|
||||
*/
|
||||
clear_pt_regs_flag(regs, PIF_SYSCALL);
|
||||
return -1;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECCOMP
|
||||
/* Do the secure computing check after ptrace. */
|
||||
if (secure_computing()) {
|
||||
/* seccomp failures shouldn't expose any additional code. */
|
||||
return -1;
|
||||
if (unlikely(test_thread_flag(TIF_SECCOMP))) {
|
||||
struct seccomp_data sd;
|
||||
|
||||
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)))
|
||||
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[5] &mask);
|
||||
|
||||
if ((signed long)regs->gprs[2] >= NR_syscalls) {
|
||||
regs->gprs[2] = -ENOSYS;
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
return regs->gprs[2];
|
||||
skip:
|
||||
clear_pt_regs_flag(regs, PIF_SYSCALL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
|
||||
|
|
|
@ -301,6 +301,7 @@ void update_vsyscall(struct timekeeper *tk)
|
|||
|
||||
vdso_data->tk_mult = tk->tkr_mono.mult;
|
||||
vdso_data->tk_shift = tk->tkr_mono.shift;
|
||||
vdso_data->hrtimer_res = hrtimer_resolution;
|
||||
smp_wmb();
|
||||
++vdso_data->tb_update_count;
|
||||
}
|
||||
|
|
|
@ -331,7 +331,7 @@ EXPORT_SYMBOL_GPL(arch_make_page_accessible);
|
|||
static ssize_t uv_query_facilities(struct kobject *kobj,
|
||||
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[1],
|
||||
uv_info.inst_calls_list[2],
|
||||
|
@ -344,7 +344,7 @@ static struct kobj_attribute uv_query_facilities_attr =
|
|||
static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ KBUILD_AFLAGS_64 += -m64 -s
|
|||
|
||||
KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
|
||||
KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
|
||||
KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
|
||||
-Wl,--hash-style=both
|
||||
ldflags-y := -fPIC -shared -nostdlib -soname=linux-vdso64.so.1 \
|
||||
--hash-style=both --build-id -T
|
||||
|
||||
$(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
|
||||
$(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64)
|
||||
|
@ -37,8 +37,8 @@ KASAN_SANITIZE := n
|
|||
$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
|
||||
|
||||
# link rule for the .so file, .lds has to be first
|
||||
$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE
|
||||
$(call if_changed,vdso64ld)
|
||||
$(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
||||
# strip rule for the .so file
|
||||
$(obj)/%.so: OBJCOPYFLAGS := -S
|
||||
|
@ -50,8 +50,6 @@ $(obj-vdso64): %.o: %.S FORCE
|
|||
$(call if_changed_dep,vdso64as)
|
||||
|
||||
# actual build commands
|
||||
quiet_cmd_vdso64ld = VDSO64L $@
|
||||
cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $(filter %.lds %.o,$^) -o $@
|
||||
quiet_cmd_vdso64as = VDSO64A $@
|
||||
cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
|
||||
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
.type __kernel_clock_getres,@function
|
||||
__kernel_clock_getres:
|
||||
CFI_STARTPROC
|
||||
larl %r1,4f
|
||||
larl %r1,3f
|
||||
lg %r0,0(%r1)
|
||||
cghi %r2,__CLOCK_REALTIME_COARSE
|
||||
je 0f
|
||||
cghi %r2,__CLOCK_MONOTONIC_COARSE
|
||||
je 0f
|
||||
larl %r1,3f
|
||||
larl %r1,_vdso_data
|
||||
llgf %r0,__VDSO_CLOCK_REALTIME_RES(%r1)
|
||||
cghi %r2,__CLOCK_REALTIME
|
||||
je 0f
|
||||
cghi %r2,__CLOCK_MONOTONIC
|
||||
|
@ -36,7 +38,6 @@ __kernel_clock_getres:
|
|||
jz 2f
|
||||
0: ltgr %r3,%r3
|
||||
jz 1f /* res == NULL */
|
||||
lg %r0,0(%r1)
|
||||
xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */
|
||||
stg %r0,8(%r3) /* store tp->tv_usec */
|
||||
1: lghi %r2,0
|
||||
|
@ -45,6 +46,5 @@ __kernel_clock_getres:
|
|||
svc 0
|
||||
br %r14
|
||||
CFI_ENDPROC
|
||||
3: .quad __CLOCK_REALTIME_RES
|
||||
4: .quad __CLOCK_COARSE_RES
|
||||
3: .quad __CLOCK_COARSE_RES
|
||||
.size __kernel_clock_getres,.-__kernel_clock_getres
|
||||
|
|
|
@ -182,10 +182,9 @@ enum qdio_irq_poll_states {
|
|||
};
|
||||
|
||||
struct qdio_input_q {
|
||||
/* first ACK'ed buffer */
|
||||
int ack_start;
|
||||
/* how many SBALs are acknowledged */
|
||||
int ack_count;
|
||||
/* Batch of SBALs that we processed while polling the queue: */
|
||||
unsigned int batch_start;
|
||||
unsigned int batch_count;
|
||||
/* last time of noticing incoming data */
|
||||
u64 timestamp;
|
||||
};
|
||||
|
|
|
@ -110,8 +110,8 @@ static int qstat_show(struct seq_file *m, void *v)
|
|||
seq_printf(m, "nr_used: %d ftc: %d\n",
|
||||
atomic_read(&q->nr_buf_used), q->first_to_check);
|
||||
if (q->is_input_q) {
|
||||
seq_printf(m, "ack start: %d ack count: %d\n",
|
||||
q->u.in.ack_start, q->u.in.ack_count);
|
||||
seq_printf(m, "batch start: %u batch count: %u\n",
|
||||
q->u.in.batch_start, q->u.in.batch_count);
|
||||
seq_printf(m, "DSCI: %x IRQs disabled: %u\n",
|
||||
*(u8 *)q->irq_ptr->dsci,
|
||||
test_bit(QDIO_IRQ_DISABLED,
|
||||
|
|
|
@ -254,10 +254,17 @@ static inline int set_buf_states(struct qdio_q *q, int bufnr,
|
|||
if (is_qebsm(q))
|
||||
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++) {
|
||||
xchg(&q->slsb.val[bufnr], state);
|
||||
WRITE_ONCE(q->slsb.val[bufnr], state);
|
||||
bufnr = next_buf(bufnr);
|
||||
}
|
||||
|
||||
/* Make our SLSB changes visible: */
|
||||
mb();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
if (!q->u.in.ack_count)
|
||||
if (!q->u.in.batch_count)
|
||||
return;
|
||||
|
||||
qperf_inc(q, stop_polling);
|
||||
|
||||
/* show the card that we are not polling anymore */
|
||||
set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT,
|
||||
q->u.in.ack_count);
|
||||
q->u.in.ack_count = 0;
|
||||
set_buf_states(q, q->u.in.batch_start, SLSB_P_INPUT_NOT_INIT,
|
||||
q->u.in.batch_count);
|
||||
q->u.in.batch_count = 0;
|
||||
}
|
||||
|
||||
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,
|
|||
static inline void inbound_handle_work(struct qdio_q *q, unsigned int start,
|
||||
int count, bool auto_ack)
|
||||
{
|
||||
int new;
|
||||
/* ACK the newest SBAL: */
|
||||
if (!auto_ack)
|
||||
set_buf_state(q, add_buf(start, count - 1), SLSB_P_INPUT_ACK);
|
||||
|
||||
if (auto_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;
|
||||
q->u.in.ack_start = new;
|
||||
count--;
|
||||
if (!count)
|
||||
return;
|
||||
/* need to change ALL buffers to get more interrupts */
|
||||
set_buf_states(q, start, SLSB_P_INPUT_NOT_INIT, count);
|
||||
if (!q->u.in.batch_count)
|
||||
q->u.in.batch_start = start;
|
||||
q->u.in.batch_count += count;
|
||||
}
|
||||
|
||||
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);
|
||||
return count;
|
||||
case SLSB_CU_INPUT_EMPTY:
|
||||
case SLSB_P_INPUT_NOT_INIT:
|
||||
case SLSB_P_INPUT_ACK:
|
||||
if (q->irq_ptr->perf_stat_enabled)
|
||||
q->q_stats.nr_sbal_nop++;
|
||||
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop:%1d %#02x",
|
||||
q->nr, start);
|
||||
return 0;
|
||||
case SLSB_P_INPUT_NOT_INIT:
|
||||
case SLSB_P_INPUT_ACK:
|
||||
/* We should never see this state, throw a WARN: */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
q->nr);
|
||||
return 0;
|
||||
case SLSB_P_OUTPUT_NOT_INIT:
|
||||
case SLSB_P_OUTPUT_HALTED:
|
||||
return 0;
|
||||
case SLSB_P_OUTPUT_NOT_INIT:
|
||||
/* We should never see this state, throw a WARN: */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
unsigned long intparm, int cstat, int dstat)
|
||||
static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
|
||||
unsigned long intparm, int cstat,
|
||||
int dstat)
|
||||
{
|
||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||
struct qdio_q *q;
|
||||
|
||||
DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no);
|
||||
|
@ -968,11 +952,9 @@ static void qdio_handle_activate_check(struct ccw_device *cdev,
|
|||
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)
|
||||
{
|
||||
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
|
||||
|
||||
DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
|
||||
|
||||
if (cstat)
|
||||
|
@ -1019,7 +1001,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
|||
|
||||
switch (irq_ptr->state) {
|
||||
case QDIO_IRQ_STATE_INACTIVE:
|
||||
qdio_establish_handle_irq(cdev, cstat, dstat);
|
||||
qdio_establish_handle_irq(irq_ptr, cstat, dstat);
|
||||
break;
|
||||
case QDIO_IRQ_STATE_CLEANUP:
|
||||
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
|
||||
|
@ -1031,7 +1013,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
|
|||
return;
|
||||
}
|
||||
if (cstat || dstat)
|
||||
qdio_handle_activate_check(cdev, intparm, cstat,
|
||||
qdio_handle_activate_check(irq_ptr, intparm, cstat,
|
||||
dstat);
|
||||
break;
|
||||
case QDIO_IRQ_STATE_STOPPED:
|
||||
|
@ -1446,12 +1428,12 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
|
|||
|
||||
qperf_inc(q, inbound_call);
|
||||
|
||||
/* If any ACKed SBALs are returned to HW, adjust ACK tracking: */
|
||||
overlap = min(count - sub_buf(q->u.in.ack_start, bufnr),
|
||||
q->u.in.ack_count);
|
||||
/* If any processed SBALs are returned to HW, adjust our tracking: */
|
||||
overlap = min_t(int, count - sub_buf(q->u.in.batch_start, bufnr),
|
||||
q->u.in.batch_count);
|
||||
if (overlap > 0) {
|
||||
q->u.in.ack_start = add_buf(q->u.in.ack_start, overlap);
|
||||
q->u.in.ack_count -= overlap;
|
||||
q->u.in.batch_start = add_buf(q->u.in.batch_start, overlap);
|
||||
q->u.in.batch_count -= overlap;
|
||||
}
|
||||
|
||||
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,
|
|||
int do_QDIO(struct ccw_device *cdev, unsigned int callflags,
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
irq_ptr = cdev->private->qdio_data;
|
||||
if (!irq_ptr)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
@ -195,11 +195,10 @@ static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
|
|||
size_t len = sizeof(struct ep11_cprb) + payload_len;
|
||||
struct ep11_cprb *cprb;
|
||||
|
||||
cprb = kmalloc(len, GFP_KERNEL);
|
||||
cprb = kzalloc(len, GFP_KERNEL);
|
||||
if (!cprb)
|
||||
return NULL;
|
||||
|
||||
memset(cprb, 0, len);
|
||||
cprb->cprb_len = sizeof(struct ep11_cprb);
|
||||
cprb->cprb_ver_id = 0x04;
|
||||
memcpy(cprb->func_id, "T4", 2);
|
||||
|
|
|
@ -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 = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -1405,11 +1384,6 @@ static struct ccw_driver virtio_ccw_driver = {
|
|||
.set_online = virtio_ccw_online,
|
||||
.notify = virtio_ccw_cio_notify,
|
||||
.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,
|
||||
|
|
|
@ -1615,6 +1615,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
|
|||
# define ARCH_REGS s390_regs
|
||||
# define SYSCALL_NUM gprs[2]
|
||||
# define SYSCALL_RET gprs[2]
|
||||
# define SYSCALL_NUM_RET_SHARE_REG
|
||||
#elif defined(__mips__)
|
||||
# define ARCH_REGS struct pt_regs
|
||||
# define SYSCALL_NUM regs[2]
|
||||
|
|
Loading…
Reference in New Issue
Block a user