History

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

Paolo Bonzini committed 6 years ago

Commit ef09f4f2 parents df7e881 b2ff7289 files · +354 −37Browse files

Unified · Split

9 files
  1. Documentation/virt/kvm/api.txt +43 −0
  2. arch/s390/include/asm/kvm_host.h +5 −0
  3. arch/s390/kvm/interrupt.c +3 −3
  4. arch/s390/kvm/kvm-s390.c +58 −34
  5. include/uapi/linux/kvm.h +5 −0
  6. tools/testing/selftests/kvm/Makefile +1 −0
  7. tools/testing/selftests/kvm/include/kvm_util.h +6 −0
  8. tools/testing/selftests/kvm/lib/kvm_util.c +36 −0
  9. tools/testing/selftests/kvm/s390x/resets.c +197 −0
Documentation/virt/kvm/api.txt+43−0
@@ -4177,6 +4177,42 @@ This ioctl issues an ultravisor call to terminate the secure guest, · 4176 unmodified lines
4177unpins the VPA pages and releases all the device pages that are used to4177unpins the VPA pages and releases all the device pages that are used to
4178track the secure pages by hypervisor.4178track the secure pages by hypervisor.
4179 4179
41804.122 KVM_S390_NORMAL_RESET
4181
4182Capability: KVM_CAP_S390_VCPU_RESETS
4183Architectures: s390
4184Type: vcpu ioctl
4185Parameters: none
4186Returns: 0
4187
4188This ioctl resets VCPU registers and control structures according to
4189the cpu reset definition in the POP (Principles Of Operation).
4190
41914.123 KVM_S390_INITIAL_RESET
4192
4193Capability: none
4194Architectures: s390
4195Type: vcpu ioctl
4196Parameters: none
4197Returns: 0
4198
4199This ioctl resets VCPU registers and control structures according to
4200the initial cpu reset definition in the POP. However, the cpu is not
4201put into ESA mode. This reset is a superset of the normal reset.
4202
42034.124 KVM_S390_CLEAR_RESET
4204
4205Capability: KVM_CAP_S390_VCPU_RESETS
4206Architectures: s390
4207Type: vcpu ioctl
4208Parameters: none
4209Returns: 0
4210
4211This ioctl resets VCPU registers and control structures according to
4212the clear cpu reset definition in the POP. However, the cpu is not put
4213into ESA mode. This reset is a superset of the initial reset.
4214
4215
41805. The kvm_run structure42165. The kvm_run structure
4181------------------------4217------------------------
4182 4218
@@ -5405,3 +5441,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB · 1222 unmodified lines
5405flush hypercalls by Hyper-V) so userspace should disable KVM identification5441flush hypercalls by Hyper-V) so userspace should disable KVM identification
5406in CPUID and only exposes Hyper-V identification. In this case, guest5442in CPUID and only exposes Hyper-V identification. In this case, guest
5407thinks it's running on Hyper-V and only use Hyper-V hypercalls.5443thinks it's running on Hyper-V and only use Hyper-V hypercalls.
5444
54458.22 KVM_CAP_S390_VCPU_RESETS
5446
5447Architectures: s390
5448
5449This capability indicates that the KVM_S390_NORMAL_RESET and
5450KVM_S390_CLEAR_RESET ioctls are available.
arch/s390/include/asm/kvm_host.h+5−0
@@ -122,6 +122,11 @@ struct mcck_volatile_info { · 121 unmodified lines
122 __u32 reserved;122 __u32 reserved;
123};123};
124 124
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
125#define CPUSTAT_STOPPED 0x80000000130#define CPUSTAT_STOPPED 0x80000000
126#define CPUSTAT_WAIT 0x10000000131#define CPUSTAT_WAIT 0x10000000
127#define CPUSTAT_ECALL_PEND 0x08000000132#define CPUSTAT_ECALL_PEND 0x08000000
arch/s390/kvm/interrupt.c+3−3
@@ -2190,7 +2190,7 @@ static int flic_ais_mode_get_all(struct kvm *kvm, struct kvm_device_attr *attr) · 2189 unmodified lines
2190 return -EINVAL;2190 return -EINVAL;
2191 2191
2192 if (!test_kvm_facility(kvm, 72))2192 if (!test_kvm_facility(kvm, 72))
2193 return -ENOTSUPP;2193 return -EOPNOTSUPP;
2194 2194
2195 mutex_lock(&fi->ais_lock);2195 mutex_lock(&fi->ais_lock);
2196 ais.simm = fi->simm;2196 ais.simm = fi->simm;
@@ -2499,7 +2499,7 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr) · 302 unmodified lines
2499 int ret = 0;2499 int ret = 0;
2500 2500
2501 if (!test_kvm_facility(kvm, 72))2501 if (!test_kvm_facility(kvm, 72))
2502 return -ENOTSUPP;2502 return -EOPNOTSUPP;
2503 2503
2504 if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))2504 if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
2505 return -EFAULT;2505 return -EFAULT;
@@ -2579,7 +2579,7 @@ static int flic_ais_mode_set_all(struct kvm *kvm, struct kvm_device_attr *attr) · 73 unmodified lines
2579 struct kvm_s390_ais_all ais;2579 struct kvm_s390_ais_all ais;
2580 2580
2581 if (!test_kvm_facility(kvm, 72))2581 if (!test_kvm_facility(kvm, 72))
2582 return -ENOTSUPP;2582 return -EOPNOTSUPP;
2583 2583
2584 if (copy_from_user(&ais, (void __user *)attr->addr, sizeof(ais)))2584 if (copy_from_user(&ais, (void __user *)attr->addr, sizeof(ais)))
2585 return -EFAULT;2585 return -EFAULT;
arch/s390/kvm/kvm-s390.c+58−34
@@ -529,6 +529,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 528 unmodified lines
529 case KVM_CAP_S390_CMMA_MIGRATION:529 case KVM_CAP_S390_CMMA_MIGRATION:
530 case KVM_CAP_S390_AIS:530 case KVM_CAP_S390_AIS:
531 case KVM_CAP_S390_AIS_MIGRATION:531 case KVM_CAP_S390_AIS_MIGRATION:
532 case KVM_CAP_S390_VCPU_RESETS:
532 r = 1;533 r = 1;
533 break;534 break;
534 case KVM_CAP_S390_HPAGE_1M:535 case KVM_CAP_S390_HPAGE_1M:
@@ -2808,35 +2809,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) · 2273 unmodified lines
2808 2809
2809}2810}
2810 2811
2811static 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
2840void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)2812void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
2841{2813{
2842 mutex_lock(&vcpu->kvm->lock);2814 mutex_lock(&vcpu->kvm->lock);
@@ -3279,10 +3251,53 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, · 436 unmodified lines
3279 return r;3251 return r;
3280}3252}
3281 3253
3282static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)3254static void kvm_arch_vcpu_ioctl_normal_reset(struct kvm_vcpu *vcpu)
3283{3255{
3284 kvm_s390_vcpu_initial_reset(vcpu);3256 vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI;
3285 return 0;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
3266static 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
3287static 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;
3286}3301}
3287 3302
3288int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)3303int 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, · 1054 unmodified lines
4343 switch (ioctl) {4358 switch (ioctl) {
4344 case KVM_S390_STORE_STATUS:4359 case KVM_S390_STORE_STATUS:
4345 idx = srcu_read_lock(&vcpu->kvm->srcu);4360 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);
4347 srcu_read_unlock(&vcpu->kvm->srcu, idx);4362 srcu_read_unlock(&vcpu->kvm->srcu, idx);
4348 break;4363 break;
4349 case KVM_S390_SET_INITIAL_PSW: {4364 case KVM_S390_SET_INITIAL_PSW: {
@@ -4355,8 +4370,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 5 unmodified lines
4355 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);4370 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
4356 break;4371 break;
4357 }4372 }
4373 case KVM_S390_CLEAR_RESET:
4374 r = 0;
4375 kvm_arch_vcpu_ioctl_clear_reset(vcpu);
4376 break;
4358 case KVM_S390_INITIAL_RESET:4377 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);
4360 break;4384 break;
4361 case KVM_SET_ONE_REG:4385 case KVM_SET_ONE_REG:
4362 case KVM_GET_ONE_REG: {4386 case KVM_GET_ONE_REG: {
include/uapi/linux/kvm.h+5−0
@@ -1009,6 +1009,7 @@ struct kvm_ppc_resize_hpt { · 1008 unmodified lines
1009#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 1761009#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176
1010#define KVM_CAP_ARM_NISV_TO_USER 1771010#define KVM_CAP_ARM_NISV_TO_USER 177
1011#define KVM_CAP_ARM_INJECT_EXT_DABT 1781011#define KVM_CAP_ARM_INJECT_EXT_DABT 178
1012#define KVM_CAP_S390_VCPU_RESETS 179
1012 1013
1013#ifdef KVM_CAP_IRQ_ROUTING1014#ifdef KVM_CAP_IRQ_ROUTING
1014 1015
@@ -1473,6 +1474,10 @@ struct kvm_enc_region { · 458 unmodified lines
1473/* Available with KVM_CAP_ARM_SVE */1474/* Available with KVM_CAP_ARM_SVE */
1474#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int)1475#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int)
1475 1476
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
1476/* Secure Encrypted Virtualization command */1481/* Secure Encrypted Virtualization command */
1477enum sev_cmd_id {1482enum sev_cmd_id {
1478 /* Guest initialization commands */1483 /* Guest initialization commands */
tools/testing/selftests/kvm/Makefile+1−0
@@ -36,6 +36,7 @@ TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus · 35 unmodified lines
36 36
37TEST_GEN_PROGS_s390x = s390x/memop37TEST_GEN_PROGS_s390x = s390x/memop
38TEST_GEN_PROGS_s390x += s390x/sync_regs_test38TEST_GEN_PROGS_s390x += s390x/sync_regs_test
39TEST_GEN_PROGS_s390x += s390x/resets
39TEST_GEN_PROGS_s390x += dirty_log_test40TEST_GEN_PROGS_s390x += dirty_log_test
40TEST_GEN_PROGS_s390x += kvm_create_max_vcpus41TEST_GEN_PROGS_s390x += kvm_create_max_vcpus
41 42
tools/testing/selftests/kvm/include/kvm_util.h+6−0
@@ -125,6 +125,12 @@ void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, · 124 unmodified lines
125 struct kvm_sregs *sregs);125 struct kvm_sregs *sregs);
126int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,126int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid,
127 struct kvm_sregs *sregs);127 struct kvm_sregs *sregs);
128void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid,
129 struct kvm_fpu *fpu);
130void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid,
131 struct kvm_fpu *fpu);
132void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg);
133void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg);
128#ifdef __KVM_HAVE_VCPU_EVENTS134#ifdef __KVM_HAVE_VCPU_EVENTS
129void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,135void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
130 struct kvm_vcpu_events *events);136 struct kvm_vcpu_events *events);
tools/testing/selftests/kvm/lib/kvm_util.c+36−0
@@ -1373,6 +1373,42 @@ int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs) · 1372 unmodified lines
1373 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);1373 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
1374}1374}
1375 1375
1376void 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
1385void 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
1394void 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
1403void 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
1376/*1412/*
1377 * VCPU Ioctl1413 * VCPU Ioctl
1378 *1414 *
tools/testing/selftests/kvm/s390x/resets.c+197−0
@@ -0,0 +1,197 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Test for s390x CPU resets
4 *
5 * Copyright (C) 2020, IBM
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/ioctl.h>
12
13#include "test_util.h"
14#include "kvm_util.h"
15
16#define VCPU_ID 3
17#define LOCAL_IRQS 32
18
19struct kvm_s390_irq buf[VCPU_ID + LOCAL_IRQS];
20
21struct kvm_vm *vm;
22struct kvm_run *run;
23struct kvm_sync_regs *regs;
24static uint64_t regs_null[16];
25
26static uint64_t crs[16] = { 0x40000ULL,
27 0x42000ULL,
28 0, 0, 0, 0, 0,
29 0x43000ULL,
30 0, 0, 0, 0, 0,
31 0x44000ULL,
32 0, 0
33};
34
35static void guest_code_initial(void)
36{
37 /* Round toward 0 */
38 uint32_t fpc = 0x11;
39
40 /* Dirty registers */
41 asm volatile (
42 " lctlg 0,15,%0\n"
43 " sfpc %1\n"
44 : : "Q" (crs), "d" (fpc));
45 GUEST_SYNC(0);
46}
47
48static void test_one_reg(uint64_t id, uint64_t value)
49{
50 struct kvm_one_reg reg;
51 uint64_t eval_reg;
52
53 reg.addr = (uintptr_t)&eval_reg;
54 reg.id = id;
55 vcpu_get_reg(vm, VCPU_ID, &reg);
56 TEST_ASSERT(eval_reg == value, "value == %s", value);
57}
58
59static void assert_noirq(void)
60{
61 struct kvm_s390_irq_state irq_state;
62 int irqs;
63
64 irq_state.len = sizeof(buf);
65 irq_state.buf = (unsigned long)buf;
66 irqs = _vcpu_ioctl(vm, VCPU_ID, KVM_S390_GET_IRQ_STATE, &irq_state);
67 /*
68 * irqs contains the number of retrieved interrupts. Any interrupt
69 * (notably, the emergency call interrupt we have injected) should
70 * be cleared by the resets, so this should be 0.
71 */
72 TEST_ASSERT(irqs >= 0, "Could not fetch IRQs: errno %d\n", errno);
73 TEST_ASSERT(!irqs, "IRQ pending");
74}
75
76static void assert_clear(void)
77{
78 struct kvm_sregs sregs;
79 struct kvm_regs regs;
80 struct kvm_fpu fpu;
81
82 vcpu_regs_get(vm, VCPU_ID, &regs);
83 TEST_ASSERT(!memcmp(&regs.gprs, regs_null, sizeof(regs.gprs)), "grs == 0");
84
85 vcpu_sregs_get(vm, VCPU_ID, &sregs);
86 TEST_ASSERT(!memcmp(&sregs.acrs, regs_null, sizeof(sregs.acrs)), "acrs == 0");
87
88 vcpu_fpu_get(vm, VCPU_ID, &fpu);
89 TEST_ASSERT(!memcmp(&fpu.fprs, regs_null, sizeof(fpu.fprs)), "fprs == 0");
90}
91
92static void assert_initial(void)
93{
94 struct kvm_sregs sregs;
95 struct kvm_fpu fpu;
96
97 vcpu_sregs_get(vm, VCPU_ID, &sregs);
98 TEST_ASSERT(sregs.crs[0] == 0xE0UL, "cr0 == 0xE0");
99 TEST_ASSERT(sregs.crs[14] == 0xC2000000UL, "cr14 == 0xC2000000");
100 TEST_ASSERT(!memcmp(&sregs.crs[1], regs_null, sizeof(sregs.crs[1]) * 12),
101 "cr1-13 == 0");
102 TEST_ASSERT(sregs.crs[15] == 0, "cr15 == 0");
103
104 vcpu_fpu_get(vm, VCPU_ID, &fpu);
105 TEST_ASSERT(!fpu.fpc, "fpc == 0");
106
107 test_one_reg(KVM_REG_S390_GBEA, 1);
108 test_one_reg(KVM_REG_S390_PP, 0);
109 test_one_reg(KVM_REG_S390_TODPR, 0);
110 test_one_reg(KVM_REG_S390_CPU_TIMER, 0);
111 test_one_reg(KVM_REG_S390_CLOCK_COMP, 0);
112}
113
114static void assert_normal(void)
115{
116 test_one_reg(KVM_REG_S390_PFTOKEN, KVM_S390_PFAULT_TOKEN_INVALID);
117 assert_noirq();
118}
119
120static void inject_irq(int cpu_id)
121{
122 struct kvm_s390_irq_state irq_state;
123 struct kvm_s390_irq *irq = &buf[0];
124 int irqs;
125
126 /* Inject IRQ */
127 irq_state.len = sizeof(struct kvm_s390_irq);
128 irq_state.buf = (unsigned long)buf;
129 irq->type = KVM_S390_INT_EMERGENCY;
130 irq->u.emerg.code = cpu_id;
131 irqs = _vcpu_ioctl(vm, cpu_id, KVM_S390_SET_IRQ_STATE, &irq_state);
132 TEST_ASSERT(irqs >= 0, "Error injecting EMERGENCY IRQ errno %d\n", errno);
133}
134
135static void test_normal(void)
136{
137 printf("Testing normal reset\n");
138 /* Create VM */
139 vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
140 run = vcpu_state(vm, VCPU_ID);
141 regs = &run->s.regs;
142
143 vcpu_run(vm, VCPU_ID);
144
145 inject_irq(VCPU_ID);
146
147 vcpu_ioctl(vm, VCPU_ID, KVM_S390_NORMAL_RESET, 0);
148 assert_normal();
149 kvm_vm_free(vm);
150}
151
152static void test_initial(void)
153{
154 printf("Testing initial reset\n");
155 vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
156 run = vcpu_state(vm, VCPU_ID);
157 regs = &run->s.regs;
158
159 vcpu_run(vm, VCPU_ID);
160
161 inject_irq(VCPU_ID);
162
163 vcpu_ioctl(vm, VCPU_ID, KVM_S390_INITIAL_RESET, 0);
164 assert_normal();
165 assert_initial();
166 kvm_vm_free(vm);
167}
168
169static void test_clear(void)
170{
171 printf("Testing clear reset\n");
172 vm = vm_create_default(VCPU_ID, 0, guest_code_initial);
173 run = vcpu_state(vm, VCPU_ID);
174 regs = &run->s.regs;
175
176 vcpu_run(vm, VCPU_ID);
177
178 inject_irq(VCPU_ID);
179
180 vcpu_ioctl(vm, VCPU_ID, KVM_S390_CLEAR_RESET, 0);
181 assert_normal();
182 assert_initial();
183 assert_clear();
184 kvm_vm_free(vm);
185}
186
187int main(int argc, char *argv[])
188{
189 setbuf(stdout, NULL); /* Tell stdout not to buffer its content */
190
191 test_initial();
192 if (kvm_check_cap(KVM_CAP_S390_VCPU_RESETS)) {
193 test_normal();
194 test_clear();
195 }
196 return 0;
197}