Skip to content

Commit 7de3f14

Browse files
frankjaaborntraeger
authored andcommitted
KVM: s390: Add new reset vcpu API
The architecture states that we need to reset local IRQs for all CPU resets. Because the old reset interface did not support the normal CPU reset we never did that on a normal reset. Let's implement an interface for the missing normal and clear resets and reset all local IRQs, registers and control structures as stated in the architecture. Userspace might already reset the registers via the vcpu run struct, but as we need the interface for the interrupt clearing part anyway, we implement the resets fully and don't rely on userspace to reset the rest. Signed-off-by: Janosch Frank <[email protected]> Reviewed-by: Cornelia Huck <[email protected]> Reviewed-by: Christian Borntraeger <[email protected]> Reviewed-by: Thomas Huth <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Borntraeger <[email protected]>
1 parent cca00eb commit 7de3f14

File tree

3 files changed

+105
-27
lines changed

3 files changed

+105
-27
lines changed

Documentation/virt/kvm/api.txt

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

4171+
4.122 KVM_S390_NORMAL_RESET
4172+
4173+
Capability: KVM_CAP_S390_VCPU_RESETS
4174+
Architectures: s390
4175+
Type: vcpu ioctl
4176+
Parameters: none
4177+
Returns: 0
4178+
4179+
This ioctl resets VCPU registers and control structures according to
4180+
the cpu reset definition in the POP (Principles Of Operation).
4181+
4182+
4.123 KVM_S390_INITIAL_RESET
4183+
4184+
Capability: none
4185+
Architectures: s390
4186+
Type: vcpu ioctl
4187+
Parameters: none
4188+
Returns: 0
4189+
4190+
This ioctl resets VCPU registers and control structures according to
4191+
the initial cpu reset definition in the POP. However, the cpu is not
4192+
put into ESA mode. This reset is a superset of the normal reset.
4193+
4194+
4.124 KVM_S390_CLEAR_RESET
4195+
4196+
Capability: KVM_CAP_S390_VCPU_RESETS
4197+
Architectures: s390
4198+
Type: vcpu ioctl
4199+
Parameters: none
4200+
Returns: 0
4201+
4202+
This ioctl resets VCPU registers and control structures according to
4203+
the clear cpu reset definition in the POP. However, the cpu is not put
4204+
into ESA mode. This reset is a superset of the initial reset.
4205+
4206+
41714207
5. The kvm_run structure
41724208
------------------------
41734209

@@ -5396,3 +5432,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB
53965432
flush hypercalls by Hyper-V) so userspace should disable KVM identification
53975433
in CPUID and only exposes Hyper-V identification. In this case, guest
53985434
thinks it's running on Hyper-V and only use Hyper-V hypercalls.
5435+
5436+
8.22 KVM_CAP_S390_VCPU_RESETS
5437+
5438+
Architectures: s390
5439+
5440+
This capability indicates that the KVM_S390_NORMAL_RESET and
5441+
KVM_S390_CLEAR_RESET ioctls are available.

arch/s390/kvm/kvm-s390.c

Lines changed: 57 additions & 27 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:
@@ -2844,29 +2845,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
28442845

28452846
}
28462847

2847-
static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
2848-
{
2849-
/* this equals initial cpu reset in pop, but we don't switch to ESA */
2850-
vcpu->arch.sie_block->gpsw.mask = 0;
2851-
vcpu->arch.sie_block->gpsw.addr = 0;
2852-
kvm_s390_set_prefix(vcpu, 0);
2853-
kvm_s390_set_cpu_timer(vcpu, 0);
2854-
vcpu->arch.sie_block->ckc = 0;
2855-
vcpu->arch.sie_block->todpr = 0;
2856-
memset(vcpu->arch.sie_block->gcr, 0, sizeof(vcpu->arch.sie_block->gcr));
2857-
vcpu->arch.sie_block->gcr[0] = CR0_INITIAL_MASK;
2858-
vcpu->arch.sie_block->gcr[14] = CR14_INITIAL_MASK;
2859-
vcpu->run->s.regs.fpc = 0;
2860-
vcpu->arch.sie_block->gbea = 1;
2861-
vcpu->arch.sie_block->pp = 0;
2862-
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
2863-
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
2864-
kvm_clear_async_pf_completion_queue(vcpu);
2865-
if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
2866-
kvm_s390_vcpu_stop(vcpu);
2867-
kvm_s390_clear_local_irqs(vcpu);
2868-
}
2869-
28702848
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
28712849
{
28722850
mutex_lock(&vcpu->kvm->lock);
@@ -3281,10 +3259,53 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
32813259
return r;
32823260
}
32833261

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

32903311
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -4357,8 +4378,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
43574378
r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
43584379
break;
43594380
}
4381+
case KVM_S390_CLEAR_RESET:
4382+
r = 0;
4383+
kvm_arch_vcpu_ioctl_clear_reset(vcpu);
4384+
break;
43604385
case KVM_S390_INITIAL_RESET:
4361-
r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
4386+
r = 0;
4387+
kvm_arch_vcpu_ioctl_initial_reset(vcpu);
4388+
break;
4389+
case KVM_S390_NORMAL_RESET:
4390+
r = 0;
4391+
kvm_arch_vcpu_ioctl_normal_reset(vcpu);
43624392
break;
43634393
case KVM_SET_ONE_REG:
43644394
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 */

0 commit comments

Comments
 (0)