KVM: s390: Add new reset vcpu API
Subsystems (5)
Janosch Frank
maintainerv9 cover KVM: s390: Add new reset vcpu API
Let's implement the remaining resets, namely the normal and clear reset to improve architectural compliance.
While we're at it, let's also start testing the new API. Those tests are not yet complete, but will be extended in the future.
Christian Borntraeger (1):
KVM: s390: do not clobber registers during guest reset/store status
Janosch Frank (4):
KVM: s390: Cleanup initial cpu reset
KVM: s390: Add new reset vcpu API
selftests: KVM: Add fpu and one reg set/get library functions
selftests: KVM: s390x: Add reset tests
Pierre Morel (1):
selftests: KVM: testing the local IRQs resets
Documentation/virt/kvm/api.txt | 43 ++++ arch/s390/include/asm/kvm_host.h | 5 + arch/s390/kvm/kvm-s390.c | 86 ++++++-- include/uapi/linux/kvm.h | 5 + tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/include/kvm_util.h | 6 + tools/testing/selftests/kvm/lib/kvm_util.c | 48 +++++ tools/testing/selftests/kvm/s390x/resets.c | 203 ++++++++++++++++++ 8 files changed, 379 insertions(+), 18 deletions(-) create mode 100644 tools/testing/selftests/kvm/s390x/resets.c
Signature · 1 line
2.20.1
Janosch Frank
maintainerPATCH v9 1/6 KVM: s390: do not clobber registers during guest reset/store status
From: Christian Borntraeger <[email protected]>
The initial CPU reset clobbers the userspace fpc and the store status ioctl clobbers the guest acrs + fpr. As these calls are only done via ioctl (and not via vcpu_run), no CPU context is loaded, so we can (and must) act directly on the sync regs, not on the thread context.
--- arch/s390/kvm/kvm-s390.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
arch/s390/kvm/kvm-s390.c +2 -3
@@ -2824,8 +2824,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gcr[14 ] =CR14_UNUSED_32 |CR14_UNUSED_33 |CR14_EXTERNAL_DAMAGE_SUBMASK ; -/* make sure the new fpc will be lazily loaded */ -save_fpu_regs (); + vcpu->run->s.regs.fpc =0 ; current->thread.fpu.fpc =0 ; vcpu->arch.sie_block->gbea =1 ; vcpu->arch.sie_block->pp =0 ;
@@ -4343,7 +4342,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,switch (ioctl) {case KVM_S390_STORE_STATUS : idx =srcu_read_lock (&vcpu->kvm->srcu); - r =kvm_s390_vcpu_store_status (vcpu, arg); + r =kvm_s390_store_status_unloaded (vcpu, arg);srcu_read_unlock (&vcpu->kvm->srcu, idx);break ;case KVM_S390_SET_INITIAL_PSW : {
Signature · 1 line
2.20.1
Re: [PATCH v9 1/6] KVM: s390: do not clobber registers during guest reset/store status
Quoted 31 lines · Janosch Frank
From: Christian Borntraeger <[email protected]>
The initial CPU reset clobbers the userspace fpc and the store status ioctl clobbers the guest acrs + fpr. As these calls are only done via ioctl (and not via
vcpu_run), no CPU context is loaded, so we can (and must) act directly on the sync regs, not on the thread context.Fixes e1788bb995be ("KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load")Fixes 31d8b8d41a7e ("KVM: s390: handle access registers in the run ioctl not in vcpu_put/load")Signed-off-by Christian Borntraeger <[email protected]>--- arch/s390/kvm/kvm-s390.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)arch/s390/kvm/kvm-s390.c +1
-2@@ -2824,8 +2824,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gcr[14 ] =CR14_UNUSED_32 |CR14_UNUSED_33 |CR14_EXTERNAL_DAMAGE_SUBMASK ; -/* make sure the new fpc will be lazily loaded */ -save_fpu_regs (); + vcpu->run->s.regs.fpc =0 ; current->thread.fpu.fpc =0 ; vcpu->arch.sie_block->gbea =1 ; vcpu->arch.sie_block->pp =0 ;
arch/s390/kvm/kvm-s390.c long kvm_arch_vcpu_ioctl(struct file *filp, · line 4348
Quoted 8 lines
arch/s390/kvm/kvm-s390.c +1
-1@@ -4343,7 +4342,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,switch (ioctl) {case KVM_S390_STORE_STATUS : idx =srcu_read_lock (&vcpu->kvm->srcu); - r =kvm_s390_vcpu_store_status (vcpu, arg); + r =kvm_s390_store_status_unloaded (vcpu, arg);srcu_read_unlock (&vcpu->kvm->srcu, idx);break ;case KVM_S390_SET_INITIAL_PSW : {
Signature · 3 lines
Thanks, David / dhildenb
Re: [PATCH v9 1/6] KVM: s390: do not clobber registers during guest reset/store status
In reply to Janosch FrankQuoted 11 lines · On Thu, 30 Jan 2020 07:34:29 -0500 Janosch Frank <[email protected]> wrote:
From: Christian Borntraeger <[email protected]>
The initial CPU reset clobbers the userspace fpc and the store status ioctl clobbers the guest acrs + fpr. As these calls are only done via ioctl (and not via
vcpu_run), no CPU context is loaded, so we can (and must) act directly on the sync regs, not on the thread context.Fixes e1788bb995be ("KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load")Fixes 31d8b8d41a7e ("KVM: s390: handle access registers in the run ioctl not in vcpu_put/load")Signed-off-by Christian Borntraeger <[email protected]>
Add your s-o-b?
Quoted 3 lines
--- arch/s390/kvm/kvm-s390.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
Re: [PATCH v9 1/6] KVM: s390: do not clobber registers during guest reset/store status
In reply to Janosch FrankQuoted 20 lines · Janosch Frank
From: Christian Borntraeger <[email protected]>
The initial CPU reset clobbers the userspace fpc and the store status ioctl clobbers the guest acrs + fpr. As these calls are only done via ioctl (and not via
vcpu_run), no CPU context is loaded, so we can (and must) act directly on the sync regs, not on the thread context.Fixes e1788bb995be ("KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load")Fixes 31d8b8d41a7e ("KVM: s390: handle access registers in the run ioctl not in vcpu_put/load")Signed-off-by Christian Borntraeger <[email protected]>--- arch/s390/kvm/kvm-s390.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)arch/s390/kvm/kvm-s390.c +0
-0
arch/s390/kvm/kvm-s390.c static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) · line 2830
Quoted 9 lines
arch/s390/kvm/kvm-s390.c +1
-2@@ -2824,8 +2824,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) vcpu->arch.sie_block->gcr[14 ] =CR14_UNUSED_32 |CR14_UNUSED_33 |CR14_EXTERNAL_DAMAGE_SUBMASK ; -/* make sure the new fpc will be lazily loaded */ -save_fpu_regs (); + vcpu->run->s.regs.fpc =0 ; current->thread.fpu.fpc =0 ;
this needs to go out here as well.
Quoted 12 lines
arch/s390/kvm/kvm-s390.c +1
-1vcpu->arch.sie_block->gbea =1 ; vcpu->arch.sie_block->pp =0 ;@@ -4343,7 +4342,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,switch (ioctl) {case KVM_S390_STORE_STATUS : idx =srcu_read_lock (&vcpu->kvm->srcu); - r =kvm_s390_vcpu_store_status (vcpu, arg); + r =kvm_s390_store_status_unloaded (vcpu, arg);srcu_read_unlock (&vcpu->kvm->srcu, idx);break ;case KVM_S390_SET_INITIAL_PSW : {
Janosch Frank
maintainerPATCH v9 2/6 KVM: s390: Cleanup initial cpu reset
In reply to Janosch FrankThe code seems to be quite old and uses lots of unneeded spaces for alignment, which doesn't really help with readability.
Let's:
* Get rid of the extra spaces
* Remove the ULs as they are not needed on 0s
* Define constants for the CR 0 and 14 initial values
* Use the sizeof of the gcr array to memset it to 0
--- arch/s390/include/asm/kvm_host.h | 5 +++++ arch/s390/kvm/kvm-s390.c | 18 +++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)
arch/s390/include/asm/kvm_host.h +5 -0
@@ -122,6 +122,11 @@ struct mcck_volatile_info {__u32 reserved; }; +#define CR0_INITIAL_MASK (CR0_UNUSED_56 | CR0_INTERRUPT_KEY_SUBMASK | \ + CR0_MEASUREMENT_ALERT_SUBMASK) +#define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \ + CR14_EXTERNAL_DAMAGE_SUBMASK) +#define CPUSTAT_STOPPED 0x80000000#define CPUSTAT_WAIT 0x10000000#define CPUSTAT_ECALL_PEND 0x08000000
arch/s390/kvm/kvm-s390.c +7 -11
@@ -2811,19 +2811,15 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)static void kvm_s390_vcpu_initial_reset (struct kvm_vcpu *vcpu) {/* this equals initial cpu reset in pop, but we don't switch to ESA */ - vcpu->arch.sie_block->gpsw.mask =0UL ; - vcpu->arch.sie_block->gpsw.addr =0UL ; + vcpu->arch.sie_block->gpsw.mask =0 ; + vcpu->arch.sie_block->gpsw.addr =0 ;kvm_s390_set_prefix (vcpu,0 );kvm_s390_set_cpu_timer (vcpu,0 ); - vcpu->arch.sie_block->ckc =0UL ; - vcpu->arch.sie_block->todpr =0 ; -memset (vcpu->arch.sie_block->gcr,0 ,16 *sizeof (__u64)); - vcpu->arch.sie_block->gcr[0 ] =CR0_UNUSED_56 | -CR0_INTERRUPT_KEY_SUBMASK | -CR0_MEASUREMENT_ALERT_SUBMASK ; - vcpu->arch.sie_block->gcr[14 ] =CR14_UNUSED_32 | -CR14_UNUSED_33 | -CR14_EXTERNAL_DAMAGE_SUBMASK ; + vcpu->arch.sie_block->ckc =0 ; + vcpu->arch.sie_block->todpr =0 ; +memset (vcpu->arch.sie_block->gcr,0 ,sizeof (vcpu->arch.sie_block->gcr)); + vcpu->arch.sie_block->gcr[0 ] =CR0_INITIAL_MASK ; + vcpu->arch.sie_block->gcr[14 ] =CR14_INITIAL_MASK ; vcpu->run->s.regs.fpc =0 ; current->thread.fpu.fpc =0 ; vcpu->arch.sie_block->gbea =1 ;
Signature · 1 line
2.20.1
Re: [PATCH v9 2/6] KVM: s390: Cleanup initial cpu reset
Quoted 9 lines · Janosch Frank
The code seems to be quite old and uses lots of unneeded spaces for alignment, which doesn't really help with readability.
Let's:
* Get rid of the extra spaces
* Remove the ULs as they are not needed on 0s
* Define constants for the CR 0 and 14 initial values
* Use the sizeof of the gcr array to memset it to 0
Quoted 7 lines
Signed-off-by Janosch Frank <[email protected]>Reviewed-by David Hildenbrand <[email protected]>Reviewed-by Cornelia Huck <[email protected]>--- arch/s390/include/asm/kvm_host.h | 5 +++++ arch/s390/kvm/kvm-s390.c | 18 +++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-)
Janosch Frank
maintainerPATCH v9 3/6 KVM: s390: Add new reset vcpu API
In reply to Janosch FrankThe 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.
--- Documentation/virt/kvm/api.txt | 43 +++++++++++++++++++++++ arch/s390/kvm/kvm-s390.c | 63 +++++++++++++++++++++++++++++++--- include/uapi/linux/kvm.h | 5 +++ 3 files changed, 107 insertions(+), 4 deletions(-)
Documentation/virt/kvm/api.txt +43 -0
@@ -4168,6 +4168,42 @@ This ioctl issues an ultravisor call to terminate the secure guest, unpins the VPA pages and releases all the device pages that are used to track the secure pages by hypervisor. +4.122 KVM_S390_NORMAL_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the cpu reset definition in the POP (Principles Of Operation). + +4.123 KVM_S390_INITIAL_RESET + +Capability: none +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the initial cpu reset definition in the POP. However, the cpu is not +put into ESA mode. This reset is a superset of the normal reset. + +4.124 KVM_S390_CLEAR_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the clear cpu reset definition in the POP. However, the cpu is not put +into ESA mode. This reset is a superset of the initial reset. + + 5. The kvm_run structure ------------------------
@@ -5396,3 +5432,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB flush hypercalls by Hyper-V) so userspace should disable KVM identification in CPUID and only exposes Hyper-V identification. In this case, guest thinks it's running on Hyper-V and only use Hyper-V hypercalls. + +8.22 KVM_CAP_S390_VCPU_RESETS + +Architectures: s390 + +This capability indicates that the KVM_S390_NORMAL_RESET and +KVM_S390_CLEAR_RESET ioctls are available.
arch/s390/kvm/kvm-s390.c +59 -4
83 lines not on this page · raw message
include/uapi/linux/kvm.h +5 -0
@@ -1009,6 +1009,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176#define KVM_CAP_ARM_NISV_TO_USER 177#define KVM_CAP_ARM_INJECT_EXT_DABT 178 +#define KVM_CAP_S390_VCPU_RESETS 179#ifdef KVM_CAP_IRQ_ROUTING
@@ -1473,6 +1474,10 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +/* Available with KVM_CAP_S390_VCPU_RESETS */ +#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) +#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */
Signature · 1 line
2.20.1
Janosch Frank
maintainerQuoted 4 lines · Janosch Frank
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.
Quoted 8 lines
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.
My rebase conflict fix did miss the removal of the old initial reset function...
Janosch Frank
maintainerPATCH v9 1/1 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.
--- Documentation/virt/kvm/api.txt | 43 +++++++++++++++++ arch/s390/kvm/kvm-s390.c | 86 +++++++++++++++++++++++----------- include/uapi/linux/kvm.h | 5 ++ 3 files changed, 106 insertions(+), 28 deletions(-)
Documentation/virt/kvm/api.txt +43 -0
@@ -4168,6 +4168,42 @@ This ioctl issues an ultravisor call to terminate the secure guest, unpins the VPA pages and releases all the device pages that are used to track the secure pages by hypervisor. +4.122 KVM_S390_NORMAL_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the cpu reset definition in the POP (Principles Of Operation). + +4.123 KVM_S390_INITIAL_RESET + +Capability: none +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the initial cpu reset definition in the POP. However, the cpu is not +put into ESA mode. This reset is a superset of the normal reset. + +4.124 KVM_S390_CLEAR_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the clear cpu reset definition in the POP. However, the cpu is not put +into ESA mode. This reset is a superset of the initial reset. + + 5. The kvm_run structure ------------------------
@@ -5396,3 +5432,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB flush hypercalls by Hyper-V) so userspace should disable KVM identification in CPUID and only exposes Hyper-V identification. In this case, guest thinks it's running on Hyper-V and only use Hyper-V hypercalls. + +8.22 KVM_CAP_S390_VCPU_RESETS + +Architectures: s390 + +This capability indicates that the KVM_S390_NORMAL_RESET and +KVM_S390_CLEAR_RESET ioctls are available.
arch/s390/kvm/kvm-s390.c +58 -28
112 lines not on this page · raw message
include/uapi/linux/kvm.h +5 -0
@@ -1009,6 +1009,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176#define KVM_CAP_ARM_NISV_TO_USER 177#define KVM_CAP_ARM_INJECT_EXT_DABT 178 +#define KVM_CAP_S390_VCPU_RESETS 179#ifdef KVM_CAP_IRQ_ROUTING
@@ -1473,6 +1474,10 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +/* Available with KVM_CAP_S390_VCPU_RESETS */ +#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) +#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */
Signature · 1 line
2.20.1
Quoted 8 lines · Janosch Frank
arch/s390/kvm/kvm-s390.c +8
-0+static void kvm_arch_vcpu_ioctl_initial_reset (struct kvm_vcpu *vcpu) +{ +/* Initial reset is a superset of the normal reset */ +kvm_arch_vcpu_ioctl_normal_reset (vcpu); + +/* this equals initial cpu reset in pop, but we don't switch to ESA */ + vcpu->arch.sie_block->gpsw.mask =0 ; + vcpu->arch.sie_block->gpsw.addr =0 ;
arch/s390/kvm/kvm-s390.c static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +9
-0+kvm_s390_set_prefix (vcpu,0 ); +kvm_s390_set_cpu_timer (vcpu,0 ); + vcpu->arch.sie_block->ckc =0 ; + vcpu->arch.sie_block->todpr =0 ; +memset (vcpu->arch.sie_block->gcr,0 ,sizeof (vcpu->arch.sie_block->gcr)); + vcpu->arch.sie_block->gcr[0 ] =CR0_INITIAL_MASK ; + vcpu->arch.sie_block->gcr[14 ] =CR14_INITIAL_MASK ; + vcpu->run->s.regs.fpc =0 ; + current->thread.fpu.fpc =0 ;
This is still wrong.
Janosch Frank
maintainerQuoted 21 lines · Christian Borntraeger
Quoted 16 lines · Janosch Frank
arch/s390/kvm/kvm-s390.c +16
-0+static void kvm_arch_vcpu_ioctl_initial_reset (struct kvm_vcpu *vcpu) +{ +/* Initial reset is a superset of the normal reset */ +kvm_arch_vcpu_ioctl_normal_reset (vcpu); + +/* this equals initial cpu reset in pop, but we don't switch to ESA */ + vcpu->arch.sie_block->gpsw.mask =0 ; + vcpu->arch.sie_block->gpsw.addr =0 ; +kvm_s390_set_prefix (vcpu,0 ); +kvm_s390_set_cpu_timer (vcpu,0 ); + vcpu->arch.sie_block->ckc =0 ; + vcpu->arch.sie_block->todpr =0 ; +memset (vcpu->arch.sie_block->gcr,0 ,sizeof (vcpu->arch.sie_block->gcr)); + vcpu->arch.sie_block->gcr[0 ] =CR0_INITIAL_MASK ; + vcpu->arch.sie_block->gcr[14 ] =CR14_INITIAL_MASK ; + vcpu->run->s.regs.fpc =0 ;
Quoted 3 lines
arch/s390/kvm/kvm-s390.c static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, · line 3290
Quoted 1 line
arch/s390/kvm/kvm-s390.c +1
-0+ current->thread.fpu.fpc =0 ;This is still wrong.
Your fixpatch doesn't delete it :)
That hunk is not mine...
Quoted 13 lines · On Thu, 30 Jan 2020 07:55:59 -0500 Janosch Frank <[email protected]> wrote:
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.
Quoted 8 lines
Signed-off-by Janosch Frank <[email protected]>Reviewed-by Cornelia Huck <[email protected]>Reviewed-by Christian Borntraeger <[email protected]>--- Documentation/virt/kvm/api.txt | 43 +++++++++++++++++ arch/s390/kvm/kvm-s390.c | 86 +++++++++++++++++++++++----------- include/uapi/linux/kvm.h | 5 ++ 3 files changed, 106 insertions(+), 28 deletions(-)
This version looks good to me.
Quoted 118 lines · Janosch Frank
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]>--- Documentation/virt/kvm/api.txt | 43 +++++++++++++++++++++++ arch/s390/kvm/kvm-s390.c | 63 +++++++++++++++++++++++++++++++--- include/uapi/linux/kvm.h | 5 +++ 3 files changed, 107 insertions(+), 4 deletions(-)Documentation/virt/kvm/api.txt +43
-0@@ -4168,6 +4168,42 @@ This ioctl issues an ultravisor call to terminate the secure guest, unpins the VPA pages and releases all the device pages that are used to track the secure pages by hypervisor. +4.122 KVM_S390_NORMAL_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the cpu reset definition in the POP (Principles Of Operation). + +4.123 KVM_S390_INITIAL_RESET + +Capability: none +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the initial cpu reset definition in the POP. However, the cpu is not +put into ESA mode. This reset is a superset of the normal reset. + +4.124 KVM_S390_CLEAR_RESET + +Capability: KVM_CAP_S390_VCPU_RESETS +Architectures: s390 +Type: vcpu ioctl +Parameters: none +Returns: 0 + +This ioctl resets VCPU registers and control structures according to +the clear cpu reset definition in the POP. However, the cpu is not put +into ESA mode. This reset is a superset of the initial reset. + + 5. The kvm_run structure ------------------------@@ -5396,3 +5432,10 @@ handling by KVM (as some KVM hypercall may be mistakenly treated as TLB flush hypercalls by Hyper-V) so userspace should disable KVM identification in CPUID and only exposes Hyper-V identification. In this case, guest thinks it's running on Hyper-V and only use Hyper-V hypercalls. + +8.22 KVM_CAP_S390_VCPU_RESETS + +Architectures: s390 + +This capability indicates that the KVM_S390_NORMAL_RESET and +KVM_S390_CLEAR_RESET ioctls are available.arch/s390/kvm/kvm-s390.c +20
-3@@ -529,6 +529,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)case KVM_CAP_S390_CMMA_MIGRATION :case KVM_CAP_S390_AIS :case KVM_CAP_S390_AIS_MIGRATION : +case KVM_CAP_S390_VCPU_RESETS : r =1 ;break ;case KVM_CAP_S390_HPAGE_1M :@@ -3274,10 +3275,55 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,return r; } -static int kvm_arch_vcpu_ioctl_initial_reset (struct kvm_vcpu *vcpu) +static void kvm_arch_vcpu_ioctl_normal_reset (struct kvm_vcpu *vcpu) { -kvm_s390_vcpu_initial_reset (vcpu); -return 0 ; + vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI ; + vcpu->arch.pfault_token =KVM_S390_PFAULT_TOKEN_INVALID ; +memset (vcpu->run->s.regs.riccb,0 ,sizeof (vcpu->run->s.regs.riccb)); + +kvm_clear_async_pf_completion_queue (vcpu); +if (!kvm_s390_user_cpu_state_ctrl (vcpu->kvm)) +kvm_s390_vcpu_stop (vcpu); +kvm_s390_clear_local_irqs (vcpu); +} + +static void kvm_arch_vcpu_ioctl_initial_reset (struct kvm_vcpu *vcpu) +{ +/* Initial reset is a superset of the normal reset */ +kvm_arch_vcpu_ioctl_normal_reset (vcpu); + +/* this equals initial cpu reset in pop, but we don't switch to ESA */ + vcpu->arch.sie_block->gpsw.mask =0 ; + vcpu->arch.sie_block->gpsw.addr =0 ;
arch/s390/kvm/kvm-s390.c static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, · line 3307
Quoted 10 lines
arch/s390/kvm/kvm-s390.c +10
-0+kvm_s390_set_prefix (vcpu,0 ); +kvm_s390_set_cpu_timer (vcpu,0 ); + vcpu->arch.sie_block->ckc =0 ; + vcpu->arch.sie_block->todpr =0 ; +memset (vcpu->arch.sie_block->gcr,0 ,sizeof (vcpu->arch.sie_block->gcr)); + vcpu->arch.sie_block->gcr[0 ] =CR0_INITIAL_MASK ; + vcpu->arch.sie_block->gcr[14 ] =CR14_INITIAL_MASK ; +/* make sure the new fpc will be lazily loaded */ +save_fpu_regs (); + current->thread.fpu.fpc =0 ;
with that fixed up
Quoted 65 lines
arch/s390/kvm/kvm-s390.c +29
-1+ vcpu->arch.sie_block->gbea =1 ; + vcpu->arch.sie_block->pp =0 ; + vcpu->arch.sie_block->fpf &= ~FPF_BPBC ; +} + +static void kvm_arch_vcpu_ioctl_clear_reset (struct kvm_vcpu *vcpu) +{ +struct kvm_sync_regs *regs = &vcpu->run->s.regs; + +/* Clear reset is a superset of the initial reset */ +kvm_arch_vcpu_ioctl_initial_reset (vcpu); + +memset (®s->gprs,0 ,sizeof (regs->gprs)); +memset (®s->vrs,0 ,sizeof (regs->vrs)); +memset (®s->acrs,0 ,sizeof (regs->acrs)); +memset (®s->gscb,0 ,sizeof (regs->gscb)); + + regs->etoken =0 ; + regs->etoken_extension =0 ; }int kvm_arch_vcpu_ioctl_set_regs (struct kvm_vcpu *vcpu,struct kvm_regs *regs)@@ -4350,8 +4396,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp, r =kvm_arch_vcpu_ioctl_set_initial_psw (vcpu, psw);break ; } +case KVM_S390_CLEAR_RESET : + r =0 ; +kvm_arch_vcpu_ioctl_clear_reset (vcpu); +break ;case KVM_S390_INITIAL_RESET : - r =kvm_arch_vcpu_ioctl_initial_reset (vcpu); + r =0 ; +kvm_arch_vcpu_ioctl_initial_reset (vcpu); +break ; +case KVM_S390_NORMAL_RESET : + r =0 ; +kvm_arch_vcpu_ioctl_normal_reset (vcpu);break ;case KVM_SET_ONE_REG :case KVM_GET_ONE_REG : {include/uapi/linux/kvm.h +5
-0@@ -1009,6 +1009,7 @@ struct kvm_ppc_resize_hpt {#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176#define KVM_CAP_ARM_NISV_TO_USER 177#define KVM_CAP_ARM_INJECT_EXT_DABT 178 +#define KVM_CAP_S390_VCPU_RESETS 179#ifdef KVM_CAP_IRQ_ROUTING @@ -1473,6 +1474,10 @@ struct kvm_enc_region {/* Available with KVM_CAP_ARM_SVE */ #define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) +/* Available with KVM_CAP_S390_VCPU_RESETS */ +#define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) +#define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) +/* Secure Encrypted Virtualization command */ enum sev_cmd_id {/* Guest initialization commands */
Janosch Frank
maintainerPATCH v9 4/6 selftests: KVM: Add fpu and one reg set/get library functions
In reply to Janosch FrankAdd library access to more registers.
--- .../testing/selftests/kvm/include/kvm_util.h | 6 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+)
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, struct kvm_sregs *sregs);int _vcpu_sregs_set (struct kvm_vm *vm,uint32_t vcpuid,struct kvm_sregs *sregs); +void vcpu_fpu_get (struct kvm_vm *vm,uint32_t vcpuid, +struct kvm_fpu *fpu); +void vcpu_fpu_set (struct kvm_vm *vm,uint32_t vcpuid, +struct kvm_fpu *fpu); +void vcpu_get_reg (struct kvm_vm *vm,uint32_t vcpuid,struct kvm_one_reg *reg); +void vcpu_set_reg (struct kvm_vm *vm,uint32_t vcpuid,struct kvm_one_reg *reg);#ifdef __KVM_HAVE_VCPU_EVENTSvoid vcpu_events_get (struct kvm_vm *vm,uint32_t vcpuid,struct kvm_vcpu_events *events);
tools/testing/selftests/kvm/lib/kvm_util.c +48 -0
54 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [PATCH v9 4/6] selftests: KVM: Add fpu and one reg set/get library functions
Quoted 8 lines · On Thu, 30 Jan 2020 07:34:32 -0500 Janosch Frank <[email protected]> wrote:
Add library access to more registers.
Signed-off-by Janosch Frank <[email protected]>Reviewed-by Thomas Huth <[email protected]>--- .../testing/selftests/kvm/include/kvm_util.h | 6 +++ tools/testing/selftests/kvm/lib/kvm_util.c | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+)
Janosch Frank
maintainerPATCH v9 5/6 selftests: KVM: s390x: Add reset tests
In reply to Janosch FrankTest if the registers end up having the correct values after a normal, initial and clear reset.
--- tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/resets.c | 157 +++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/resets.c
tools/testing/selftests/kvm/Makefile +1 -0
@@ -36,6 +36,7 @@ TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/sync_regs_test +TEST_GEN_PROGS_s390x += s390x/resets TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpus
tools/testing/selftests/kvm/s390x/resets.c new file +157 -0
157 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [PATCH v9 5/6] selftests: KVM: s390x: Add reset tests
Quoted 119 lines · Janosch Frank
Test if the registers end up having the correct values after a normal, initial and clear reset.
Signed-off-by Janosch Frank <[email protected]>--- tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/resets.c | 157 +++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/resets.ctools/testing/selftests/kvm/Makefile +1
-0@@ -36,6 +36,7 @@ TEST_GEN_PROGS_aarch64 += kvm_create_max_vcpus TEST_GEN_PROGS_s390x = s390x/memop TEST_GEN_PROGS_s390x += s390x/sync_regs_test +TEST_GEN_PROGS_s390x += s390x/resets TEST_GEN_PROGS_s390x += dirty_log_test TEST_GEN_PROGS_s390x += kvm_create_max_vcpustools/testing/selftests/kvm/s390x/resets.c new file +91
-0@@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* +* Test for s390x CPU resets +* +* Copyright (C) 2020, IBM +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> + +#include "test_util.h" +#include "kvm_util.h" + +#define VCPU_ID 3 + +struct kvm_vm *vm; +struct kvm_run *run; +struct kvm_sync_regs *regs; +static uint64_t regs_null[16 ]; + +static uint64_t crs[16 ] = {0x40000ULL , +0x42000ULL , +0 ,0 ,0 ,0 ,0 , +0x43000ULL , +0 ,0 ,0 ,0 ,0 , +0x44000ULL , +0 ,0 +}; + +static void guest_code_initial (void ) +{ +/* Round toward 0 */ +uint32_t fpc =0x11 ; + +/* Dirty registers */ + asmvolatile ( +" lctlg 0,15,%0\n" +" sfpc %1\n" + : :"Q" (crs),"d" (fpc)); +GUEST_SYNC (0 ); +} + +static void test_one_reg (uint64_t id,uint64_t value) +{ +struct kvm_one_reg reg; +uint64_t eval_reg; + + reg.addr = (uintptr_t )&eval_reg; + reg.id = id; +vcpu_get_reg (vm,VCPU_ID , ®); +TEST_ASSERT (eval_reg == value,"value == %s" , value); +} + +static void assert_clear (void ) +{ +struct kvm_sregs sregs; +struct kvm_regs regs; +struct kvm_fpu fpu; + +vcpu_regs_get (vm,VCPU_ID , ®s); +TEST_ASSERT (!memcmp (®s.gprs, regs_null,sizeof (regs.gprs)),"grs == 0" ); + +vcpu_sregs_get (vm,VCPU_ID , &sregs); +TEST_ASSERT (!memcmp (&sregs.acrs, regs_null,sizeof (sregs.acrs)),"acrs == 0" ); + +vcpu_fpu_get (vm,VCPU_ID , &fpu); +TEST_ASSERT (!memcmp (&fpu.fprs, regs_null,sizeof (fpu.fprs)),"fprs == 0" ); +} + +static void assert_initial (void ) +{ +struct kvm_sregs sregs; +struct kvm_fpu fpu; + +vcpu_sregs_get (vm,VCPU_ID , &sregs); +TEST_ASSERT (sregs.crs[0 ] ==0xE0UL ,"cr0 == 0xE0" ); +TEST_ASSERT (sregs.crs[14 ] ==0xC2000000UL ,"cr14 == 0xC2000000" ); +TEST_ASSERT (!memcmp (&sregs.crs[1 ], regs_null,sizeof (sregs.crs[1 ]) *12 ), +"cr1-13 == 0" ); +TEST_ASSERT (sregs.crs[15 ] ==0 ,"cr15 == 0" ); + +vcpu_fpu_get (vm,VCPU_ID , &fpu); +TEST_ASSERT (!fpu.fpc,"fpc == 0" ); + +test_one_reg (KVM_REG_S390_GBEA ,1 ); +test_one_reg (KVM_REG_S390_PP ,0 ); +test_one_reg (KVM_REG_S390_TODPR ,0 ); +test_one_reg (KVM_REG_S390_CPU_TIMER ,0 ); +test_one_reg (KVM_REG_S390_CLOCK_COMP ,0 );
tools/testing/selftests/kvm/s390x/resets.c line 101
Quoted 10 lines
tools/testing/selftests/kvm/s390x/resets.c new file +10
-0+} + +static void assert_normal (void ) +{ +test_one_reg (KVM_REG_S390_PFTOKEN ,KVM_S390_PFAULT_TOKEN_INVALID ); +} + +static void test_normal (void ) +{ +printf ("Testing notmal reset\n" );
s/notmal/normal/
With the typo fixed:
Re: [PATCH v9 5/6] selftests: KVM: s390x: Add reset tests
In reply to Janosch FrankQuoted 9 lines · On Thu, 30 Jan 2020 07:34:33 -0500 Janosch Frank <[email protected]> wrote:
Test if the registers end up having the correct values after a normal, initial and clear reset.
Signed-off-by Janosch Frank <[email protected]>--- tools/testing/selftests/kvm/Makefile | 1 + tools/testing/selftests/kvm/s390x/resets.c | 157 +++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 tools/testing/selftests/kvm/s390x/resets.c
Janosch Frank
maintainerPATCH v9 6/6 selftests: KVM: testing the local IRQs resets
In reply to Janosch FrankFrom: Pierre Morel <[email protected]>
Local IRQs are reset by a normal cpu reset. The initial cpu reset and the clear cpu reset, as superset of the normal reset, both clear the IRQs too.
Let's inject an interrupt to a vCPU before calling a reset and see if it is gone after the reset.
We choose to inject only an emergency interrupt at this point and can extend the test to other types of IRQs later.
--- tools/testing/selftests/kvm/s390x/resets.c | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+)
tools/testing/selftests/kvm/s390x/resets.c +46 -0
@@ -14,6 +14,9 @@#include "kvm_util.h" #define VCPU_ID 3 +#define LOCAL_IRQS 32 + +struct kvm_s390_irq buf[VCPU_ID +LOCAL_IRQS ];struct kvm_vm *vm;struct kvm_run *run;
@@ -53,6 +56,27 @@ static void test_one_reg(uint64_t id, uint64_t value)TEST_ASSERT (eval_reg == value,"value == %s" , value); } +static void assert_noirq (void ) +{ +struct kvm_s390_irq_state irq_state; +int irqs; + +if (!(kvm_check_cap (KVM_CAP_S390_INJECT_IRQ ) && +kvm_check_cap (KVM_CAP_S390_IRQ_STATE ))) +return ; + + irq_state.len =sizeof (buf); + irq_state.buf = (unsigned long )buf; + irqs =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_GET_IRQ_STATE , &irq_state); +/* +* irqs contains the number of retrieved interrupts, apart from the +* emergency call that should be cleared by the resets, there should be +* none. +*/ +TEST_ASSERT (irqs >=0 ,"Could not fetch IRQs: errno %d\n" , errno); +TEST_ASSERT (!irqs,"IRQ pending" ); +} +static void assert_clear (void ) {struct kvm_sregs sregs;
@@ -94,6 +118,22 @@ static void assert_initial(void)static void assert_normal (void ) {test_one_reg (KVM_REG_S390_PFTOKEN ,KVM_S390_PFAULT_TOKEN_INVALID ); +assert_noirq (); +} + +static void inject_irq (int cpu_id) +{ +struct kvm_s390_irq_state irq_state; +struct kvm_s390_irq *irq = &buf[0 ]; +int irqs; + +/* Inject IRQ */ + irq_state.len =sizeof (struct kvm_s390_irq ); + irq_state.buf = (unsigned long )buf; + irq->type =KVM_S390_INT_EMERGENCY ; + irq->u.emerg.code = cpu_id; + irqs =_vcpu_ioctl (vm, cpu_id,KVM_S390_SET_IRQ_STATE , &irq_state); +TEST_ASSERT (irqs >=0 ,"Error injecting EMERGENCY IRQ errno %d\n" , errno); }static void test_normal (void )
@@ -106,6 +146,8 @@ static void test_normal(void)vcpu_run (vm,VCPU_ID ); +inject_irq (VCPU_ID ); +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_NORMAL_RESET ,0 );assert_normal ();kvm_vm_free (vm);
@@ -121,6 +163,8 @@ static void test_initial(void)vcpu_run (vm,VCPU_ID ); +inject_irq (VCPU_ID ); +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_INITIAL_RESET ,0 );assert_normal ();assert_initial ();
@@ -137,6 +181,8 @@ static void test_clear(void)vcpu_run (vm,VCPU_ID ); +inject_irq (VCPU_ID ); +vcpu_ioctl (vm,VCPU_ID ,KVM_S390_CLEAR_RESET ,0 );assert_normal ();assert_initial ();
Signature · 1 line
2.20.1
Re: [PATCH v9 6/6] selftests: KVM: testing the local IRQs resets
Quoted 23 lines · On Thu, 30 Jan 2020 07:34:34 -0500 Janosch Frank <[email protected]> wrote:
From: Pierre Morel <[email protected]>
Local IRQs are reset by a normal cpu reset. The initial cpu reset and the clear cpu reset, as superset of the normal reset, both clear the IRQs too.
Let's inject an interrupt to a vCPU before calling a reset and see if it is gone after the reset.
We choose to inject only an emergency interrupt at this point and can extend the test to other types of IRQs later.
Signed-off-by Pierre Morel <[email protected]>Signed-off-by Janosch Frank <[email protected]>[minor fixups]--- tools/testing/selftests/kvm/s390x/resets.c | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+)tools/testing/selftests/kvm/s390x/resets.c +0
-0
tools/testing/selftests/kvm/s390x/resets.c line 17
Quoted 4 lines
tools/testing/selftests/kvm/s390x/resets.c +1
-0@@ -14,6 +14,9 @@#include "kvm_util.h" #define VCPU_ID 3 +#define LOCAL_IRQS 32
The choice of 32 here is still a bit unclear (although not a problem).
Quoted 7 lines
tools/testing/selftests/kvm/s390x/resets.c +2
-0+ +struct kvm_s390_irq buf[VCPU_ID +LOCAL_IRQS ];struct kvm_vm *vm;struct kvm_run *run;@@ -53,6 +56,27 @@ static void test_one_reg(uint64_t id, uint64_t value)TEST_ASSERT (eval_reg == value,"value == %s" , value);
tools/testing/selftests/kvm/s390x/resets.c static void test_one_reg(uint64_t id, uint64_t value) · line 66
Quoted 10 lines
tools/testing/selftests/kvm/s390x/resets.c +8
-0} +static void assert_noirq (void ) +{ +struct kvm_s390_irq_state irq_state; +int irqs; + +if (!(kvm_check_cap (KVM_CAP_S390_INJECT_IRQ ) && +kvm_check_cap (KVM_CAP_S390_IRQ_STATE ))) +return ;
I think you should drop the capability check here as well.
tools/testing/selftests/kvm/s390x/resets.c static void test_one_reg(uint64_t id, uint64_t value) · line 74
Quoted 8 lines
tools/testing/selftests/kvm/s390x/resets.c +8
-0+ + irq_state.len =sizeof (buf); + irq_state.buf = (unsigned long )buf; + irqs =_vcpu_ioctl (vm,VCPU_ID ,KVM_S390_GET_IRQ_STATE , &irq_state); +/* +* irqs contains the number of retrieved interrupts, apart from the +* emergency call that should be cleared by the resets, there should be +* none.
What about the updated comment? :)
tools/testing/selftests/kvm/s390x/resets.c static void test_one_reg(uint64_t id, uint64_t value) · line 82
Quoted 8 lines
tools/testing/selftests/kvm/s390x/resets.c +5
-0+*/ +TEST_ASSERT (irqs >=0 ,"Could not fetch IRQs: errno %d\n" , errno); +TEST_ASSERT (!irqs,"IRQ pending" ); +} +static void assert_clear (void ) {struct kvm_sregs sregs;
Else, looks sane to me.