summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/nmi.h3
-rw-r--r--arch/s390/kernel/nmi.c5
-rw-r--r--arch/s390/kvm/guestdbg.c9
-rw-r--r--arch/s390/kvm/interrupt.c26
-rw-r--r--arch/s390/kvm/kvm-s390.c22
5 files changed, 34 insertions, 31 deletions
diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h
index 6454c1531854..7919b2b9ac9c 100644
--- a/arch/s390/include/asm/nmi.h
+++ b/arch/s390/include/asm/nmi.h
@@ -22,6 +22,7 @@
#define MCCK_CODE_SYSTEM_DAMAGE BIT(63)
#define MCCK_CODE_EXT_DAMAGE BIT(63 - 5)
#define MCCK_CODE_CP BIT(63 - 9)
+#define MCCK_CODE_CK BIT(63 - 11)
#define MCCK_CODE_STG_ERROR BIT(63 - 16)
#define MCCK_CODE_STG_KEY_ERROR BIT(63 - 18)
#define MCCK_CODE_STG_DEGRAD BIT(63 - 19)
@@ -33,6 +34,8 @@
#define MCCK_CODE_FC_VALID BIT(63 - 43)
#define MCCK_CODE_CPU_TIMER_VALID BIT(63 - 46)
+#define MCCK_CODE_NO_GUEST (MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE | MCCK_CODE_CK)
+
#ifndef __ASSEMBLER__
union mci {
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index e17a59d4d5a4..17297a8b63d9 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -344,8 +344,7 @@ static void notrace s390_backup_mcck_info(struct pt_regs *regs)
sie_page = container_of(sie_block, struct sie_page, sie_block);
mcck_backup = &sie_page->mcck_info;
- mcck_backup->mcic = get_lowcore()->mcck_interruption_code &
- ~(MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE);
+ mcck_backup->mcic = get_lowcore()->mcck_interruption_code & ~MCCK_CODE_NO_GUEST;
mcck_backup->ext_damage_code = get_lowcore()->external_damage_code;
mcck_backup->failing_storage_address = get_lowcore()->failing_storage_address;
}
@@ -357,8 +356,6 @@ NOKPROBE_SYMBOL(s390_backup_mcck_info);
#define ED_STP_ISLAND 6 /* External damage STP island check */
#define ED_STP_SYNC 7 /* External damage STP sync check */
-#define MCCK_CODE_NO_GUEST (MCCK_CODE_CP | MCCK_CODE_EXT_DAMAGE)
-
/*
* machine check handler.
*/
diff --git a/arch/s390/kvm/guestdbg.c b/arch/s390/kvm/guestdbg.c
index 69835e1d4f20..9a6149e310bb 100644
--- a/arch/s390/kvm/guestdbg.c
+++ b/arch/s390/kvm/guestdbg.c
@@ -184,7 +184,7 @@ static int __import_wp_info(struct kvm_vcpu *vcpu,
if (wp_info->len < 0 || wp_info->len > MAX_WP_SIZE)
return -EINVAL;
- wp_info->old_data = kmalloc(bp_data->len, GFP_KERNEL_ACCOUNT);
+ wp_info->old_data = kmalloc(wp_info->len, GFP_KERNEL_ACCOUNT);
if (!wp_info->old_data)
return -ENOMEM;
/* try to backup the original value */
@@ -252,7 +252,7 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
ret = __import_wp_info(vcpu, &bp_data[i],
&wp_info[nr_wp]);
if (ret)
- goto error;
+ goto error_wp;
nr_wp++;
break;
case KVM_HW_BP:
@@ -267,7 +267,12 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
vcpu->arch.guestdbg.hw_bp_info = bp_info;
vcpu->arch.guestdbg.nr_hw_wp = nr_wp;
vcpu->arch.guestdbg.hw_wp_info = wp_info;
+ kfree(bp_data);
return 0;
+
+error_wp:
+ while (nr_wp--)
+ kfree(wp_info[nr_wp].old_data);
error:
kfree(bp_data);
kfree(wp_info);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 8f24bcd1a6d3..d33dd58f4a4f 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -3108,9 +3108,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
struct mcck_volatile_info *mcck_info)
{
- struct kvm_s390_interrupt_info inti;
- struct kvm_s390_irq irq;
- struct kvm_s390_mchk_info *mchk;
+ struct kvm_s390_irq irq = {};
union mci mci;
__u64 cr14 = 0; /* upper bits are not used */
int rc;
@@ -3129,20 +3127,14 @@ void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
if (mci.w)
cr14 |= CR14_WARNING_SUBMASK;
- mchk = mci.ck ? &inti.mchk : &irq.u.mchk;
- mchk->cr14 = cr14;
- mchk->mcic = mcck_info->mcic;
- mchk->ext_damage_code = mcck_info->ext_damage_code;
- mchk->failing_storage_address = mcck_info->failing_storage_address;
- if (mci.ck) {
- /* Inject the floating machine check */
- inti.type = KVM_S390_MCHK;
- rc = __inject_vm(vcpu->kvm, &inti);
- } else {
- /* Inject the machine check to specified vcpu */
- irq.type = KVM_S390_MCHK;
- rc = kvm_s390_inject_vcpu(vcpu, &irq);
- }
+ irq.u.mchk.cr14 = cr14;
+ irq.u.mchk.mcic = mcck_info->mcic;
+ irq.u.mchk.ext_damage_code = mcck_info->ext_damage_code;
+ irq.u.mchk.failing_storage_address = mcck_info->failing_storage_address;
+
+ /* Inject the machine check to specified vcpu */
+ irq.type = KVM_S390_MCHK;
+ rc = kvm_s390_inject_vcpu(vcpu, &irq);
WARN_ON_ONCE(rc);
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 518a69c55e85..17aa38710170 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -562,11 +562,12 @@ static void __kvm_s390_exit(void)
static int kvm_s390_keyop(struct kvm_s390_mmu_cache *mc, struct kvm *kvm, int op,
unsigned long addr, union skey skey)
{
- union asce asce = kvm->arch.gmap->asce;
gfn_t gfn = gpa_to_gfn(addr);
+ union asce asce;
int r;
guard(read_lock)(&kvm->mmu_lock);
+ asce = kvm->arch.gmap->asce;
switch (op) {
case KVM_S390_KEYOP_SSKE:
@@ -3410,6 +3411,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
kvm_s390_clear_local_irqs(vcpu);
kvm_clear_async_pf_completion_queue(vcpu);
+ kvm_s390_clear_bp_data(vcpu);
if (!kvm_is_ucontrol(vcpu->kvm))
sca_del_vcpu(vcpu);
kvm_s390_update_topology_change_report(vcpu->kvm, 1);
@@ -4248,8 +4250,10 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
/* enforce guest PER */
kvm_s390_set_cpuflags(vcpu, CPUSTAT_P);
- if (dbg->control & KVM_GUESTDBG_USE_HW_BP)
- rc = kvm_s390_import_bp_data(vcpu, dbg);
+ if (dbg->control & KVM_GUESTDBG_USE_HW_BP) {
+ scoped_guard(srcu, &vcpu->kvm->srcu)
+ rc = kvm_s390_import_bp_data(vcpu, dbg);
+ }
} else {
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_P);
vcpu->arch.guestdbg.last_bp = 0;
@@ -4474,8 +4478,8 @@ int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clo
static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,
unsigned long token)
{
- struct kvm_s390_interrupt inti;
- struct kvm_s390_irq irq;
+ struct kvm_s390_interrupt inti = {};
+ struct kvm_s390_irq irq = {};
struct kvm_s390_interrupt_info *inti_mem = NULL;
int ret = 0;
@@ -5069,7 +5073,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
pr_err_ratelimited("can't run stopped vcpu %d\n",
vcpu->vcpu_id);
rc = -EINVAL;
- goto out;
+ goto out_sigset;
}
kernel_fpu_begin(&fpu, KERNEL_FPC | KERNEL_VXR);
@@ -5099,9 +5103,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
store_regs(vcpu);
kernel_fpu_end(&fpu, KERNEL_FPC | KERNEL_VXR);
+ vcpu->stat.exit_userspace++;
+
+out_sigset:
kvm_sigset_deactivate(vcpu);
- vcpu->stat.exit_userspace++;
out:
vcpu_put(vcpu);
return rc;
@@ -5732,7 +5738,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = kvm_s390_handle_pv_vcpu_dump(vcpu, &cmd);
/* Always copy over UV rc / rrc data */
- if (copy_to_user((__u8 __user *)argp, &cmd.rc,
+ if (copy_to_user(argp + offsetof(struct kvm_pv_cmd, rc), &cmd.rc,
sizeof(cmd.rc) + sizeof(cmd.rrc)))
r = -EFAULT;
break;