Plumb PSCI SYSTEM_RESET2 call for guests
Subsystems (5)
Will Deacon
maintainercover Plumb PSCI SYSTEM_RESET2 call for guests
Hi folks,
This small series exposes the PSCI SYSTEM_RESET2 call to guests, which allows the propagation of a "reset_type" and a "cookie" back to the VMM. Although Linux guests only ever pass 0 for the type ("SYSTEM_WARM_RESET"), the vendor-defined range can be used by a bootloader to provide additional information about the reset, such as an error code.
Cheers,
Will
--->8
Will Deacon (3):
KVM: arm64: Bump guest PSCI version to 1.1
KVM: arm64: Expose PSCI SYSTEM_RESET2 call to the guest
KVM: arm64: Indicate SYSTEM_RESET2 in kvm_run::system_event flags
field
Documentation/virt/kvm/api.rst | 5 +++ arch/arm64/include/uapi/asm/kvm.h | 7 ++++ arch/arm64/kvm/psci.c | 58 +++++++++++++++++++++++++------ include/kvm/arm_psci.h | 3 +- include/uapi/linux/psci.h | 4 +++ 5 files changed, 66 insertions(+), 11 deletions(-)
Signature · 6 lines
2.35.1.265.g69c8d7142f-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Will Deacon
maintainerPATCH 1/3 KVM: arm64: Bump guest PSCI version to 1.1
Expose PSCI version v1.1 to the guest by default. The only difference for now is that an updated version number is reported by PSCI_VERSION.
--- arch/arm64/kvm/psci.c | 12 +++++++++--- include/kvm/arm_psci.h | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-)
arch/arm64/kvm/psci.c +9 -3
@@ -305,16 +305,19 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)return ret; } -static int kvm_psci_1_0_call (struct kvm_vcpu *vcpu) +static int kvm_psci_1_x_call (struct kvm_vcpu *vcpu,u32 minor) {u32 psci_fn =smccc_get_function (vcpu);u32 feature;unsigned long val;int ret =1 ; +if (minor >1 ) +return -EINVAL ; +switch (psci_fn) {case PSCI_0_2_FN_PSCI_VERSION : - val =KVM_ARM_PSCI_1_0 ; + val = minor ==0 ?KVM_ARM_PSCI_1_0 :KVM_ARM_PSCI_1_1 ;break ;case PSCI_1_0_FN_PSCI_FEATURES : feature =smccc_get_arg1 (vcpu);
@@ -393,8 +396,10 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)int kvm_psci_call (struct kvm_vcpu *vcpu) {switch (kvm_psci_version (vcpu, vcpu->kvm)) { +case KVM_ARM_PSCI_1_1 : +return kvm_psci_1_x_call (vcpu,1 );case KVM_ARM_PSCI_1_0 : -return kvm_psci_1_0_call (vcpu); +return kvm_psci_1_x_call (vcpu,0 );case KVM_ARM_PSCI_0_2 :return kvm_psci_0_2_call (vcpu);case KVM_ARM_PSCI_0_1 :
@@ -511,6 +516,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)return 0 ;case KVM_ARM_PSCI_0_2 :case KVM_ARM_PSCI_1_0 : +case KVM_ARM_PSCI_1_1 :if (!wants_02)return -EINVAL ; vcpu->kvm->arch.psci_version = val;
include/kvm/arm_psci.h +2 -1
@@ -13,8 +13,9 @@#define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1)#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2)#define KVM_ARM_PSCI_1_0 PSCI_VERSION(1, 0) +#define KVM_ARM_PSCI_1_1 PSCI_VERSION(1, 1) -#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 +#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_1/* * We need the KVM pointer independently from the vcpu as we can call
Signature · 6 lines
2.35.1.265.g69c8d7142f-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Will Deacon
maintainerPATCH 2/3 KVM: arm64: Expose PSCI SYSTEM_RESET2 call to the guest
In reply to Will DeaconPSCI v1.1 introduces the optional SYSTEM_RESET2 call, which allows the caller to provide a vendor-specific "reset type" to request a particular form of reset or shutdown.
Expose this call to the guest and handle it in the same way as PSCI SYSTEM_RESET, along with some basic range checking on the argument.
--- arch/arm64/kvm/psci.c | 33 +++++++++++++++++++++++++++++---- include/uapi/linux/psci.h | 4 ++++ 2 files changed, 33 insertions(+), 4 deletions(-)
arch/arm64/kvm/psci.c +29 -4
@@ -308,7 +308,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)static int kvm_psci_1_x_call (struct kvm_vcpu *vcpu,u32 minor) {u32 psci_fn =smccc_get_function (vcpu); -u32 feature; +u32 arg;unsigned long val;int ret =1 ;
@@ -320,12 +320,12 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor) val = minor ==0 ?KVM_ARM_PSCI_1_0 :KVM_ARM_PSCI_1_1 ;break ;case PSCI_1_0_FN_PSCI_FEATURES : - feature =smccc_get_arg1 (vcpu); - val =kvm_psci_check_allowed_function (vcpu, feature); + arg =smccc_get_arg1 (vcpu); + val =kvm_psci_check_allowed_function (vcpu, arg);if (val)break ; -switch (feature) { +switch (arg) {case PSCI_0_2_FN_PSCI_VERSION :case PSCI_0_2_FN_CPU_SUSPEND :case PSCI_0_2_FN64_CPU_SUSPEND :
@@ -341,11 +341,36 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)case ARM_SMCCC_VERSION_FUNC_ID : val =0 ;break ; +case PSCI_1_1_FN_SYSTEM_RESET2 : +case PSCI_1_1_FN64_SYSTEM_RESET2 : +if (minor >=1 ) { + val =0 ; +break ; + } + fallthrough;default : val =PSCI_RET_NOT_SUPPORTED ;break ; }break ; +case PSCI_1_1_FN_SYSTEM_RESET2 : +kvm_psci_narrow_to_32bit (vcpu); + fallthrough; +case PSCI_1_1_FN64_SYSTEM_RESET2 : +if (minor >=1 ) { + arg =smccc_get_arg1 (vcpu); + +if (arg >PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET && + arg <PSCI_1_1_RESET_TYPE_VENDOR_START ) { + val =PSCI_RET_INVALID_PARAMS ; + }else { +kvm_psci_system_reset (vcpu); + val =PSCI_RET_INTERNAL_FAILURE ; + ret =0 ; + } +break ; + }; + fallthrough;default :return kvm_psci_0_2_call (vcpu); }
include/uapi/linux/psci.h +4 -0
@@ -82,6 +82,10 @@#define PSCI_0_2_TOS_UP_NO_MIGRATE 1#define PSCI_0_2_TOS_MP 2 +/* PSCI v1.1 reset type encoding for SYSTEM_RESET2 */ +#define PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET 0 +#define PSCI_1_1_RESET_TYPE_VENDOR_START 0x80000000U +/* PSCI version decoding (independent of PSCI version) */ #define PSCI_VERSION_MAJOR_SHIFT 16#define PSCI_VERSION_MINOR_MASK \
Signature · 6 lines
2.35.1.265.g69c8d7142f-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Will Deacon
maintainerPATCH 3/3 KVM: arm64: Indicate SYSTEM_RESET2 in kvm_run::system_event flags field
In reply to Will DeaconWhen handling reset and power-off PSCI calls from the guest, we initialise X0 to PSCI_RET_INTERNAL_FAILURE in case the VMM tries to re-run the vCPU after issuing the call.
Unfortunately, this also means that the VMM cannot see which PSCI call was issued and therefore cannot distinguish between PSCI SYSTEM_RESET and SYSTEM_RESET2 calls, which is necessary in order to determine the validity of the "reset_type" in X1.
Allocate bit 0 of the previously unused 'flags' field of the system_event structure so that we can indicate the PSCI call used to initiate the reset.
--- Documentation/virt/kvm/api.rst | 5 +++++ arch/arm64/include/uapi/asm/kvm.h | 7 +++++++ arch/arm64/kvm/psci.c | 15 +++++++++++---- 3 files changed, 23 insertions(+), 4 deletions(-)
Documentation/virt/kvm/api.rst +5 -0
@@ -5939,6 +5939,11 @@ Valid values for 'type' are: to ignore the request, or to gather VM memory core dump and/or reset/shutdown of the VM. +Valid flags are: + + - KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (arm64 only) -- the guest issued + a PSCI SYSTEM_RESET2 call with a "reset type" passed in register X1. + :: /* KVM_EXIT_IOAPIC_EOI */
arch/arm64/include/uapi/asm/kvm.h +7 -0
@@ -413,6 +413,13 @@ struct kvm_arm_copy_mte_tags {#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED +/* arm64-specific kvm_run::system_event flags */ +/* +* Reset caused by a PSCI SYSTEM_RESET2 call with a "reset_type" in x1. +* Valid only when the system event has a type of KVM_SYSTEM_EVENT_RESET. +*/ +#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0) +#endif #endif /* __ARM_KVM_H__ */
arch/arm64/kvm/psci.c +11 -4
@@ -162,7 +162,7 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)return PSCI_0_2_AFFINITY_LEVEL_OFF ; } -static void kvm_prepare_system_event (struct kvm_vcpu *vcpu,u32 type) +static void kvm_prepare_system_event (struct kvm_vcpu *vcpu,u32 type,u64 flags) {unsigned long i;struct kvm_vcpu *tmp;
@@ -182,17 +182,24 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)memset (&vcpu->run->system_event,0 ,sizeof (vcpu->run->system_event)); vcpu->run->system_event.type = type; + vcpu->run->system_event.flags = flags; vcpu->run->exit_reason =KVM_EXIT_SYSTEM_EVENT ; }static void kvm_psci_system_off (struct kvm_vcpu *vcpu) { -kvm_prepare_system_event (vcpu,KVM_SYSTEM_EVENT_SHUTDOWN ); +kvm_prepare_system_event (vcpu,KVM_SYSTEM_EVENT_SHUTDOWN ,0 ); }static void kvm_psci_system_reset (struct kvm_vcpu *vcpu) { -kvm_prepare_system_event (vcpu,KVM_SYSTEM_EVENT_RESET ); +kvm_prepare_system_event (vcpu,KVM_SYSTEM_EVENT_RESET ,0 ); +} + +static void kvm_psci_system_reset2 (struct kvm_vcpu *vcpu) +{ +kvm_prepare_system_event (vcpu,KVM_SYSTEM_EVENT_RESET , +KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 ); }static void kvm_psci_narrow_to_32bit (struct kvm_vcpu *vcpu)
@@ -364,7 +371,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor) arg < PSCI_1_1_RESET_TYPE_VENDOR_START) { val = PSCI_RET_INVALID_PARAMS; } else { -kvm_psci_system_reset (vcpu); +kvm_psci_system_reset2 (vcpu); val =PSCI_RET_INTERNAL_FAILURE ; ret =0 ; }
Signature · 6 lines
2.35.1.265.g69c8d7142f-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm