aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-02-24 13:31:31 +0000
committerPeter Maydell <peter.maydell@linaro.org>2022-02-24 13:31:31 +0000
commitd73755082669ff713e8174147e02ba6da41df76b (patch)
tree89401b860e74de8cb5a70c1358b1a51a9d7face3
parent47a3518e204a040eaac5d443493be65da2967354 (diff)
target/arm: Report KVM's actual PSCI version to guest in dtb
When we're using KVM, the PSCI implementation is provided by the kernel, but QEMU has to tell the guest about it via the device tree. Currently we look at the KVM_CAP_ARM_PSCI_0_2 capability to determine if the kernel is providing at least PSCI 0.2, but if the kernel provides a newer version than that we will still only tell the guest it has PSCI 0.2. (This is fairly harmless; it just means the guest won't use newer parts of the PSCI API.) The kernel exposes the specific PSCI version it is implementing via the ONE_REG API; use this to report in the dtb that the PSCI implementation is 1.0-compatible if appropriate. (The device tree binding currently only distinguishes "pre-0.2", "0.2-compatible" and "1.0-compatible".) Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/boot.c5
-rw-r--r--target/arm/kvm-consts.h1
-rw-r--r--target/arm/kvm64.c12
3 files changed, 15 insertions, 3 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0eeef94ceb..a47f38dfc9 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -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 {
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
index e770921ddc..faacf96fdc 100644
--- a/target/arm/kvm-consts.h
+++ b/target/arm/kvm-consts.h
@@ -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);
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 64d48bfb19..ccadfbbe72 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -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)) {
@@ -905,6 +906,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
* override our defaults with what we get from KVM.