blob: 384f522d3e2c2ef927c0304046c17b574806d92c [file] [log] [blame]
From 65bbc8575b5c362c12f7c1e88ce9161bbfa75480 Mon Sep 17 00:00:00 2001
From: David Dai <davidai@google.com>
Date: Thu, 18 May 2023 16:02:14 +0900
Subject: [PATCH] BACKPORT: FROMLIST: kvm: arm64: Add support for
get_cur_cpufreq service
This service allows guests to query the host for frequency of the CPU
that the vCPU is currently running on.
Co-developed-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: David Dai <davidai@google.com>
(am from https://patchwork.kernel.org/patch/13194986/)
(also found at https://lore.kernel.org/r/20230330224348.1006691-3-davidai@google.com)
Conflicts:
include/uapi/linux/kvm.h
Changes:
Change the hypercall ID so that it doesn't share the possible new hypercall
IDs.
Remove KVM_REG_ARM_VENDOR_HYP_BIT_GET_CUR_CPUFREQ because it was assigned
to wrong number and the correct number is out of 64bit.
GET_CUR_CPUFREQ hypercall is hidden from UAPI and always available.
BUG=b:249685960
TEST=Build
UPSTREAM-TASK=b:256983979
Change-Id: I12e23cbc8578176992a2847062b6547570fba197
Signed-off-by: Masami Hiramatsu <mhiramat@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4546352
Reviewed-by: Suleiman Souhlal <suleiman@chromium.org>
Kcr-patch: 6028b04d70558778902110e06e73067bcde3fb6eb3e41a90afd9c898.patch
---
.../virt/kvm/arm/get_cur_cpufreq.rst | 21 +++++++++++++++++++
Documentation/virt/kvm/arm/index.rst | 1 +
arch/arm64/kvm/arm.c | 1 +
arch/arm64/kvm/hypercalls.c | 19 +++++++++++++++++
include/linux/arm-smccc.h | 7 +++++++
include/uapi/linux/kvm.h | 1 +
6 files changed, 50 insertions(+)
create mode 100644 Documentation/virt/kvm/arm/get_cur_cpufreq.rst
diff --git a/Documentation/virt/kvm/arm/get_cur_cpufreq.rst b/Documentation/virt/kvm/arm/get_cur_cpufreq.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e100826d5e0973dda8c654ae5af4593abd3fc72d
--- /dev/null
+++ b/Documentation/virt/kvm/arm/get_cur_cpufreq.rst
@@ -0,0 +1,21 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+get_cur_cpufreq support for arm/arm64
+=============================
+
+Get_cur_cpufreq support is used to get current frequency(in KHz) of the
+current CPU that the vCPU thread is running on.
+
+* ARM_SMCCC_VENDOR_HYP_KVM_GET_CUR_CPUFREQ_FUNC_ID: 0x86000041
+
+This hypercall uses the SMC32/HVC32 calling convention:
+
+ARM_SMCCC_VENDOR_HYP_KVM_GET_CUR_CPUFREQ_FUNC_ID
+ ============== ======== =====================================
+ Function ID: (uint32) 0x86000041
+ Return Values: (int32) NOT_SUPPORTED(-1) on error, or
+ (uint32) Frequency in KHz of current CPU that the
+ vCPU thread is running on.
+ Endianness: Must be the same endianness
+ as the host.
+ ============== ======== =====================================
diff --git a/Documentation/virt/kvm/arm/index.rst b/Documentation/virt/kvm/arm/index.rst
index ec09881de4cf6dce07da909d174f45baf460ca46..a798573e58dcad3ba0d8e15d6e2b2ebe65884723 100644
--- a/Documentation/virt/kvm/arm/index.rst
+++ b/Documentation/virt/kvm/arm/index.rst
@@ -13,3 +13,4 @@ ARM
pvtime
ptp_kvm
vcpu-features
+ get_cur_cpufreq
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index a7ca776b51ec8a1425d457206f35811eb26fa77c..4da83002cdeffb1809404133f220d7a2b0b036c7 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -333,6 +333,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_VCPU_ATTRIBUTES:
case KVM_CAP_PTP_KVM:
case KVM_CAP_ARM_SYSTEM_SUSPEND:
+ case KVM_CAP_GET_CUR_CPUFREQ:
case KVM_CAP_IRQFD_RESAMPLE:
case KVM_CAP_COUNTER_OFFSET:
r = 1;
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 5763d979d8cae00ac206a6f80f10c2d36f86bdac..419f3d8a98e8704bb9b3c5ace5d3b5e8dbd59d80 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -3,6 +3,9 @@
#include <linux/arm-smccc.h>
#include <linux/kvm_host.h>
+#include <linux/cpufreq.h>
+#include <linux/sched.h>
+#include <uapi/linux/sched/types.h>
#include <asm/kvm_emulate.h>
@@ -16,6 +19,15 @@
#define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES \
GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT - 1, 0)
+static void kvm_sched_get_cur_cpufreq(struct kvm_vcpu *vcpu, u64 *val)
+{
+ unsigned long ret_freq;
+
+ ret_freq = cpufreq_get(task_cpu(current));
+
+ val[0] = ret_freq;
+}
+
static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
{
struct system_time_snapshot systime_snapshot;
@@ -116,6 +128,8 @@ static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id)
case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
return test_bit(KVM_REG_ARM_VENDOR_HYP_BIT_PTP,
&smccc_feat->vendor_hyp_bmap);
+ case ARM_SMCCC_VENDOR_HYP_KVM_GET_CUR_CPUFREQ_FUNC_ID:
+ return true;
default:
return false;
}
@@ -360,10 +374,15 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
break;
case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
val[0] = smccc_feat->vendor_hyp_bmap;
+ val[ARM_SMCCC_KVM_FUNC_GET_CUR_CPUFREQ / 32] |=
+ BIT(ARM_SMCCC_KVM_FUNC_GET_CUR_CPUFREQ % 32);
break;
case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
kvm_ptp_get_time(vcpu, val);
break;
+ case ARM_SMCCC_VENDOR_HYP_KVM_GET_CUR_CPUFREQ_FUNC_ID:
+ kvm_sched_get_cur_cpufreq(vcpu, val);
+ break;
case ARM_SMCCC_TRNG_VERSION:
case ARM_SMCCC_TRNG_FEATURES:
case ARM_SMCCC_TRNG_GET_UUID:
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 083f8565371616269fa0050036ec8a3631c44357..22d47cb9e62d683f54b5d4b5471a8a67b93903e9 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -115,6 +115,7 @@
/* KVM "vendor specific" services */
#define ARM_SMCCC_KVM_FUNC_FEATURES 0
#define ARM_SMCCC_KVM_FUNC_PTP 1
+#define ARM_SMCCC_KVM_FUNC_GET_CUR_CPUFREQ 65
#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
#define ARM_SMCCC_KVM_NUM_FUNCS 128
@@ -141,6 +142,12 @@
#define KVM_PTP_VIRT_COUNTER 0
#define KVM_PTP_PHYS_COUNTER 1
+#define ARM_SMCCC_VENDOR_HYP_KVM_GET_CUR_CPUFREQ_FUNC_ID \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ ARM_SMCCC_KVM_FUNC_GET_CUR_CPUFREQ)
+
/* Paravirtualised time calls (defined by ARM DEN0057A) */
#define ARM_SMCCC_HV_PV_TIME_FEATURES \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 637efc05514534ca635671f64f84bfd65a1b8ea1..7f4680a4013fce89c47b8f9c6890562540c6b63e 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -933,6 +933,7 @@ struct kvm_enable_cap {
#define KVM_CAP_PRE_FAULT_MEMORY 236
#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
#define KVM_CAP_X86_GUEST_MODE 238
+#define KVM_CAP_GET_CUR_CPUFREQ 512
struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.46.0.rc2.264.g509ed76dc8-goog