Commit 9c69481e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Martin Schwidefsky:
 "One improvement for the zcrypt driver, the quality attribute for the
  hwrng device has been missing.  Without it the kernel entropy seeding
  will not happen automatically.

  And six bug fixes, the most important one is the fix for the vector
  register corruption due to machine checks"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/nmi: fix vector register corruption
  s390/process: fix sfpc inline assembly
  s390/dasd: fix kernel panic when alias is set offline
  s390/sclp: clear upper register halves in _sclp_print_early
  s390/oprofile: fix compile error
  s390/sclp: fix compile error
  s390/zcrypt: enable s390 hwrng to seed kernel entropy
parents 97d6e2b6 cad49cfc
...@@ -57,7 +57,10 @@ union ctlreg0 { ...@@ -57,7 +57,10 @@ union ctlreg0 {
unsigned long lap : 1; /* Low-address-protection control */ unsigned long lap : 1; /* Low-address-protection control */
unsigned long : 4; unsigned long : 4;
unsigned long edat : 1; /* Enhanced-DAT-enablement control */ unsigned long edat : 1; /* Enhanced-DAT-enablement control */
unsigned long : 23; unsigned long : 4;
unsigned long afp : 1; /* AFP-register control */
unsigned long vx : 1; /* Vector enablement control */
unsigned long : 17;
}; };
}; };
......
...@@ -87,7 +87,15 @@ struct sf_raw_sample { ...@@ -87,7 +87,15 @@ struct sf_raw_sample {
} __packed; } __packed;
/* Perf hardware reserve and release functions */ /* Perf hardware reserve and release functions */
#ifdef CONFIG_PERF_EVENTS
int perf_reserve_sampling(void); int perf_reserve_sampling(void);
void perf_release_sampling(void); void perf_release_sampling(void);
#else /* CONFIG_PERF_EVENTS */
static inline int perf_reserve_sampling(void)
{
return 0;
}
static inline void perf_release_sampling(void) {}
#endif /* CONFIG_PERF_EVENTS */
#endif /* _ASM_S390_PERF_EVENT_H */ #endif /* _ASM_S390_PERF_EVENT_H */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/crw.h> #include <asm/crw.h>
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/ctl_reg.h>
struct mcck_struct { struct mcck_struct {
int kill_task; int kill_task;
...@@ -129,26 +130,30 @@ static int notrace s390_revalidate_registers(struct mci *mci) ...@@ -129,26 +130,30 @@ static int notrace s390_revalidate_registers(struct mci *mci)
} else } else
asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area)); asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
asm volatile( if (!MACHINE_HAS_VX) {
" ld 0,0(%0)\n" /* Revalidate floating point registers */
" ld 1,8(%0)\n" asm volatile(
" ld 2,16(%0)\n" " ld 0,0(%0)\n"
" ld 3,24(%0)\n" " ld 1,8(%0)\n"
" ld 4,32(%0)\n" " ld 2,16(%0)\n"
" ld 5,40(%0)\n" " ld 3,24(%0)\n"
" ld 6,48(%0)\n" " ld 4,32(%0)\n"
" ld 7,56(%0)\n" " ld 5,40(%0)\n"
" ld 8,64(%0)\n" " ld 6,48(%0)\n"
" ld 9,72(%0)\n" " ld 7,56(%0)\n"
" ld 10,80(%0)\n" " ld 8,64(%0)\n"
" ld 11,88(%0)\n" " ld 9,72(%0)\n"
" ld 12,96(%0)\n" " ld 10,80(%0)\n"
" ld 13,104(%0)\n" " ld 11,88(%0)\n"
" ld 14,112(%0)\n" " ld 12,96(%0)\n"
" ld 15,120(%0)\n" " ld 13,104(%0)\n"
: : "a" (fpt_save_area)); " ld 14,112(%0)\n"
/* Revalidate vector registers */ " ld 15,120(%0)\n"
if (MACHINE_HAS_VX && current->thread.vxrs) { : : "a" (fpt_save_area));
} else {
/* Revalidate vector registers */
union ctlreg0 cr0;
if (!mci->vr) { if (!mci->vr) {
/* /*
* Vector registers can't be restored and therefore * Vector registers can't be restored and therefore
...@@ -156,8 +161,12 @@ static int notrace s390_revalidate_registers(struct mci *mci) ...@@ -156,8 +161,12 @@ static int notrace s390_revalidate_registers(struct mci *mci)
*/ */
kill_task = 1; kill_task = 1;
} }
cr0.val = S390_lowcore.cregs_save_area[0];
cr0.afp = cr0.vx = 1;
__ctl_load(cr0.val, 0, 0);
restore_vx_regs((__vector128 *) restore_vx_regs((__vector128 *)
S390_lowcore.vector_save_area_addr); &S390_lowcore.vector_save_area);
__ctl_load(S390_lowcore.cregs_save_area[0], 0, 0);
} }
/* Revalidate access registers */ /* Revalidate access registers */
asm volatile( asm volatile(
......
...@@ -163,7 +163,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, ...@@ -163,7 +163,7 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
asmlinkage void execve_tail(void) asmlinkage void execve_tail(void)
{ {
current->thread.fp_regs.fpc = 0; current->thread.fp_regs.fpc = 0;
asm volatile("sfpc %0,%0" : : "d" (0)); asm volatile("sfpc %0" : : "d" (0));
} }
/* /*
......
...@@ -270,6 +270,8 @@ ENTRY(_sclp_print_early) ...@@ -270,6 +270,8 @@ ENTRY(_sclp_print_early)
jno .Lesa2 jno .Lesa2
ahi %r15,-80 ahi %r15,-80
stmh %r6,%r15,96(%r15) # store upper register halves stmh %r6,%r15,96(%r15) # store upper register halves
basr %r13,0
lmh %r0,%r15,.Lzeroes-.(%r13) # clear upper register halves
.Lesa2: .Lesa2:
lr %r10,%r2 # save string pointer lr %r10,%r2 # save string pointer
lhi %r2,0 lhi %r2,0
...@@ -291,6 +293,8 @@ ENTRY(_sclp_print_early) ...@@ -291,6 +293,8 @@ ENTRY(_sclp_print_early)
.Lesa3: .Lesa3:
lm %r6,%r15,120(%r15) # restore registers lm %r6,%r15,120(%r15) # restore registers
br %r14 br %r14
.Lzeroes:
.fill 64,4,0
.LwritedataS4: .LwritedataS4:
.long 0x00760005 # SCLP command for write data .long 0x00760005 # SCLP command for write data
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/perf_event.h>
#include "../../../drivers/oprofile/oprof.h" #include "../../../drivers/oprofile/oprof.h"
......
...@@ -1862,6 +1862,33 @@ static void __dasd_device_check_expire(struct dasd_device *device) ...@@ -1862,6 +1862,33 @@ static void __dasd_device_check_expire(struct dasd_device *device)
} }
} }
/*
* return 1 when device is not eligible for IO
*/
static int __dasd_device_is_unusable(struct dasd_device *device,
struct dasd_ccw_req *cqr)
{
int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM);
if (test_bit(DASD_FLAG_OFFLINE, &device->flags)) {
/* dasd is being set offline. */
return 1;
}
if (device->stopped) {
if (device->stopped & mask) {
/* stopped and CQR will not change that. */
return 1;
}
if (!test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags)) {
/* CQR is not able to change device to
* operational. */
return 1;
}
/* CQR required to get device operational. */
}
return 0;
}
/* /*
* Take a look at the first request on the ccw queue and check * Take a look at the first request on the ccw queue and check
* if it needs to be started. * if it needs to be started.
...@@ -1876,13 +1903,8 @@ static void __dasd_device_start_head(struct dasd_device *device) ...@@ -1876,13 +1903,8 @@ static void __dasd_device_start_head(struct dasd_device *device)
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist); cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
if (cqr->status != DASD_CQR_QUEUED) if (cqr->status != DASD_CQR_QUEUED)
return; return;
/* when device is stopped, return request to previous layer /* if device is not usable return request to upper layer */
* exception: only the disconnect or unresumed bits are set and the if (__dasd_device_is_unusable(device, cqr)) {
* cqr is a path verification request
*/
if (device->stopped &&
!(!(device->stopped & ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
&& test_bit(DASD_CQR_VERIFY_PATH, &cqr->flags))) {
cqr->intrc = -EAGAIN; cqr->intrc = -EAGAIN;
cqr->status = DASD_CQR_CLEARED; cqr->status = DASD_CQR_CLEARED;
dasd_schedule_device_bh(device); dasd_schedule_device_bh(device);
......
...@@ -699,7 +699,8 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device) ...@@ -699,7 +699,8 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
struct dasd_device, alias_list); struct dasd_device, alias_list);
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
alias_priv = (struct dasd_eckd_private *) alias_device->private; alias_priv = (struct dasd_eckd_private *) alias_device->private;
if ((alias_priv->count < private->count) && !alias_device->stopped) if ((alias_priv->count < private->count) && !alias_device->stopped &&
!test_bit(DASD_FLAG_OFFLINE, &alias_device->flags))
return alias_device; return alias_device;
else else
return NULL; return NULL;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define KMSG_COMPONENT "sclp_early" #define KMSG_COMPONENT "sclp_early"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/errno.h>
#include <asm/ctl_reg.h> #include <asm/ctl_reg.h>
#include <asm/sclp.h> #include <asm/sclp.h>
#include <asm/ipl.h> #include <asm/ipl.h>
......
...@@ -54,6 +54,10 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \ ...@@ -54,6 +54,10 @@ MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \
"Copyright IBM Corp. 2001, 2012"); "Copyright IBM Corp. 2001, 2012");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int zcrypt_hwrng_seed = 1;
module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, S_IRUSR|S_IRGRP);
MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on).");
static DEFINE_SPINLOCK(zcrypt_device_lock); static DEFINE_SPINLOCK(zcrypt_device_lock);
static LIST_HEAD(zcrypt_device_list); static LIST_HEAD(zcrypt_device_list);
static int zcrypt_device_count = 0; static int zcrypt_device_count = 0;
...@@ -1373,6 +1377,7 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data) ...@@ -1373,6 +1377,7 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
static struct hwrng zcrypt_rng_dev = { static struct hwrng zcrypt_rng_dev = {
.name = "zcrypt", .name = "zcrypt",
.data_read = zcrypt_rng_data_read, .data_read = zcrypt_rng_data_read,
.quality = 990,
}; };
static int zcrypt_rng_device_add(void) static int zcrypt_rng_device_add(void)
...@@ -1387,6 +1392,8 @@ static int zcrypt_rng_device_add(void) ...@@ -1387,6 +1392,8 @@ static int zcrypt_rng_device_add(void)
goto out; goto out;
} }
zcrypt_rng_buffer_index = 0; zcrypt_rng_buffer_index = 0;
if (!zcrypt_hwrng_seed)
zcrypt_rng_dev.quality = 0;
rc = hwrng_register(&zcrypt_rng_dev); rc = hwrng_register(&zcrypt_rng_dev);
if (rc) if (rc)
goto out_free; goto out_free;
......
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