@@ -95,6 +95,7 @@ MISMATCH_CHECK(QEMU_PSCI_1_0_FN_PSCI_FEATURES, PSCI_1_0_FN_PSCI_FEATURES);
#define QEMU_PSCI_VERSION_0_1 0x00001
#define QEMU_PSCI_VERSION_0_2 0x00002
+#define QEMU_PSCI_VERSION_1_0 0x10000
#define QEMU_PSCI_VERSION_1_1 0x10001
MISMATCH_CHECK(QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED, PSCI_0_2_TOS_MP);
@@ -488,9 +488,8 @@ static void fdt_add_psci_node(void *fdt)
}
qemu_fdt_add_subnode(fdt, "/psci");
- if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2 ||
- armcpu->psci_version == QEMU_PSCI_VERSION_1_1) {
- if (armcpu->psci_version == QEMU_PSCI_VERSION_0_2) {
+ if (armcpu->psci_version >= QEMU_PSCI_VERSION_0_2) {
+ if (armcpu->psci_version < QEMU_PSCI_VERSION_1_0) {
const char comp[] = "arm,psci-0.2\0arm,psci";
qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
} else {
@@ -849,6 +849,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
uint64_t mpidr;
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
+ uint64_t psciver;
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
!object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) {
@@ -904,6 +905,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
}
+ /*
+ * KVM reports the exact PSCI version it is implementing via a
+ * special sysreg. If it is present, use its contents to determine
+ * what to report to the guest in the dtb (it is the PSCI version,
+ * in the same 15-bits major 16-bits minor format that PSCI_VERSION
+ * returns).
+ */
+ if (!kvm_get_one_reg(cs, KVM_REG_ARM_PSCI_VERSION, &psciver)) {
+ cpu->psci_version = psciver;
+ }
+
/*
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
* Currently KVM has its own idea about MPIDR assignment, so we