Skip to content

Commit ef09f4f

Browse files
committed
Merge tag 'kvm-s390-next-5.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
KVM: s390: Fixes and cleanups for 5.6 - fix register corruption - ENOTSUPP/EOPNOTSUPP mixed - reset cleanups/fixes - selftests
2 parents df7e881 + b2ff728 commit ef09f4f

File tree

9 files changed

+354
-37
lines changed

9 files changed

+354
-37
lines changed

Documentation/virt/kvm/api.txt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4177,6 +4177,42 @@ This ioctl issues an ultravisor call to terminate the secure guest,
41774177
unpins the VPA pages and releases all the device pages that are used to
41784178
track the secure pages by hypervisor.
41794179

4180+
4.122 KVM_S390_NORMAL_RESET
4181+
4182+
Capability: KVM_CAP_S390_VCPU_RESETS
4183+
Architectures: s390
4184+
Type: vcpu ioctl
4185+
Parameters: none
4186+
Returns: 0
4187+
4188+
This ioctl resets VCPU registers and control structures according to
4189+
the cpu reset definition in the POP (Principles Of Operation).
4190+
4191+
4.123 KVM_S390_INITIAL_RESET
4192+
4193+
Capability: none
4194+
Architectures: s390
4195+
Type: vcpu ioctl
4196+
Parameters: none
4197+
Returns: 0
4198+
4199+
This ioctl resets VCPU registers and control structures according to
4200+
the initial cpu reset definition in the POP. However, the cpu is not
4201+
put into ESA mode. This reset is a superset of the normal reset.
4202+
4203+
4.124 KVM_S390_CLEAR_RESET
4204+
4205+
Capability: KVM_CAP_S390_VCPU_RESETS
4206+
Architectures: s390
4207+
Type: vcpu ioctl
4208+
Parameters: none
4209+
Returns: 0
4210+
4211+
This ioctl resets VCPU registers and control structures according to
4212+
the clear cpu reset definition in the POP. However, the cpu is not put
4213+
into ESA mode. This reset is a superset of the initial reset.
4214+
4215+
41804216
5. The kvm_run structure
41814217
------------------------
41824218

@@ -5405,3 +5441,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB
54055441
flush hypercalls by Hyper-V) so userspace should disable KVM identification
54065442
in CPUID and only exposes Hyper-V identification. In this case, guest
54075443
thinks it's running on Hyper-V and only use Hyper-V hypercalls.
5444+
5445+
8.22 KVM_CAP_S390_VCPU_RESETS
5446+
5447+
Architectures: s390
5448+
5449+
This capability indicates that the KVM_S390_NORMAL_RESET and
5450+
KVM_S390_CLEAR_RESET ioctls are available.

arch/s390/include/asm/kvm_host.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ struct mcck_volatile_info {
122122
__u32 reserved;
123123
};
124124

125+
#define CR0_INITIAL_MASK (CR0_UNUSED_56 | CR0_INTERRUPT_KEY_SUBMASK | \
126+
CR0_MEASUREMENT_ALERT_SUBMASK)
127+
#define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \
128+
CR14_EXTERNAL_DAMAGE_SUBMASK)
129+
125130
#define CPUSTAT_STOPPED 0x80000000
126131
#define CPUSTAT_WAIT 0x10000000
127132
#define CPUSTAT_ECALL_PEND 0x08000000

arch/s390/kvm/interrupt.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,7 +2190,7 @@ static int flic_ais_mode_get_all(struct kvm *kvm, struct kvm_device_attr *attr)
21902190
return -EINVAL;
21912191

21922192
if (!test_kvm_facility(kvm, 72))
2193-
return -ENOTSUPP;
2193+
return -EOPNOTSUPP;
21942194

21952195
mutex_lock(&fi->ais_lock);
21962196
ais.simm = fi->simm;
@@ -2499,7 +2499,7 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr)
24992499
int ret = 0;
25002500

25012501
if (!test_kvm_facility(kvm, 72))
2502-
return -ENOTSUPP;
2502+
return -EOPNOTSUPP;
25032503

25042504
if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
25052505
return -EFAULT;
@@ -2579,7 +2579,7 @@ static int flic_ais_mode_set_all(struct kvm *kvm, struct kvm_device_attr *attr)
25792579
struct kvm_s390_ais_all ais;
25802580

25812581
if (!test_kvm_facility(kvm, 72))
2582-
return -ENOTSUPP;
2582+
return -EOPNOTSUPP;
25832583

25842584
if (copy_from_user(&ais, (void __user *)attr->addr, sizeof(ais)))
25852585
return -EFAULT;

arch/s390/kvm/kvm-s390.c

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
529529
case KVM_CAP_S390_CMMA_MIGRATION:
530530
case KVM_CAP_S390_AIS:
531531
case KVM_CAP_S390_AIS_MIGRATION:
532+
case KVM_CAP_S390_VCPU_RESETS:
532533
r = 1;
533534
break;
534535
case KVM_CAP_S390_HPAGE_1M:
@@ -2808,35 +2809,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
28082809

28092810
}
28102811

2811-
static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
2812-
{
2813-
/* this equals initial cpu reset in pop, but we don't switch to ESA */
2814-
vcpu->arch.sie_block->gpsw.mask = 0UL;
2815-
vcpu->arch.sie_block->gpsw.addr = 0UL;
2816-
kvm_s390_set_prefix(vcpu, 0);
2817-
kvm_s390_set_cpu_timer(vcpu, 0);
2818-
vcpu->arch.sie_block->ckc = 0UL;
2819-
vcpu->arch.sie_block->todpr = 0;
2820-
memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
2821-
vcpu->arch.sie_block->gcr[0] = CR0_UNUSED_56 |
2822-
CR0_INTERRUPT_KEY_SUBMASK |
2823-
CR0_MEASUREMENT_ALERT_SUBMASK;
2824-
vcpu->arch.sie_block->gcr[14] = CR14_UNUSED_32 |
2825-
CR14_UNUSED_33 |
2826-
CR14_EXTERNAL_DAMAGE_SUBMASK;
2827-
/* make sure the new fpc will be lazily loaded */
2828-
save_fpu_regs();
2829-
current->thread.fpu.fpc = 0;
2830-
vcpu->arch.sie_block->gbea = 1;
2831-
vcpu->arch.sie_block->pp = 0;
2832-
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
2833-
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
2834-
kvm_clear_async_pf_completion_queue(vcpu);
2835-
if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
2836-
kvm_s390_vcpu_stop(vcpu);
2837-
kvm_s390_clear_local_irqs(vcpu);
2838-
}
2839-
28402812
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
28412813
{
28422814
mutex_lock(&vcpu->kvm->lock);
@@ -3279,10 +3251,53 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
32793251
return r;
32803252
}
32813253

3282-
static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
3254+
static void kvm_arch_vcpu_ioctl_normal_reset(struct kvm_vcpu *vcpu)
32833255
{
3284-
kvm_s390_vcpu_initial_reset(vcpu);
3285-
return 0;
3256+
vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI;
3257+
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
3258+
memset(vcpu->run->s.regs.riccb, 0, sizeof(vcpu->run->s.regs.riccb));
3259+
3260+
kvm_clear_async_pf_completion_queue(vcpu);
3261+
if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
3262+
kvm_s390_vcpu_stop(vcpu);
3263+
kvm_s390_clear_local_irqs(vcpu);
3264+
}
3265+
3266+
static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
3267+
{
3268+
/* Initial reset is a superset of the normal reset */
3269+
kvm_arch_vcpu_ioctl_normal_reset(vcpu);
3270+
3271+
/* this equals initial cpu reset in pop, but we don't switch to ESA */
3272+
vcpu->arch.sie_block->gpsw.mask = 0;
3273+
vcpu->arch.sie_block->gpsw.addr = 0;
3274+
kvm_s390_set_prefix(vcpu, 0);
3275+
kvm_s390_set_cpu_timer(vcpu, 0);
3276+
vcpu->arch.sie_block->ckc = 0;
3277+
vcpu->arch.sie_block->todpr = 0;
3278+
memset(vcpu->arch.sie_block->gcr, 0, sizeof(vcpu->arch.sie_block->gcr));
3279+
vcpu->arch.sie_block->gcr[0] = CR0_INITIAL_MASK;
3280+
vcpu->arch.sie_block->gcr[14] = CR14_INITIAL_MASK;
3281+
vcpu->run->s.regs.fpc = 0;
3282+
vcpu->arch.sie_block->gbea = 1;
3283+
vcpu->arch.sie_block->pp = 0;
3284+
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
3285+
}
3286+
3287+
static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
3288+
{
3289+
struct kvm_sync_regs *regs = &vcpu->run->s.regs;
3290+
3291+
/* Clear reset is a superset of the initial reset */
3292+
kvm_arch_vcpu_ioctl_initial_reset(vcpu);
3293+
3294+
memset(&regs->gprs, 0, sizeof(regs->gprs));
3295+
memset(&regs->vrs, 0, sizeof(regs->vrs));
3296+
memset(&regs->acrs, 0, sizeof(regs->acrs));
3297+
memset(&regs->gscb, 0, sizeof(regs->gscb));
3298+
3299+
regs->etoken = 0;
3300+
regs->etoken_extension = 0;
32863301
}
32873302

32883303
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -4343,7 +4358,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
43434358
switch (ioctl) {
43444359
case KVM_S390_STORE_STATUS:
43454360
idx = srcu_read_lock(&vcpu->kvm->srcu);
4346-
r = kvm_s390_vcpu_store_status(vcpu, arg);
4361+
r = kvm_s390_store_status_unloaded(vcpu, arg);
43474362
srcu_read_unlock(&vcpu->kvm->srcu, idx);
43484363
break;
43494364
case KVM_S390_SET_INITIAL_PSW: {
@@ -4355,8 +4370,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
43554370
r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
43564371
break;
43574372
}
4373+
case KVM_S390_CLEAR_RESET:
4374+
r = 0;
4375+
kvm_arch_vcpu_ioctl_clear_reset(vcpu);
4376+
break;
43584377
case KVM_S390_INITIAL_RESET:
4359-
r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
4378+
r = 0;
4379+
kvm_arch_vcpu_ioctl_initial_reset(vcpu);
4380+
break;
4381+
case KVM_S390_NORMAL_RESET:
4382+
r = 0;
4383+
kvm_arch_vcpu_ioctl_normal_reset(vcpu);
43604384
break;
43614385
case KVM_SET_ONE_REG:
43624386
case KVM_GET_ONE_REG: {

include/uapi/linux/kvm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,7 @@ struct kvm_ppc_resize_hpt {
10091009
#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176
10101010
#define KVM_CAP_ARM_NISV_TO_USER 177
10111011
#define KVM_CAP_ARM_INJECT_EXT_DABT 178
1012+
#define KVM_CAP_S390_VCPU_RESETS 179
10121013

10131014
#ifdef KVM_CAP_IRQ_ROUTING
10141015

@@ -1473,6 +1474,10 @@ struct kvm_enc_region {
14731474
/* Available with KVM_CAP_ARM_SVE */
14741475
#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int)
14751476

1477+
/* Available with KVM_CAP_S390_VCPU_RESETS */
1478+
#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3)
1479+
#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4)
1480+
14761481
/* Secure Encrypted Virtualization command */
14771482
enum sev_cmd_id {
14781483
/* Guest initialization commands */

tools/testing/selftests/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus
3636

3737
TEST_GEN_PROGS_s390x = s390x/memop
3838
TEST_GEN_PROGS_s390x += s390x/sync_regs_test
39+
TEST_GEN_PROGS_s390x += s390x/resets
3940
TEST_GEN_PROGS_s390x += dirty_log_test
4041
TEST_GEN_PROGS_s390x += kvm_create_max_vcpus
4142

tools/testing/selftests/kvm/include/kvm_util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,
125125
struct kvm_sregs *sregs);
126126
int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,
127127
struct kvm_sregs *sregs);
128+
void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid,
129+
struct kvm_fpu *fpu);
130+
void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid,
131+
struct kvm_fpu *fpu);
132+
void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg);
133+
void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg);
128134
#ifdef __KVM_HAVE_VCPU_EVENTS
129135
void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
130136
struct kvm_vcpu_events *events);

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,42 @@ int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
13731373
return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
13741374
}
13751375

1376+
void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu)
1377+
{
1378+
int ret;
1379+
1380+
ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_FPU, fpu);
1381+
TEST_ASSERT(ret == 0, "KVM_GET_FPU failed, rc: %i errno: %i (%s)",
1382+
ret, errno, strerror(errno));
1383+
}
1384+
1385+
void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu)
1386+
{
1387+
int ret;
1388+
1389+
ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_FPU, fpu);
1390+
TEST_ASSERT(ret == 0, "KVM_SET_FPU failed, rc: %i errno: %i (%s)",
1391+
ret, errno, strerror(errno));
1392+
}
1393+
1394+
void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg)
1395+
{
1396+
int ret;
1397+
1398+
ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, reg);
1399+
TEST_ASSERT(ret == 0, "KVM_GET_ONE_REG failed, rc: %i errno: %i (%s)",
1400+
ret, errno, strerror(errno));
1401+
}
1402+
1403+
void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg)
1404+
{
1405+
int ret;
1406+
1407+
ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, reg);
1408+
TEST_ASSERT(ret == 0, "KVM_SET_ONE_REG failed, rc: %i errno: %i (%s)",
1409+
ret, errno, strerror(errno));
1410+
}
1411+
13761412
/*
13771413
* VCPU Ioctl
13781414
*

0 commit comments

Comments
 (0)