cpu_id = smccc_get_arg1(source_vcpu); if (!kvm_psci_valid_affinity(source_vcpu, cpu_id)) return PSCI_RET_INVALID_PARAMS;
vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);
/* *MakesurethecallerrequestedavalidCPUandthattheCPUis *turnedoff.
*/ if (!vcpu) return PSCI_RET_INVALID_PARAMS;
spin_lock(&vcpu->arch.mp_state_lock); if (!kvm_arm_vcpu_stopped(vcpu)) { if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
ret = PSCI_RET_ALREADY_ON; else
ret = PSCI_RET_INVALID_PARAMS;
staticvoid kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
{ int i;
/* *Zerotheinputregisters'upper32bits.Theywillbefully *zeroedonexit,sowe'refinechangingtheminplace.
*/ for (i = 1; i < 4; i++)
vcpu_set_reg(vcpu, i, lower_32_bits(vcpu_get_reg(vcpu, i)));
}
staticint kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
{
u32 psci_fn = smccc_get_function(vcpu); unsignedlong val; int ret = 1;
switch (psci_fn) { case PSCI_0_2_FN_PSCI_VERSION: /* *Bits[31:16]=MajorVersion=0 *Bits[15:0]=MinorVersion=2
*/
val = KVM_ARM_PSCI_0_2; break; case PSCI_0_2_FN_CPU_SUSPEND: case PSCI_0_2_FN64_CPU_SUSPEND:
val = kvm_psci_vcpu_suspend(vcpu); break; case PSCI_0_2_FN_CPU_OFF:
kvm_arm_vcpu_power_off(vcpu);
val = PSCI_RET_SUCCESS; break; case PSCI_0_2_FN_CPU_ON:
kvm_psci_narrow_to_32bit(vcpu);
fallthrough; case PSCI_0_2_FN64_CPU_ON:
val = kvm_psci_vcpu_on(vcpu); break; case PSCI_0_2_FN_AFFINITY_INFO:
kvm_psci_narrow_to_32bit(vcpu);
fallthrough; case PSCI_0_2_FN64_AFFINITY_INFO:
val = kvm_psci_vcpu_affinity_info(vcpu); break; case PSCI_0_2_FN_MIGRATE_INFO_TYPE: /* *TrustedOSisMPhencedoesnotrequiremigration *or *TrustedOSisnotpresent
*/
val = PSCI_0_2_TOS_MP; break; case PSCI_0_2_FN_SYSTEM_OFF:
kvm_psci_system_off(vcpu); /* *Weshouldn'tbegoingbacktoguestVCPUafter *receivingSYSTEM_OFFrequest. * *Ifuserspaceaccidentally/deliberatelyresumes *guestVCPUafterSYSTEM_OFFrequestthenguest *VCPUshouldseeinternalfailurefromPSCIreturn *value.Toachievethis,wepreloadr0(orx0)with *PSCIreturnvalueINTERNAL_FAILURE.
*/
val = PSCI_RET_INTERNAL_FAILURE;
ret = 0; break; case PSCI_0_2_FN_SYSTEM_RESET:
kvm_psci_system_reset(vcpu); /* *SamereasonasSYSTEM_OFFforpreloadingr0(orx0) *withPSCIreturnvalueINTERNAL_FAILURE.
*/
val = PSCI_RET_INTERNAL_FAILURE;
ret = 0; break; default:
val = PSCI_RET_NOT_SUPPORTED; break;
}
staticint kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
{ unsignedlong val = PSCI_RET_NOT_SUPPORTED;
u32 psci_fn = smccc_get_function(vcpu); struct kvm *kvm = vcpu->kvm;
u32 arg; int ret = 1;
switch(psci_fn) { case PSCI_0_2_FN_PSCI_VERSION:
val = PSCI_VERSION(1, minor); break; case PSCI_1_0_FN_PSCI_FEATURES:
arg = smccc_get_arg1(vcpu);
val = kvm_psci_check_allowed_function(vcpu, arg); if (val) break;
val = PSCI_RET_NOT_SUPPORTED;
switch(arg) { case PSCI_0_2_FN_PSCI_VERSION: case PSCI_0_2_FN_CPU_SUSPEND: case PSCI_0_2_FN64_CPU_SUSPEND: case PSCI_0_2_FN_CPU_OFF: case PSCI_0_2_FN_CPU_ON: case PSCI_0_2_FN64_CPU_ON: case PSCI_0_2_FN_AFFINITY_INFO: case PSCI_0_2_FN64_AFFINITY_INFO: case PSCI_0_2_FN_MIGRATE_INFO_TYPE: case PSCI_0_2_FN_SYSTEM_OFF: case PSCI_0_2_FN_SYSTEM_RESET: case PSCI_1_0_FN_PSCI_FEATURES: case ARM_SMCCC_VERSION_FUNC_ID:
val = 0; break; case PSCI_1_0_FN_SYSTEM_SUSPEND: case PSCI_1_0_FN64_SYSTEM_SUSPEND: if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags))
val = 0; break; case PSCI_1_1_FN_SYSTEM_RESET2: case PSCI_1_1_FN64_SYSTEM_RESET2: if (minor >= 1)
val = 0; break; case PSCI_1_3_FN_SYSTEM_OFF2: case PSCI_1_3_FN64_SYSTEM_OFF2: if (minor >= 3)
val = PSCI_1_3_OFF_TYPE_HIBERNATE_OFF; break;
} break; case PSCI_1_0_FN_SYSTEM_SUSPEND:
kvm_psci_narrow_to_32bit(vcpu);
fallthrough; case PSCI_1_0_FN64_SYSTEM_SUSPEND: /* *ReturndirectlytouserspacewithoutchangingthevCPU's *registers.UserspacedependsonreadingtheSMCCCparameters *toimplementSYSTEM_SUSPEND.
*/ if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags)) {
kvm_psci_system_suspend(vcpu); return0;
} 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);
val = PSCI_RET_INVALID_PARAMS; break;
} break; case PSCI_1_3_FN_SYSTEM_OFF2:
kvm_psci_narrow_to_32bit(vcpu);
fallthrough; case PSCI_1_3_FN64_SYSTEM_OFF2: if (minor < 3) break;
switch (psci_fn) { case KVM_PSCI_FN_CPU_OFF:
kvm_arm_vcpu_power_off(vcpu);
val = PSCI_RET_SUCCESS; break; case KVM_PSCI_FN_CPU_ON:
val = kvm_psci_vcpu_on(vcpu); break; default:
val = PSCI_RET_NOT_SUPPORTED; break;
}
smccc_set_retval(vcpu, val, 0, 0, 0); return1;
}
/** *kvm_psci_call-handlePSCIcallifr0valueisinrange *@vcpu:PointertotheVCPUstruct * *HandlePSCIcallsfromgueststhroughtrapsfromHVCinstructions. *ThecallingconventionissimilartoSMCcallstothesecureworld *wherethefunctionnumberisplacedinr0. * *Thisfunctionreturns:>0(success),0(successbutexittouser *space),and<0(errors) * *Errors: *-EINVAL:UnrecognizedPSCIfunction
*/ int kvm_psci_call(struct kvm_vcpu *vcpu)
{
u32 psci_fn = smccc_get_function(vcpu); int version = kvm_psci_version(vcpu); unsignedlong val;
val = kvm_psci_check_allowed_function(vcpu, psci_fn); if (val) {
smccc_set_retval(vcpu, val, 0, 0, 0); return1;
}
switch (version) { case KVM_ARM_PSCI_1_3: return kvm_psci_1_x_call(vcpu, 3); case KVM_ARM_PSCI_1_2: return kvm_psci_1_x_call(vcpu, 2); case KVM_ARM_PSCI_1_1: return kvm_psci_1_x_call(vcpu, 1); case KVM_ARM_PSCI_1_0: 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: return kvm_psci_0_1_call(vcpu); default:
WARN_ONCE(1, "Unknown PSCI version %d", version);
smccc_set_retval(vcpu, SMCCC_RET_NOT_SUPPORTED, 0, 0, 0); return1;
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-09-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.