Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "This patch set contains the main portion of the changes for 3.18 in regard to the s390 architecture. It is a bit bigger than usual, mainly because of a new driver and the vector extension patches. The interesting bits are: - Quite a bit of work on the tracing front. Uprobes is enabled and the ftrace code is reworked to get some of the lost performance back if CONFIG_FTRACE is enabled. - To improve boot time with CONFIG_DEBIG_PAGEALLOC, support for the IPTE range facility is added. - The rwlock code is re-factored to improve writer fairness and to be able to use the interlocked-access instructions. - The kernel part for the support of the vector extension is added. - The device driver to access the CD/DVD on the HMC is added, this will hopefully come in handy to improve the installation process. - Add support for control-unit initiated reconfiguration. - The crypto device driver is enhanced to enable the additional AP domains and to allow the new crypto hardware to be used. - Bug fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (39 commits) s390/ftrace: simplify enabling/disabling of ftrace_graph_caller s390/ftrace: remove 31 bit ftrace support s390/kdump: add support for vector extension s390/disassembler: add vector instructions s390: add support for vector extension s390/zcrypt: Toleration of new crypto hardware s390/idle: consolidate idle functions and definitions s390/nohz: use a per-cpu flag for arch_needs_cpu s390/vtime: do not reset idle data on CPU hotplug s390/dasd: add support for control unit initiated reconfiguration s390/dasd: fix infinite loop during format s390/mm: make use of ipte range facility s390/setup: correct 4-level kernel page table detection s390/topology: call set_sched_topology early s390/uprobes: architecture backend for uprobes s390/uprobes: common library for kprobes and uprobes s390/rwlock: use the interlocked-access facility 1 instructions s390/rwlock: improve writer fairness s390/rwlock: remove interrupt-enabling rwlock variant. s390/mm: remove change bit override support ...
This commit is contained in:
@@ -38,15 +38,6 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/syscalls.h>
|
||||
|
||||
enum s390_regset {
|
||||
REGSET_GENERAL,
|
||||
REGSET_FP,
|
||||
REGSET_LAST_BREAK,
|
||||
REGSET_TDB,
|
||||
REGSET_SYSTEM_CALL,
|
||||
REGSET_GENERAL_EXTENDED,
|
||||
};
|
||||
|
||||
void update_cr_regs(struct task_struct *task)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(task);
|
||||
@@ -55,27 +46,39 @@ void update_cr_regs(struct task_struct *task)
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/* Take care of the enable/disable of transactional execution. */
|
||||
if (MACHINE_HAS_TE) {
|
||||
if (MACHINE_HAS_TE || MACHINE_HAS_VX) {
|
||||
unsigned long cr, cr_new;
|
||||
|
||||
__ctl_store(cr, 0, 0);
|
||||
/* Set or clear transaction execution TXC bit 8. */
|
||||
cr_new = cr | (1UL << 55);
|
||||
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
||||
cr_new &= ~(1UL << 55);
|
||||
if (cr_new != cr)
|
||||
__ctl_load(cr_new, 0, 0);
|
||||
/* Set or clear transaction execution TDC bits 62 and 63. */
|
||||
__ctl_store(cr, 2, 2);
|
||||
cr_new = cr & ~3UL;
|
||||
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
|
||||
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
|
||||
cr_new |= 1UL;
|
||||
else
|
||||
cr_new |= 2UL;
|
||||
cr_new = cr;
|
||||
if (MACHINE_HAS_TE) {
|
||||
/* Set or clear transaction execution TXC bit 8. */
|
||||
cr_new |= (1UL << 55);
|
||||
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
||||
cr_new &= ~(1UL << 55);
|
||||
}
|
||||
if (MACHINE_HAS_VX) {
|
||||
/* Enable/disable of vector extension */
|
||||
cr_new &= ~(1UL << 17);
|
||||
if (task->thread.vxrs)
|
||||
cr_new |= (1UL << 17);
|
||||
}
|
||||
if (cr_new != cr)
|
||||
__ctl_load(cr_new, 2, 2);
|
||||
__ctl_load(cr_new, 0, 0);
|
||||
if (MACHINE_HAS_TE) {
|
||||
/* Set/clear transaction execution TDC bits 62/63. */
|
||||
__ctl_store(cr, 2, 2);
|
||||
cr_new = cr & ~3UL;
|
||||
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
|
||||
if (task->thread.per_flags &
|
||||
PER_FLAG_TE_ABORT_RAND_TEND)
|
||||
cr_new |= 1UL;
|
||||
else
|
||||
cr_new |= 2UL;
|
||||
}
|
||||
if (cr_new != cr)
|
||||
__ctl_load(cr_new, 2, 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Copy user specified PER registers */
|
||||
@@ -84,7 +87,8 @@ void update_cr_regs(struct task_struct *task)
|
||||
new.end = thread->per_user.end;
|
||||
|
||||
/* merge TIF_SINGLE_STEP into user specified PER registers. */
|
||||
if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
|
||||
if (test_tsk_thread_flag(task, TIF_SINGLE_STEP) ||
|
||||
test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP)) {
|
||||
if (test_tsk_thread_flag(task, TIF_BLOCK_STEP))
|
||||
new.control |= PER_EVENT_BRANCH;
|
||||
else
|
||||
@@ -93,6 +97,8 @@ void update_cr_regs(struct task_struct *task)
|
||||
new.control |= PER_CONTROL_SUSPENSION;
|
||||
new.control |= PER_EVENT_TRANSACTION_END;
|
||||
#endif
|
||||
if (test_tsk_thread_flag(task, TIF_UPROBE_SINGLESTEP))
|
||||
new.control |= PER_EVENT_IFETCH;
|
||||
new.start = 0;
|
||||
new.end = PSW_ADDR_INSN;
|
||||
}
|
||||
@@ -923,7 +929,15 @@ static int s390_fpregs_get(struct task_struct *target,
|
||||
save_fp_ctl(&target->thread.fp_regs.fpc);
|
||||
save_fp_regs(target->thread.fp_regs.fprs);
|
||||
}
|
||||
#ifdef CONFIG_64BIT
|
||||
else if (target->thread.vxrs) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __NUM_VXRS_LOW; i++)
|
||||
target->thread.fp_regs.fprs[i] =
|
||||
*(freg_t *)(target->thread.vxrs + i);
|
||||
}
|
||||
#endif
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fp_regs, 0, -1);
|
||||
}
|
||||
@@ -957,9 +971,20 @@ static int s390_fpregs_set(struct task_struct *target,
|
||||
target->thread.fp_regs.fprs,
|
||||
offsetof(s390_fp_regs, fprs), -1);
|
||||
|
||||
if (rc == 0 && target == current) {
|
||||
restore_fp_ctl(&target->thread.fp_regs.fpc);
|
||||
restore_fp_regs(target->thread.fp_regs.fprs);
|
||||
if (rc == 0) {
|
||||
if (target == current) {
|
||||
restore_fp_ctl(&target->thread.fp_regs.fpc);
|
||||
restore_fp_regs(target->thread.fp_regs.fprs);
|
||||
}
|
||||
#ifdef CONFIG_64BIT
|
||||
else if (target->thread.vxrs) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __NUM_VXRS_LOW; i++)
|
||||
*(freg_t *)(target->thread.vxrs + i) =
|
||||
target->thread.fp_regs.fprs[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1015,6 +1040,95 @@ static int s390_tdb_set(struct task_struct *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s390_vxrs_active(struct task_struct *target,
|
||||
const struct user_regset *regset)
|
||||
{
|
||||
return !!target->thread.vxrs;
|
||||
}
|
||||
|
||||
static int s390_vxrs_low_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
__u64 vxrs[__NUM_VXRS_LOW];
|
||||
int i;
|
||||
|
||||
if (target->thread.vxrs) {
|
||||
if (target == current)
|
||||
save_vx_regs(target->thread.vxrs);
|
||||
for (i = 0; i < __NUM_VXRS_LOW; i++)
|
||||
vxrs[i] = *((__u64 *)(target->thread.vxrs + i) + 1);
|
||||
} else
|
||||
memset(vxrs, 0, sizeof(vxrs));
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
|
||||
}
|
||||
|
||||
static int s390_vxrs_low_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
__u64 vxrs[__NUM_VXRS_LOW];
|
||||
int i, rc;
|
||||
|
||||
if (!target->thread.vxrs) {
|
||||
rc = alloc_vector_registers(target);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (target == current)
|
||||
save_vx_regs(target->thread.vxrs);
|
||||
|
||||
rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
|
||||
if (rc == 0) {
|
||||
for (i = 0; i < __NUM_VXRS_LOW; i++)
|
||||
*((__u64 *)(target->thread.vxrs + i) + 1) = vxrs[i];
|
||||
if (target == current)
|
||||
restore_vx_regs(target->thread.vxrs);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int s390_vxrs_high_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
__vector128 vxrs[__NUM_VXRS_HIGH];
|
||||
|
||||
if (target->thread.vxrs) {
|
||||
if (target == current)
|
||||
save_vx_regs(target->thread.vxrs);
|
||||
memcpy(vxrs, target->thread.vxrs + __NUM_VXRS_LOW,
|
||||
sizeof(vxrs));
|
||||
} else
|
||||
memset(vxrs, 0, sizeof(vxrs));
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
|
||||
}
|
||||
|
||||
static int s390_vxrs_high_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!target->thread.vxrs) {
|
||||
rc = alloc_vector_registers(target);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (target == current)
|
||||
save_vx_regs(target->thread.vxrs);
|
||||
|
||||
rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
target->thread.vxrs + __NUM_VXRS_LOW, 0, -1);
|
||||
if (rc == 0 && target == current)
|
||||
restore_vx_regs(target->thread.vxrs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int s390_system_call_get(struct task_struct *target,
|
||||
@@ -1038,7 +1152,7 @@ static int s390_system_call_set(struct task_struct *target,
|
||||
}
|
||||
|
||||
static const struct user_regset s390_regsets[] = {
|
||||
[REGSET_GENERAL] = {
|
||||
{
|
||||
.core_note_type = NT_PRSTATUS,
|
||||
.n = sizeof(s390_regs) / sizeof(long),
|
||||
.size = sizeof(long),
|
||||
@@ -1046,7 +1160,7 @@ static const struct user_regset s390_regsets[] = {
|
||||
.get = s390_regs_get,
|
||||
.set = s390_regs_set,
|
||||
},
|
||||
[REGSET_FP] = {
|
||||
{
|
||||
.core_note_type = NT_PRFPREG,
|
||||
.n = sizeof(s390_fp_regs) / sizeof(long),
|
||||
.size = sizeof(long),
|
||||
@@ -1054,25 +1168,7 @@ static const struct user_regset s390_regsets[] = {
|
||||
.get = s390_fpregs_get,
|
||||
.set = s390_fpregs_set,
|
||||
},
|
||||
#ifdef CONFIG_64BIT
|
||||
[REGSET_LAST_BREAK] = {
|
||||
.core_note_type = NT_S390_LAST_BREAK,
|
||||
.n = 1,
|
||||
.size = sizeof(long),
|
||||
.align = sizeof(long),
|
||||
.get = s390_last_break_get,
|
||||
.set = s390_last_break_set,
|
||||
},
|
||||
[REGSET_TDB] = {
|
||||
.core_note_type = NT_S390_TDB,
|
||||
.n = 1,
|
||||
.size = 256,
|
||||
.align = 1,
|
||||
.get = s390_tdb_get,
|
||||
.set = s390_tdb_set,
|
||||
},
|
||||
#endif
|
||||
[REGSET_SYSTEM_CALL] = {
|
||||
{
|
||||
.core_note_type = NT_S390_SYSTEM_CALL,
|
||||
.n = 1,
|
||||
.size = sizeof(unsigned int),
|
||||
@@ -1080,6 +1176,42 @@ static const struct user_regset s390_regsets[] = {
|
||||
.get = s390_system_call_get,
|
||||
.set = s390_system_call_set,
|
||||
},
|
||||
#ifdef CONFIG_64BIT
|
||||
{
|
||||
.core_note_type = NT_S390_LAST_BREAK,
|
||||
.n = 1,
|
||||
.size = sizeof(long),
|
||||
.align = sizeof(long),
|
||||
.get = s390_last_break_get,
|
||||
.set = s390_last_break_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_TDB,
|
||||
.n = 1,
|
||||
.size = 256,
|
||||
.align = 1,
|
||||
.get = s390_tdb_get,
|
||||
.set = s390_tdb_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_VXRS_LOW,
|
||||
.n = __NUM_VXRS_LOW,
|
||||
.size = sizeof(__u64),
|
||||
.align = sizeof(__u64),
|
||||
.active = s390_vxrs_active,
|
||||
.get = s390_vxrs_low_get,
|
||||
.set = s390_vxrs_low_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_VXRS_HIGH,
|
||||
.n = __NUM_VXRS_HIGH,
|
||||
.size = sizeof(__vector128),
|
||||
.align = sizeof(__vector128),
|
||||
.active = s390_vxrs_active,
|
||||
.get = s390_vxrs_high_get,
|
||||
.set = s390_vxrs_high_set,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct user_regset_view user_s390_view = {
|
||||
@@ -1244,7 +1376,7 @@ static int s390_compat_last_break_set(struct task_struct *target,
|
||||
}
|
||||
|
||||
static const struct user_regset s390_compat_regsets[] = {
|
||||
[REGSET_GENERAL] = {
|
||||
{
|
||||
.core_note_type = NT_PRSTATUS,
|
||||
.n = sizeof(s390_compat_regs) / sizeof(compat_long_t),
|
||||
.size = sizeof(compat_long_t),
|
||||
@@ -1252,7 +1384,7 @@ static const struct user_regset s390_compat_regsets[] = {
|
||||
.get = s390_compat_regs_get,
|
||||
.set = s390_compat_regs_set,
|
||||
},
|
||||
[REGSET_FP] = {
|
||||
{
|
||||
.core_note_type = NT_PRFPREG,
|
||||
.n = sizeof(s390_fp_regs) / sizeof(compat_long_t),
|
||||
.size = sizeof(compat_long_t),
|
||||
@@ -1260,23 +1392,7 @@ static const struct user_regset s390_compat_regsets[] = {
|
||||
.get = s390_fpregs_get,
|
||||
.set = s390_fpregs_set,
|
||||
},
|
||||
[REGSET_LAST_BREAK] = {
|
||||
.core_note_type = NT_S390_LAST_BREAK,
|
||||
.n = 1,
|
||||
.size = sizeof(long),
|
||||
.align = sizeof(long),
|
||||
.get = s390_compat_last_break_get,
|
||||
.set = s390_compat_last_break_set,
|
||||
},
|
||||
[REGSET_TDB] = {
|
||||
.core_note_type = NT_S390_TDB,
|
||||
.n = 1,
|
||||
.size = 256,
|
||||
.align = 1,
|
||||
.get = s390_tdb_get,
|
||||
.set = s390_tdb_set,
|
||||
},
|
||||
[REGSET_SYSTEM_CALL] = {
|
||||
{
|
||||
.core_note_type = NT_S390_SYSTEM_CALL,
|
||||
.n = 1,
|
||||
.size = sizeof(compat_uint_t),
|
||||
@@ -1284,7 +1400,41 @@ static const struct user_regset s390_compat_regsets[] = {
|
||||
.get = s390_system_call_get,
|
||||
.set = s390_system_call_set,
|
||||
},
|
||||
[REGSET_GENERAL_EXTENDED] = {
|
||||
{
|
||||
.core_note_type = NT_S390_LAST_BREAK,
|
||||
.n = 1,
|
||||
.size = sizeof(long),
|
||||
.align = sizeof(long),
|
||||
.get = s390_compat_last_break_get,
|
||||
.set = s390_compat_last_break_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_TDB,
|
||||
.n = 1,
|
||||
.size = 256,
|
||||
.align = 1,
|
||||
.get = s390_tdb_get,
|
||||
.set = s390_tdb_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_VXRS_LOW,
|
||||
.n = __NUM_VXRS_LOW,
|
||||
.size = sizeof(__u64),
|
||||
.align = sizeof(__u64),
|
||||
.active = s390_vxrs_active,
|
||||
.get = s390_vxrs_low_get,
|
||||
.set = s390_vxrs_low_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_VXRS_HIGH,
|
||||
.n = __NUM_VXRS_HIGH,
|
||||
.size = sizeof(__vector128),
|
||||
.align = sizeof(__vector128),
|
||||
.active = s390_vxrs_active,
|
||||
.get = s390_vxrs_high_get,
|
||||
.set = s390_vxrs_high_set,
|
||||
},
|
||||
{
|
||||
.core_note_type = NT_S390_HIGH_GPRS,
|
||||
.n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
|
||||
.size = sizeof(compat_long_t),
|
||||
|
Reference in New Issue
Block a user