* [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs
@ 2025-08-01 7:47 Shameer Kolothum
2025-08-01 7:47 ` [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support Shameer Kolothum
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Shameer Kolothum @ 2025-08-01 7:47 UTC (permalink / raw)
To: qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, cohuck, sebott, berrange, maz,
oliver.upton, armbru, linuxarm, wangzhou1, jiangkunkun,
jonathan.cameron, salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
(This is my third attempt to send this series to qemu-devel / qemu-arm.
Previous attempts failed with the following errors:
qemu-arm@nongnu.org: connect to eggs.gnu.org[209.51.188.92]:25: Connection timed out
qemu-devel@nongnu.org: connect to eggs.gnu.org[209.51.188.92]:25: Connection timed out
I'm not sure if the issue is related to my setup, so I'm now trying to send the
patches via my Gmail account.
Apologies if you’ve already received this series individually, and thank you
for your patience.)
Hi,
On ARM64 platforms, many errata workarounds are based on CPU identification
registers, particularly MIDR_EL1 and REVIDR_EL1. Some of these errata
require corresponding fixes in the guest kernel as well. This becomes a
challenge during guest migration between hosts with different MIDR/REVIDR
values, even when the VMM provides a common baseline feature set using
the recently introduced writable ID register support.
To address this, the Linux kernel now provides:
-A mechanism to expose implementation CPU data to guests via KVM
hypercalls [0]:
ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID
ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID
-A way to override implementation ID registers (MIDR, REVIDR, AIDR),
which were previously treated as invariant [1].
What this RFC does:
This RFC enables the virt machine to specify Target Implementation CPUs
via QEMU command-line, exposing them to the guest via KVM hypercalls.
Example use case (hosts with differing MIDRs):
./qemu-system-aarch64 -machine virt,gic-version=3 \
-enable-kvm \
-bios QEMU_EFI.fd \
-m 1G -smp cpus=4,maxcpus=4 \
-cpu host \
-M impl-cpu.0.midr=0x481fd010,impl-cpu.0.revidr=0,impl-cpu.0.aidr=0x551,\
impl-cpu.1.midr=0x481fd011,impl-cpu.1.revidr=0,impl-cpu.1.aidr=0x551 \
-kernel Image-6.16-rc2 \
-initrd rootfs-iperf.cpio \
-append "rdinit=init console=ttyAMA0 root=/dev/vda rw earlycon=pl011,0x9000000 kpti=off" \
-net none \
-nographic
Highlights and Notes:
-This is based on Connie’s series[2] “kvm/arm: Introduce a customizable
aarch64 KVM host model”.
-Currently, no validation is performed on user-specified implementation CPU
data. It’s assumed that one of the entries reflects the actual host CPU.
If needed, a check can be added to enforce this. All other target CPU
definitions are treated as user-driven with no internal verification.
-For now, only the DISCOVER_IMPL_* hypercalls are supported on the QEMU side.
See patches 1 and 3 for implementation details. These are loosely inspired
by Salil's vCPU hotplug series patch here [3]. This may require a more
generic approach if we have to support other SMCCC hyper calls.
-This series uses macros and definitions from the kernel's
include/linux/arm-smccc.h. I am not sure whether these should be duplicated
in QEMU or moved to a UAPI header in the kernel. For now I am carrying
it in the test branch here,
https://github.com/hisilicon/qemu/commit/8f583c76a2a5f60cf0f9616d61d0863e524ef388
This is lightly tested on HiSilicon ARM platforms. A complete test branch
can be found here,
https://github.com/hisilicon/qemu/tree/arm-cpu-model-rfcv3-tgt-impl-cpu-rfcv1
Please take a look and let me know.
Thanks,
Shameer
[0] https://lore.kernel.org/all/20250221140229.12588-1-shameerali.kolothum.thodi@huawei.com/
[1] https://lore.kernel.org/all/20250225005401.679536-1-oliver.upton@linux.dev/
[2] https://lore.kernel.org/qemu-devel/20250414163849.321857-1-cohuck@redhat.com/
[3] https://lore.kernel.org/qemu-devel/20240614001510.202991-1-salil.mehta@huawei.com/
Shameer Kolothum (4):
target/arm/kvm: Introduce helper to check target impl CPU support
target/arm/kvm: Add QAPI struct ArmTargetImplCPU
target/arm/kvm: Handle KVM Target Imp CPU hypercalls
hw/arm/virt: Add Target Implementation CPU support
hw/arm/virt.c | 66 +++++++++++++++
include/hw/arm/virt.h | 3 +
qapi/machine.json | 34 ++++++++
target/arm/kvm.c | 187 ++++++++++++++++++++++++++++++++++++++++++
target/arm/kvm_arm.h | 20 +++++
5 files changed, 310 insertions(+)
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
@ 2025-08-01 7:47 ` Shameer Kolothum
2025-08-09 16:21 ` Eric Auger
2025-08-01 7:47 ` [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU Shameer Kolothum
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Shameer Kolothum @ 2025-08-01 7:47 UTC (permalink / raw)
To: qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, cohuck, sebott, berrange, maz,
oliver.upton, armbru, linuxarm, wangzhou1, jiangkunkun,
jonathan.cameron, salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
The helper function will try to set the SMCCC filters for KVM vendor
hypercalls related to target implementation CPU support. It also
checks the kernel support for writable implementation ID registers
(MIDR/REVIDR/AIDR) and enables it.
Subsequent patches for Target Impl CPU support will make use of this
helper.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
target/arm/kvm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
target/arm/kvm_arm.h | 12 ++++++++
2 files changed, 84 insertions(+)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 3f41f99e23..eb04640b50 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -2072,6 +2072,78 @@ bool kvm_arm_mte_supported(void)
return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
}
+static bool kvm_arm_set_vm_attr(struct kvm_device_attr *attr, const char *name)
+{
+ int err;
+
+ err = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, attr);
+ if (err != 0) {
+ error_report("%s: KVM_HAS_DEVICE_ATTR: %s", name, strerror(-err));
+ return false;
+ }
+
+ err = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, attr);
+ if (err != 0) {
+ error_report("%s: KVM_SET_DEVICE_ATTR: %s", name, strerror(-err));
+ return false;
+ }
+
+ return true;
+}
+
+static bool kvm_arm_set_smccc_filter(uint64_t func, uint8_t faction)
+{
+ struct kvm_smccc_filter filter = {
+ .base = func,
+ .nr_functions = 1,
+ .action = faction,
+ };
+ struct kvm_device_attr attr = {
+ .group = KVM_ARM_VM_SMCCC_CTRL,
+ .attr = KVM_ARM_VM_SMCCC_FILTER,
+ .flags = 0,
+ .addr = (uintptr_t)&filter,
+ };
+
+ if (!kvm_arm_set_vm_attr(&attr, "SMCCC Filter")) {
+ error_report("failed to set SMCCC filter in KVM Host");
+ return false;
+ }
+
+ return true;
+}
+
+bool kvm_arm_target_impl_cpus_supported(void)
+{
+ if (!kvm_arm_set_smccc_filter(
+ ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID,
+ KVM_SMCCC_FILTER_FWD_TO_USER)) {
+ error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER fwd filter "
+ "install failed");
+ return false;
+ }
+
+ if (!kvm_arm_set_smccc_filter(
+ ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID,
+ KVM_SMCCC_FILTER_FWD_TO_USER)) {
+ error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS fwd filter "
+ "install failed");
+ return false;
+ }
+
+ if (!kvm_check_extension(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS)) {
+ error_report("KVM_CAP_ARM_WRITABLE_IMP_ID_REGS not supported");
+ return false;
+ }
+
+ if (kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0)) {
+ error_report("Failed to enable KVM_CAP_ARM_WRITABLE_IMP_ID_REGS cap");
+ return false;
+ }
+
+ return true;
+}
+
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index ba5de45f86..3cd6447901 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -207,6 +207,13 @@ bool kvm_arm_sve_supported(void);
*/
bool kvm_arm_mte_supported(void);
+/**
+ * kvm_arm_target_impl_cpus_supported:
+ *
+ * Returns: true if KVM can enable target impl CPUs, and false otherwise.
+ */
+bool kvm_arm_target_impl_cpus_supported(void);
+
/**
* kvm_arm_get_max_vm_ipa_size:
* @ms: Machine state handle
@@ -263,6 +270,11 @@ static inline bool kvm_arm_mte_supported(void)
return false;
}
+static inline bool kvm_arm_target_impl_cpus_supported(void)
+{
+ return false;
+}
+
static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
{
return -ENOSYS;
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
2025-08-01 7:47 ` [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support Shameer Kolothum
@ 2025-08-01 7:47 ` Shameer Kolothum
2025-08-09 16:23 ` Eric Auger
2025-08-01 7:47 ` [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls Shameer Kolothum
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Shameer Kolothum @ 2025-08-01 7:47 UTC (permalink / raw)
To: qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, cohuck, sebott, berrange, maz,
oliver.upton, armbru, linuxarm, wangzhou1, jiangkunkun,
jonathan.cameron, salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Introduce a QAPI‐defined struct (and its array) for target implementation
CPUs. This enables specifying target implementation CPU parameters
via -machine, for example:
-M virt, \
impl-cpu.0.midr=1,impl-cpu.0.revidr=1,impl-cpu.0.aidr=1, \
impl-cpu.1.midr=2,impl-cpu.1.revidr=2,impl-cpu.1.aidr=0
Subsequent patch will make use of this by using object_property_add(),
allowing users to configure each target CPU’s midr, revidr, and aidr
fields directly from the command line.
While at it, also provide a helper function to set the target CPUs.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
qapi/machine.json | 34 ++++++++++++++++++++++++++++++++++
target/arm/kvm.c | 16 ++++++++++++++++
target/arm/kvm_arm.h | 8 ++++++++
3 files changed, 58 insertions(+)
diff --git a/qapi/machine.json b/qapi/machine.json
index a6b8795b09..d6e0e3b2e3 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1898,3 +1898,37 @@
{ 'command': 'x-query-interrupt-controllers',
'returns': 'HumanReadableText',
'features': [ 'unstable' ]}
+
+##
+# @ArmTargetImplCPU:
+#
+# Info for a single target implementation CPU.
+#
+# @midr: MIDR value
+# @revidr: REVIDR value
+# @aidr: AIDR value
+#
+# Since: 10.2
+##
+{ 'struct': 'ArmTargetImplCPU',
+ 'data': {
+ 'midr': 'uint64',
+ 'revidr': 'uint64',
+ 'aidr': 'uint64'
+ }
+}
+
+##
+# @ArmTargetImplCPUs:
+#
+# List of target implementation CPUs.
+#
+# @target-cpus: List of ArmTargetImplCPU entries.
+#
+# Since: 10.2
+##
+{ 'struct': 'ArmTargetImplCPUs',
+ 'data': {
+ 'target-cpus': ['ArmTargetImplCPU']
+ }
+}
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index eb04640b50..8f325c4ca4 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -66,6 +66,9 @@ typedef struct ARMHostCPUFeatures {
static ARMHostCPUFeatures arm_host_cpu_features;
+static uint64_t target_impl_cpus_num;
+static ArmTargetImplCPU *target_impl_cpus;
+
/**
* kvm_arm_vcpu_init:
* @cpu: ARMCPU
@@ -2816,3 +2819,16 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
cpu->kvm_mte = true;
}
}
+
+bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus)
+{
+
+ if (target_impl_cpus_num) {
+ return false;
+ }
+
+ target_impl_cpus_num = num;
+ target_impl_cpus = cpus;
+
+ return true;
+}
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 3cd6447901..8754302333 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -244,6 +244,8 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap);
+bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus);
+
#else
/*
@@ -280,6 +282,12 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
return -ENOSYS;
}
+static inline
+bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus)
+{
+ return false;
+}
+
/*
* These functions should never actually be called without KVM support.
*/
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
2025-08-01 7:47 ` [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support Shameer Kolothum
2025-08-01 7:47 ` [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU Shameer Kolothum
@ 2025-08-01 7:47 ` Shameer Kolothum
2025-09-19 10:51 ` Sebastian Ott
2025-08-01 7:47 ` [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support Shameer Kolothum
2025-08-01 8:31 ` [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Cornelia Huck
4 siblings, 1 reply; 10+ messages in thread
From: Shameer Kolothum @ 2025-08-01 7:47 UTC (permalink / raw)
To: qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, cohuck, sebott, berrange, maz,
oliver.upton, armbru, linuxarm, wangzhou1, jiangkunkun,
jonathan.cameron, salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
When target implementation CPUs are set, handle the related hyper calls
correctly by returning the information requested.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
target/arm/kvm.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 8f325c4ca4..5adecc864e 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -1697,6 +1697,71 @@ static bool kvm_arm_handle_debug(ARMCPU *cpu,
return false;
}
+/* Only supports HYP_KVM_DISCOVER_IMPL_XXX hypercalls */
+static void arm_handle_smccc_kvm_vendor_hypercall(ARMCPU *cpu)
+{
+ CPUARMState *env = &cpu->env;
+ uint64_t param[4] = { };
+ uint64_t idx;
+
+ if (!is_a64(env)) {
+ env->regs[0] = SMCCC_RET_NOT_SUPPORTED;
+ return;
+ }
+
+ memcpy(param, env->xregs, sizeof(param));
+
+ switch (param[0]) {
+ case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID:
+ if (!target_impl_cpus_num) {
+ env->xregs[0] = SMCCC_RET_NOT_SUPPORTED;
+ return;
+ }
+ env->xregs[0] = SMCCC_RET_SUCCESS;
+ env->xregs[1] = PSCI_VERSION(1, 0);
+ env->xregs[2] = target_impl_cpus_num;
+ break;
+ case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID:
+ idx = param[1];
+
+ if (!target_impl_cpus_num || idx >= target_impl_cpus_num) {
+ env->xregs[0] = SMCCC_RET_INVALID_PARAMETER;
+ return;
+ }
+
+ env->xregs[0] = SMCCC_RET_SUCCESS;
+ env->xregs[1] = target_impl_cpus[idx].midr;
+ env->xregs[2] = target_impl_cpus[idx].revidr;
+ env->xregs[3] = target_impl_cpus[idx].aidr;
+ break;
+ default:
+ env->xregs[0] = SMCCC_RET_NOT_SUPPORTED;
+ }
+}
+
+static int kvm_arm_handle_hypercall(CPUState *cs, struct kvm_run *run)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
+ kvm_cpu_synchronize_state(cs);
+
+ if (run->hypercall.flags == KVM_HYPERCALL_EXIT_SMC) {
+ cs->exception_index = EXCP_SMC;
+ env->exception.syndrome = syn_aa64_smc(0);
+ } else {
+ cs->exception_index = EXCP_HVC;
+ env->exception.syndrome = syn_aa64_hvc(0);
+ }
+ env->exception.target_el = 1;
+
+ bql_lock();
+ arm_handle_smccc_kvm_vendor_hypercall(cpu);
+ bql_unlock();
+
+ return EXCP_INTERRUPT;
+}
+
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
ARMCPU *cpu = ARM_CPU(cs);
@@ -1713,6 +1778,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
ret = kvm_arm_handle_dabt_nisv(cpu, run->arm_nisv.esr_iss,
run->arm_nisv.fault_ipa);
break;
+ case KVM_EXIT_HYPERCALL:
+ ret = kvm_arm_handle_hypercall(cs, run);
+ break;
default:
qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
__func__, run->exit_reason);
@@ -2212,6 +2280,29 @@ static int kvm_arm_sve_set_vls(ARMCPU *cpu)
return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM64_SVE_VLS, &vls[0]);
}
+/*
+ * Supported Target Implementation CPU hypercalls:
+ * KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER = 0,
+ * KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS = 1
+ *
+ * Setting these bits advertises the availability of the corresponding
+ * Target Implementation CPU hypercalls to the guest.
+ */
+#define BMAP_2_DISCOVER_IMPL_BITS 0x3ULL
+static int kvm_arm_target_impl_cpus_set_hyp_bmap2(ARMCPU *cpu)
+{
+ uint64_t bmap2;
+ int ret;
+
+ ret = kvm_get_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap2);
+ if (ret) {
+ return ret;
+ }
+
+ bmap2 |= BMAP_2_DISCOVER_IMPL_BITS;
+ return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap2);
+}
+
#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
int kvm_arch_init_vcpu(CPUState *cs)
@@ -2293,6 +2384,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
+ /* Set KVM_REG_ARM_VENDOR_HYP_BMAP_2 if target impl CPUs are required */
+ if (target_impl_cpus_num) {
+ ret = kvm_arm_target_impl_cpus_set_hyp_bmap2(cpu);
+ if (ret) {
+ return ret;
+ }
+ }
+
ret = kvm_arm_init_cpreg_list(cpu);
if (ret) {
return ret;
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
` (2 preceding siblings ...)
2025-08-01 7:47 ` [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls Shameer Kolothum
@ 2025-08-01 7:47 ` Shameer Kolothum
2025-08-09 16:21 ` Eric Auger
2025-08-01 8:31 ` [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Cornelia Huck
4 siblings, 1 reply; 10+ messages in thread
From: Shameer Kolothum @ 2025-08-01 7:47 UTC (permalink / raw)
To: qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, cohuck, sebott, berrange, maz,
oliver.upton, armbru, linuxarm, wangzhou1, jiangkunkun,
jonathan.cameron, salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Add the impl-cpu property to virt machine. This will enable
user to specify the target implementation CPUs as the example
below:
...
-M impl-cpu.0.midr=1,impl-cpu.0.revidr=1,impl-cpu.0.aidr=1,\
impl-cpu.1.midr=2,impl-cpu.1.revidr=2,impl-cpu.1.aidr=2 \
Make use of helper functions to check the KVM support for target
Impl CPUs and if supported set the user specified target CPUs.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
hw/arm/virt.c | 66 +++++++++++++++++++++++++++++++++++++++++++
include/hw/arm/virt.h | 3 ++
2 files changed, 69 insertions(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index a96452f17a..72a0cd3ea8 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -71,6 +71,7 @@
#include "hw/firmware/smbios.h"
#include "qapi/visitor.h"
#include "qapi/qapi-visit-common.h"
+#include "qapi/qapi-visit-machine.h"
#include "qobject/qlist.h"
#include "standard-headers/linux/input.h"
#include "hw/arm/smmuv3.h"
@@ -2232,6 +2233,20 @@ static void machvirt_init(MachineState *machine)
exit(1);
}
+ if (vms->target_cpus_num) {
+ if (!kvm_enabled()) {
+ error_report("Target Impl CPU requested, but not supported "
+ "without KVM");
+ exit(1);
+ }
+
+ if (!kvm_arm_target_impl_cpus_supported()) {
+ error_report("Target Impl CPU requested, but not supported by KVM");
+ exit(1);
+ }
+ kvm_arm_set_target_impl_cpus(vms->target_cpus_num, vms->target_cpus);
+ }
+
create_fdt(vms);
assert(possible_cpus->len == max_cpus);
@@ -2666,6 +2681,45 @@ static void virt_set_oem_table_id(Object *obj, const char *value,
strncpy(vms->oem_table_id, value, 8);
}
+static void virt_set_target_impl_cpus(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+ ArmTargetImplCPUList *list = NULL;
+ ArmTargetImplCPUList *iter = NULL;
+ ArmTargetImplCPU *target_cpus;
+ uint64_t target_num = 0;
+ int i;
+
+ visit_type_ArmTargetImplCPUList(v, name, &list, errp);
+ if (!list) {
+ return;
+ }
+
+ for (iter = list; iter; iter = iter->next) {
+ target_num++;
+ }
+
+ target_cpus = g_new0(ArmTargetImplCPU, target_num);
+ for (i = 0, iter = list; iter; iter = iter->next, i++) {
+ target_cpus[i].midr = iter->value->midr;
+ target_cpus[i].revidr = iter->value->revidr;
+ target_cpus[i].aidr = iter->value->aidr;
+ }
+ vms->target_cpus_num = target_num;
+ vms->target_cpus = target_cpus;
+ vms->target_cpus_list = list;
+}
+
+static void virt_get_target_impl_cpus(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+ ArmTargetImplCPUList **list = &vms->target_cpus_list;
+
+ visit_type_ArmTargetImplCPUList(v, name, list, errp);
+}
bool virt_is_acpi_enabled(VirtMachineState *vms)
{
@@ -3326,6 +3380,18 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
"Override the default value of field OEM Table ID "
"in ACPI table header."
"The string may be up to 8 bytes in size");
+ object_class_property_add(oc, "impl-cpu", "ArmTargetImplCPU",
+ virt_get_target_impl_cpus,
+ virt_set_target_impl_cpus,
+ NULL, NULL);
+ object_class_property_set_description(oc, "impl-cpu",
+ "Describe target implementation CPU in the format: "
+ "impl-cpu.0.midr=1,"
+ "impl-cpu.0.revidr=1,"
+ "impl-cpu.0.aidr=1,"
+ "impl-cpu.1.midr=2,"
+ "impl-cpu.1.revidr=2,"
+ "impl-cpu.1.aidr=2");
}
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index c8e94e6aed..cf462fcb37 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -180,6 +180,9 @@ struct VirtMachineState {
char *oem_id;
char *oem_table_id;
bool ns_el2_virt_timer_irq;
+ uint64_t target_cpus_num;
+ ArmTargetImplCPU *target_cpus;
+ ArmTargetImplCPUList *target_cpus_list;
};
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
` (3 preceding siblings ...)
2025-08-01 7:47 ` [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support Shameer Kolothum
@ 2025-08-01 8:31 ` Cornelia Huck
4 siblings, 0 replies; 10+ messages in thread
From: Cornelia Huck @ 2025-08-01 8:31 UTC (permalink / raw)
To: Shameer Kolothum, qemu-arm, qemu-devel
Cc: eric.auger, peter.maydell, sebott, berrange, maz, oliver.upton,
armbru, linuxarm, wangzhou1, jiangkunkun, jonathan.cameron,
salil.mehta, yangjinqian1, shameerkolothum,
shameerali.kolothum.thodi
On Fri, Aug 01 2025, Shameer Kolothum <shameerkolothum@gmail.com> wrote:
> From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
>
> (This is my third attempt to send this series to qemu-devel / qemu-arm.
> Previous attempts failed with the following errors:
>
> qemu-arm@nongnu.org: connect to eggs.gnu.org[209.51.188.92]:25: Connection timed out
> qemu-devel@nongnu.org: connect to eggs.gnu.org[209.51.188.92]:25: Connection timed out
>
> I'm not sure if the issue is related to my setup, so I'm now trying to send the
> patches via my Gmail account.
>
> Apologies if you’ve already received this series individually, and thank you
> for your patience.)
FWIW, all of your mails have made it into my inbox -- let's see if at
least my reply shows up on the lists :/
>
> Hi,
>
> On ARM64 platforms, many errata workarounds are based on CPU identification
> registers, particularly MIDR_EL1 and REVIDR_EL1. Some of these errata
> require corresponding fixes in the guest kernel as well. This becomes a
> challenge during guest migration between hosts with different MIDR/REVIDR
> values, even when the VMM provides a common baseline feature set using
> the recently introduced writable ID register support.
>
> To address this, the Linux kernel now provides:
>
> -A mechanism to expose implementation CPU data to guests via KVM
> hypercalls [0]:
>
> ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID
> ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID
>
> -A way to override implementation ID registers (MIDR, REVIDR, AIDR),
> which were previously treated as invariant [1].
>
> What this RFC does:
>
> This RFC enables the virt machine to specify Target Implementation CPUs
> via QEMU command-line, exposing them to the guest via KVM hypercalls.
>
> Example use case (hosts with differing MIDRs):
>
> ./qemu-system-aarch64 -machine virt,gic-version=3 \
> -enable-kvm \
> -bios QEMU_EFI.fd \
> -m 1G -smp cpus=4,maxcpus=4 \
> -cpu host \
> -M impl-cpu.0.midr=0x481fd010,impl-cpu.0.revidr=0,impl-cpu.0.aidr=0x551,\
> impl-cpu.1.midr=0x481fd011,impl-cpu.1.revidr=0,impl-cpu.1.aidr=0x551 \
> -kernel Image-6.16-rc2 \
> -initrd rootfs-iperf.cpio \
> -append "rdinit=init console=ttyAMA0 root=/dev/vda rw earlycon=pl011,0x9000000 kpti=off" \
> -net none \
> -nographic
>
> Highlights and Notes:
>
> -This is based on Connie’s series[2] “kvm/arm: Introduce a customizable
> aarch64 KVM host model”.
Hm, I *really* need to do a respin of that one, at least to bring it up
to date with the code that changed underneath...
>
> -Currently, no validation is performed on user-specified implementation CPU
> data. It’s assumed that one of the entries reflects the actual host CPU.
> If needed, a check can be added to enforce this. All other target CPU
> definitions are treated as user-driven with no internal verification.
Should that check rather be done by management software on top? Although
I assume that this is the part that in practice will come up with the
list of possible target cpus.
>
> -For now, only the DISCOVER_IMPL_* hypercalls are supported on the QEMU side.
> See patches 1 and 3 for implementation details. These are loosely inspired
> by Salil's vCPU hotplug series patch here [3]. This may require a more
> generic approach if we have to support other SMCCC hyper calls.
>
> -This series uses macros and definitions from the kernel's
> include/linux/arm-smccc.h. I am not sure whether these should be duplicated
> in QEMU or moved to a UAPI header in the kernel. For now I am carrying
> it in the test branch here,
> https://github.com/hisilicon/qemu/commit/8f583c76a2a5f60cf0f9616d61d0863e524ef388
>
> This is lightly tested on HiSilicon ARM platforms. A complete test branch
> can be found here,
> https://github.com/hisilicon/qemu/tree/arm-cpu-model-rfcv3-tgt-impl-cpu-rfcv1
>
> Please take a look and let me know.
>
> Thanks,
> Shameer
>
> [0] https://lore.kernel.org/all/20250221140229.12588-1-shameerali.kolothum.thodi@huawei.com/
> [1] https://lore.kernel.org/all/20250225005401.679536-1-oliver.upton@linux.dev/
> [2] https://lore.kernel.org/qemu-devel/20250414163849.321857-1-cohuck@redhat.com/
> [3] https://lore.kernel.org/qemu-devel/20240614001510.202991-1-salil.mehta@huawei.com/
>
> Shameer Kolothum (4):
> target/arm/kvm: Introduce helper to check target impl CPU support
> target/arm/kvm: Add QAPI struct ArmTargetImplCPU
> target/arm/kvm: Handle KVM Target Imp CPU hypercalls
> hw/arm/virt: Add Target Implementation CPU support
>
> hw/arm/virt.c | 66 +++++++++++++++
> include/hw/arm/virt.h | 3 +
> qapi/machine.json | 34 ++++++++
> target/arm/kvm.c | 187 ++++++++++++++++++++++++++++++++++++++++++
> target/arm/kvm_arm.h | 20 +++++
> 5 files changed, 310 insertions(+)
>
> --
> 2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support
2025-08-01 7:47 ` [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support Shameer Kolothum
@ 2025-08-09 16:21 ` Eric Auger
0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2025-08-09 16:21 UTC (permalink / raw)
To: Shameer Kolothum, qemu-arm, qemu-devel
Cc: peter.maydell, cohuck, sebott, berrange, maz, oliver.upton,
armbru, linuxarm, wangzhou1, jiangkunkun, jonathan.cameron,
salil.mehta, yangjinqian1, shameerali.kolothum.thodi
Hi Shameer,
On 8/1/25 9:47 AM, Shameer Kolothum wrote:
> From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
>
> Add the impl-cpu property to virt machine. This will enable
> user to specify the target implementation CPUs as the example
> below:
>
> ...
> -M impl-cpu.0.midr=1,impl-cpu.0.revidr=1,impl-cpu.0.aidr=1,\
> impl-cpu.1.midr=2,impl-cpu.1.revidr=2,impl-cpu.1.aidr=2 \
>
> Make use of helper functions to check the KVM support for target
> Impl CPUs and if supported set the user specified target CPUs.
I think you need to document the new virt options in
docs/system/arm/virt.rst
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> hw/arm/virt.c | 66 +++++++++++++++++++++++++++++++++++++++++++
> include/hw/arm/virt.h | 3 ++
> 2 files changed, 69 insertions(+)
>
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index a96452f17a..72a0cd3ea8 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -71,6 +71,7 @@
> #include "hw/firmware/smbios.h"
> #include "qapi/visitor.h"
> #include "qapi/qapi-visit-common.h"
> +#include "qapi/qapi-visit-machine.h"
> #include "qobject/qlist.h"
> #include "standard-headers/linux/input.h"
> #include "hw/arm/smmuv3.h"
> @@ -2232,6 +2233,20 @@ static void machvirt_init(MachineState *machine)
> exit(1);
> }
>
> + if (vms->target_cpus_num) {
> + if (!kvm_enabled()) {
> + error_report("Target Impl CPU requested, but not supported "
> + "without KVM");
> + exit(1);
> + }
> +
> + if (!kvm_arm_target_impl_cpus_supported()) {
> + error_report("Target Impl CPU requested, but not supported by KVM");
> + exit(1);
> + }
> + kvm_arm_set_target_impl_cpus(vms->target_cpus_num, vms->target_cpus);
> + }
> +
> create_fdt(vms);
>
> assert(possible_cpus->len == max_cpus);
> @@ -2666,6 +2681,45 @@ static void virt_set_oem_table_id(Object *obj, const char *value,
> strncpy(vms->oem_table_id, value, 8);
> }
>
> +static void virt_set_target_impl_cpus(Object *obj, Visitor *v,
> + const char *name, void *opaque,
> + Error **errp)
> +{
> + VirtMachineState *vms = VIRT_MACHINE(obj);
> + ArmTargetImplCPUList *list = NULL;
> + ArmTargetImplCPUList *iter = NULL;
> + ArmTargetImplCPU *target_cpus;
> + uint64_t target_num = 0;
> + int i;
> +
> + visit_type_ArmTargetImplCPUList(v, name, &list, errp);
> + if (!list) {
> + return;
> + }
> +
> + for (iter = list; iter; iter = iter->next) {
> + target_num++;
> + }
> +
> + target_cpus = g_new0(ArmTargetImplCPU, target_num);
> + for (i = 0, iter = list; iter; iter = iter->next, i++) {
> + target_cpus[i].midr = iter->value->midr;
> + target_cpus[i].revidr = iter->value->revidr;
> + target_cpus[i].aidr = iter->value->aidr;
> + }
Can't you avoid having both an array and a list. Can you use the list
all the way?
> + vms->target_cpus_num = target_num;
> + vms->target_cpus = target_cpus;
> + vms->target_cpus_list = list;
> +}
> +
> +static void virt_get_target_impl_cpus(Object *obj, Visitor *v, const char *name,
> + void *opaque, Error **errp)
> +{
> + VirtMachineState *vms = VIRT_MACHINE(obj);
> + ArmTargetImplCPUList **list = &vms->target_cpus_list;
> +
> + visit_type_ArmTargetImplCPUList(v, name, list, errp);
> +}
>
> bool virt_is_acpi_enabled(VirtMachineState *vms)
> {
> @@ -3326,6 +3380,18 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
> "Override the default value of field OEM Table ID "
> "in ACPI table header."
> "The string may be up to 8 bytes in size");
> + object_class_property_add(oc, "impl-cpu", "ArmTargetImplCPU",
> + virt_get_target_impl_cpus,
> + virt_set_target_impl_cpus,
> + NULL, NULL);
> + object_class_property_set_description(oc, "impl-cpu",
> + "Describe target implementation CPU in the format: "
> + "impl-cpu.0.midr=1,"
> + "impl-cpu.0.revidr=1,"
> + "impl-cpu.0.aidr=1,"
> + "impl-cpu.1.midr=2,"
> + "impl-cpu.1.revidr=2,"
> + "impl-cpu.1.aidr=2");
>
> }
>
> diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
> index c8e94e6aed..cf462fcb37 100644
> --- a/include/hw/arm/virt.h
> +++ b/include/hw/arm/virt.h
> @@ -180,6 +180,9 @@ struct VirtMachineState {
> char *oem_id;
> char *oem_table_id;
> bool ns_el2_virt_timer_irq;
> + uint64_t target_cpus_num;
> + ArmTargetImplCPU *target_cpus;
> + ArmTargetImplCPUList *target_cpus_list;
> };
>
> #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
Thanks
Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support
2025-08-01 7:47 ` [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support Shameer Kolothum
@ 2025-08-09 16:21 ` Eric Auger
0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2025-08-09 16:21 UTC (permalink / raw)
To: Shameer Kolothum, qemu-arm, qemu-devel
Cc: peter.maydell, cohuck, sebott, berrange, maz, oliver.upton,
armbru, linuxarm, wangzhou1, jiangkunkun, jonathan.cameron,
salil.mehta, yangjinqian1, shameerali.kolothum.thodi
Hi Shameer,
On 8/1/25 9:47 AM, Shameer Kolothum wrote:
> From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
>
> The helper function will try to set the SMCCC filters for KVM vendor
> hypercalls related to target implementation CPU support. It also
> checks the kernel support for writable implementation ID registers
> (MIDR/REVIDR/AIDR) and enables it.
>
> Subsequent patches for Target Impl CPU support will make use of this
> helper.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> target/arm/kvm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
> target/arm/kvm_arm.h | 12 ++++++++
> 2 files changed, 84 insertions(+)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 3f41f99e23..eb04640b50 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -2072,6 +2072,78 @@ bool kvm_arm_mte_supported(void)
> return kvm_check_extension(kvm_state, KVM_CAP_ARM_MTE);
> }
>
> +static bool kvm_arm_set_vm_attr(struct kvm_device_attr *attr, const char *name)
> +{
> + int err;
> +
> + err = kvm_vm_ioctl(kvm_state, KVM_HAS_DEVICE_ATTR, attr);
> + if (err != 0) {
> + error_report("%s: KVM_HAS_DEVICE_ATTR: %s", name, strerror(-err));
> + return false;
> + }
> +
> + err = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, attr);
> + if (err != 0) {
> + error_report("%s: KVM_SET_DEVICE_ATTR: %s", name, strerror(-err));
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool kvm_arm_set_smccc_filter(uint64_t func, uint8_t faction)
nit: base is _u32 in the kernel
> +{
> + struct kvm_smccc_filter filter = {
> + .base = func,
> + .nr_functions = 1,
> + .action = faction,
> + };
> + struct kvm_device_attr attr = {
> + .group = KVM_ARM_VM_SMCCC_CTRL,
> + .attr = KVM_ARM_VM_SMCCC_FILTER,
> + .flags = 0,
> + .addr = (uintptr_t)&filter,
> + };
> +
> + if (!kvm_arm_set_vm_attr(&attr, "SMCCC Filter")) {
> + error_report("failed to set SMCCC filter in KVM Host");
maybe also output @func in the error msg
> + return false;
> + }
> +
> + return true;
> +}
> +
> +bool kvm_arm_target_impl_cpus_supported(void)
> +{
> + if (!kvm_arm_set_smccc_filter(
> + ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID,
> + KVM_SMCCC_FILTER_FWD_TO_USER)) {
> + error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER fwd filter "
> + "install failed");
> + return false;
> + }
> +
> + if (!kvm_arm_set_smccc_filter(
> + ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID,
> + KVM_SMCCC_FILTER_FWD_TO_USER)) {
> + error_report("ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS fwd filter "
> + "install failed");
> + return false;
> + }
> +
> + if (!kvm_check_extension(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS)) {
> + error_report("KVM_CAP_ARM_WRITABLE_IMP_ID_REGS not supported");
> + return false;
> + }
> +
> + if (kvm_vm_enable_cap(kvm_state, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0)) {
> + error_report("Failed to enable KVM_CAP_ARM_WRITABLE_IMP_ID_REGS cap");
> + return false;
> + }
> +
> + return true;
> +}
> +
> QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
>
> uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
> diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
> index ba5de45f86..3cd6447901 100644
> --- a/target/arm/kvm_arm.h
> +++ b/target/arm/kvm_arm.h
> @@ -207,6 +207,13 @@ bool kvm_arm_sve_supported(void);
> */
> bool kvm_arm_mte_supported(void);
>
> +/**
> + * kvm_arm_target_impl_cpus_supported:
> + *
> + * Returns: true if KVM can enable target impl CPUs, and false otherwise.
> + */
> +bool kvm_arm_target_impl_cpus_supported(void);
> +
> /**
> * kvm_arm_get_max_vm_ipa_size:
> * @ms: Machine state handle
> @@ -263,6 +270,11 @@ static inline bool kvm_arm_mte_supported(void)
> return false;
> }
>
> +static inline bool kvm_arm_target_impl_cpus_supported(void)
> +{
> + return false;
> +}
> +
> static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
> {
> return -ENOSYS;
Otherwise looks good to me.
Thanks
Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU
2025-08-01 7:47 ` [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU Shameer Kolothum
@ 2025-08-09 16:23 ` Eric Auger
0 siblings, 0 replies; 10+ messages in thread
From: Eric Auger @ 2025-08-09 16:23 UTC (permalink / raw)
To: Shameer Kolothum, qemu-arm, qemu-devel
Cc: peter.maydell, cohuck, sebott, berrange, maz, oliver.upton,
armbru, linuxarm, wangzhou1, jiangkunkun, jonathan.cameron,
salil.mehta, yangjinqian1, shameerali.kolothum.thodi
Hi Shameer,
On 8/1/25 9:47 AM, Shameer Kolothum wrote:
> From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
>
> Introduce a QAPI‐defined struct (and its array) for target implementation
> CPUs. This enables specifying target implementation CPU parameters
> via -machine, for example:
>
> -M virt, \
> impl-cpu.0.midr=1,impl-cpu.0.revidr=1,impl-cpu.0.aidr=1, \
> impl-cpu.1.midr=2,impl-cpu.1.revidr=2,impl-cpu.1.aidr=0
>
> Subsequent patch will make use of this by using object_property_add(),
> allowing users to configure each target CPU’s midr, revidr, and aidr
> fields directly from the command line.
>
> While at it, also provide a helper function to set the target CPUs.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> qapi/machine.json | 34 ++++++++++++++++++++++++++++++++++
> target/arm/kvm.c | 16 ++++++++++++++++
> target/arm/kvm_arm.h | 8 ++++++++
> 3 files changed, 58 insertions(+)
>
> diff --git a/qapi/machine.json b/qapi/machine.json
> index a6b8795b09..d6e0e3b2e3 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -1898,3 +1898,37 @@
> { 'command': 'x-query-interrupt-controllers',
> 'returns': 'HumanReadableText',
> 'features': [ 'unstable' ]}
> +
> +##
> +# @ArmTargetImplCPU:
> +#
> +# Info for a single target implementation CPU.
> +#
> +# @midr: MIDR value
> +# @revidr: REVIDR value
> +# @aidr: AIDR value
> +#
> +# Since: 10.2
> +##
> +{ 'struct': 'ArmTargetImplCPU',
> + 'data': {
> + 'midr': 'uint64',
> + 'revidr': 'uint64',
> + 'aidr': 'uint64'
> + }
> +}
> +
> +##
> +# @ArmTargetImplCPUs:
> +#
> +# List of target implementation CPUs.
> +#
> +# @target-cpus: List of ArmTargetImplCPU entries.
> +#
> +# Since: 10.2
> +##
> +{ 'struct': 'ArmTargetImplCPUs',
> + 'data': {
> + 'target-cpus': ['ArmTargetImplCPU']
> + }
> +}
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index eb04640b50..8f325c4ca4 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -66,6 +66,9 @@ typedef struct ARMHostCPUFeatures {
>
> static ARMHostCPUFeatures arm_host_cpu_features;
>
> +static uint64_t target_impl_cpus_num;
> +static ArmTargetImplCPU *target_impl_cpus;
> +
> /**
> * kvm_arm_vcpu_init:
> * @cpu: ARMCPU
> @@ -2816,3 +2819,16 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
> cpu->kvm_mte = true;
> }
> }
> +
> +bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus)
> +{
> +
> + if (target_impl_cpus_num) {
> + return false;
> + }
> +
> + target_impl_cpus_num = num;
> + target_impl_cpus = cpus;
see my question on 4/4 wrt array.
Eric
> +
> + return true;
> +}
> diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
> index 3cd6447901..8754302333 100644
> --- a/target/arm/kvm_arm.h
> +++ b/target/arm/kvm_arm.h
> @@ -244,6 +244,8 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
>
> int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap);
>
> +bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus);
> +
> #else
>
> /*
> @@ -280,6 +282,12 @@ static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
> return -ENOSYS;
> }
>
> +static inline
> +bool kvm_arm_set_target_impl_cpus(uint64_t num, ArmTargetImplCPU *cpus)
> +{
> + return false;
> +}
> +
> /*
> * These functions should never actually be called without KVM support.
> */
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls
2025-08-01 7:47 ` [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls Shameer Kolothum
@ 2025-09-19 10:51 ` Sebastian Ott
0 siblings, 0 replies; 10+ messages in thread
From: Sebastian Ott @ 2025-09-19 10:51 UTC (permalink / raw)
To: Shameer Kolothum
Cc: qemu-arm, qemu-devel, eric.auger, peter.maydell, Cornelia Huck,
berrange, maz, oliver.upton, armbru, linuxarm, wangzhou1,
jiangkunkun, jonathan.cameron, salil.mehta, yangjinqian1,
shameerali.kolothum.thodi
On Fri, 1 Aug 2025, Shameer Kolothum wrote:
> From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
>
> When target implementation CPUs are set, handle the related hyper calls
> correctly by returning the information requested.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> target/arm/kvm.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 99 insertions(+)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 8f325c4ca4..5adecc864e 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -1697,6 +1697,71 @@ static bool kvm_arm_handle_debug(ARMCPU *cpu,
> return false;
> }
>
> +/* Only supports HYP_KVM_DISCOVER_IMPL_XXX hypercalls */
> +static void arm_handle_smccc_kvm_vendor_hypercall(ARMCPU *cpu)
> +{
> + CPUARMState *env = &cpu->env;
> + uint64_t param[4] = { };
> + uint64_t idx;
> +
> + if (!is_a64(env)) {
> + env->regs[0] = SMCCC_RET_NOT_SUPPORTED;
> + return;
> + }
> +
> + memcpy(param, env->xregs, sizeof(param));
> +
> + switch (param[0]) {
> + case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID:
> + if (!target_impl_cpus_num) {
> + env->xregs[0] = SMCCC_RET_NOT_SUPPORTED;
> + return;
> + }
> + env->xregs[0] = SMCCC_RET_SUCCESS;
> + env->xregs[1] = PSCI_VERSION(1, 0);
> + env->xregs[2] = target_impl_cpus_num;
> + break;
> + case ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID:
> + idx = param[1];
> +
> + if (!target_impl_cpus_num || idx >= target_impl_cpus_num) {
> + env->xregs[0] = SMCCC_RET_INVALID_PARAMETER;
> + return;
> + }
> +
> + env->xregs[0] = SMCCC_RET_SUCCESS;
> + env->xregs[1] = target_impl_cpus[idx].midr;
> + env->xregs[2] = target_impl_cpus[idx].revidr;
> + env->xregs[3] = target_impl_cpus[idx].aidr;
> + break;
> + default:
> + env->xregs[0] = SMCCC_RET_NOT_SUPPORTED;
> + }
> +}
> +
> +static int kvm_arm_handle_hypercall(CPUState *cs, struct kvm_run *run)
> +{
> + ARMCPU *cpu = ARM_CPU(cs);
> + CPUARMState *env = &cpu->env;
> +
> + kvm_cpu_synchronize_state(cs);
> +
> + if (run->hypercall.flags == KVM_HYPERCALL_EXIT_SMC) {
> + cs->exception_index = EXCP_SMC;
> + env->exception.syndrome = syn_aa64_smc(0);
> + } else {
> + cs->exception_index = EXCP_HVC;
> + env->exception.syndrome = syn_aa64_hvc(0);
> + }
> + env->exception.target_el = 1;
> +
> + bql_lock();
> + arm_handle_smccc_kvm_vendor_hypercall(cpu);
> + bql_unlock();
> +
> + return EXCP_INTERRUPT;
> +}
> +
> int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
> {
> ARMCPU *cpu = ARM_CPU(cs);
> @@ -1713,6 +1778,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
> ret = kvm_arm_handle_dabt_nisv(cpu, run->arm_nisv.esr_iss,
> run->arm_nisv.fault_ipa);
> break;
> + case KVM_EXIT_HYPERCALL:
> + ret = kvm_arm_handle_hypercall(cs, run);
> + break;
> default:
> qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
> __func__, run->exit_reason);
> @@ -2212,6 +2280,29 @@ static int kvm_arm_sve_set_vls(ARMCPU *cpu)
> return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM64_SVE_VLS, &vls[0]);
> }
>
> +/*
> + * Supported Target Implementation CPU hypercalls:
> + * KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER = 0,
> + * KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS = 1
> + *
> + * Setting these bits advertises the availability of the corresponding
> + * Target Implementation CPU hypercalls to the guest.
> + */
> +#define BMAP_2_DISCOVER_IMPL_BITS 0x3ULL
> +static int kvm_arm_target_impl_cpus_set_hyp_bmap2(ARMCPU *cpu)
> +{
> + uint64_t bmap2;
> + int ret;
> +
> + ret = kvm_get_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap2);
> + if (ret) {
> + return ret;
> + }
> +
> + bmap2 |= BMAP_2_DISCOVER_IMPL_BITS;
> + return kvm_set_one_reg(CPU(cpu), KVM_REG_ARM_VENDOR_HYP_BMAP_2, &bmap2);
> +}
> +
> #define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5
>
> int kvm_arch_init_vcpu(CPUState *cs)
> @@ -2293,6 +2384,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
> }
> cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
>
> + /* Set KVM_REG_ARM_VENDOR_HYP_BMAP_2 if target impl CPUs are required */
> + if (target_impl_cpus_num) {
> + ret = kvm_arm_target_impl_cpus_set_hyp_bmap2(cpu);
There's still the question of what we use to actually set the
imp id regs for the vm. I'm in favour of using target_impl_cpus[0].*
but if these can also be specified via the writable id regs interface
(https://lore.kernel.org/qemu-devel/20250414163849.321857-1-cohuck@redhat.com/)
we need to make sure that they match.
Otherwise, looks good to me!
Sebastian
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-09-19 10:52 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-01 7:47 [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Shameer Kolothum
2025-08-01 7:47 ` [RFC PATCH RESEND 1/4] target/arm/kvm: Introduce helper to check target impl CPU support Shameer Kolothum
2025-08-09 16:21 ` Eric Auger
2025-08-01 7:47 ` [RFC PATCH RESEND 2/4] target/arm/kvm: Add QAPI struct ArmTargetImplCPU Shameer Kolothum
2025-08-09 16:23 ` Eric Auger
2025-08-01 7:47 ` [RFC PATCH RESEND 3/4] target/arm/kvm: Handle KVM Target Imp CPU hypercalls Shameer Kolothum
2025-09-19 10:51 ` Sebastian Ott
2025-08-01 7:47 ` [RFC PATCH RESEND 4/4] hw/arm/virt: Add Target Implementation CPU support Shameer Kolothum
2025-08-09 16:21 ` Eric Auger
2025-08-01 8:31 ` [RFC PATCH RESEND 0/4] hw/arm/virt: Add support for Target Implementation CPUs Cornelia Huck
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).