* [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration
@ 2025-02-21 14:02 Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally Shameer Kolothum
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
Hi,
v7-->v8
https://lore.kernel.org/kvmarm/20250214151343.61348-1-shameerali.kolothum.thodi@huawei.com/
Changes:
-Fixed the compile error issue due to CONFIG_CORESIGHT_SOURCE_ETM4X=m
(Thanks to Sebastian for checking that config)- patch #4
-Added R-by tags.
This can be sanity tested by the Qemu branch here,
https://github.com/hisilicon/qemu/tree/v9.0-nv-rfcv4-vcpu-model-v2-target-cpu-errata
(branch based on Eric's/Connie's NV + custom CPU series)
Eg: to specify target impl CPUs,
-machine virt,.., x-target-impl-cpus=0xMIDR1:0xREVIDR1-0xMIDR2:REVIDR2
Please take a look and let me know your feedback.
Thanks,
Shameer
v6-->v7
https://lore.kernel.org/kvmarm/20250205132222.55816-1-shameerali.kolothum.thodi@huawei.com/
Changes:
-Introduced KVM_REG_ARM_VENDOR_HYP_BMAP_2 register for new hypercall
support(patch #3)
-Added selftest for KVM_REG_ARM_VENDOR_HYP_BMAP_2(patch #5).
v5 --> v6
https://lore.kernel.org/kvmarm/20250124151732.6072-1-shameerali.kolothum.thodi@huawei.com/
-Addressed comments from Oliver,
-Changed version to 32 bit to match SMCCC_VERSION
-Don't advertise pKVM hypercalls to guests.
-Moved hypercall invocation to kvm_guest.c
v4 --> v5
https://lore.kernel.org/kvmarm/20241218105345.73472-1-shameerali.kolothum.thodi@huawei.com/
-Addressed comments from Marc,
-Added an hypercall to retrieve version and number of supported target
impl CPUs.
-Added a check for KVM hypercall services availability.
-Removed R-by tags from Connie & Sebastian as patches 2 & 4 are now
changed a bit. Please take another look.
v3 --> v4(Minor updates)
https://lore.kernel.org/kvmarm/20241209115311.40496-1-shameerali.kolothum.thodi@huawei.com/
-Changed MIDR/REVIDR to 64 bits based on feedback from Connie
and Marc(Patch #3).
-Added R-by tags from Sebastian (Thanks!).
RFC v2 --> v3
https://lore.kernel.org/kvmarm/20241024094012.29452-1-shameerali.kolothum.thodi@huawei.com/
-Addressed comments from Oliver(Thanks!).
-Using implementation CPUs MIDR/REVIDR when it is set for
_midr_range() functions(Patch 1 & 3)
-New hypercall for retrieving implementation CPUs(Patch #2).
-Dropped RFC.
RFC v1 --> RFCv2:
https://lore.kernel.org/kvmarm/20241011075053.80540-1-shameerali.kolothum.thodi@huawei.com/
-Introduced hypercalls to retrieve target CPUs info from user space VMM.
see patch #1 for details.
-Patch #2 uses the hypercall to retrieve the target CPU info if any.
-Use the target CPUs MIDR/REVIDR in errata enablement. See patch #3.
Background from v1:
On ARM64 platforms most of the errata workarounds are based on CPU
MIDR/REVIDR values and a number of these workarounds need to be
implemented by the Guest kernel as well. This creates a problem when
Guest needs to be migrated to a platform that differs in these
MIDR/REVIDR values even if the VMM can come up with a common minimum
feature list for the Guest using the recently introduced "Writable
ID registers" support.
(This is roughly based on a discussion I had with Marc and Oliver
at KVM forum. Marc outlined his idea for a solution and this is an
attempt to implement it. Thanks to both and I take all the blame
if this is nowhere near what is intended/required)
Shameer Kolothum (6):
arm64: Modify _midr_range() functions to read MIDR/REVIDR internally
KVM: arm64: Introduce hypercall support for retrieving target
implementations
KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2
arm64: Make _midr_in_range_list() an exported function
smccc/kvm_guest: Enable errata based on implementation CPUs
KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2
.../virt/kvm/arm/fw-pseudo-registers.rst | 15 +++-
Documentation/virt/kvm/arm/hypercalls.rst | 59 +++++++++++++++
arch/arm64/include/asm/cputype.h | 40 +++++-----
arch/arm64/include/asm/hypervisor.h | 1 +
arch/arm64/include/asm/kvm_host.h | 3 +-
arch/arm64/include/asm/mmu.h | 3 +-
arch/arm64/include/uapi/asm/kvm.h | 12 +++
arch/arm64/kernel/cpu_errata.c | 73 ++++++++++++++++---
arch/arm64/kernel/cpufeature.c | 8 +-
arch/arm64/kernel/image-vars.h | 1 +
arch/arm64/kernel/proton-pack.c | 17 ++---
arch/arm64/kvm/hypercalls.c | 13 ++++
arch/arm64/kvm/vgic/vgic-v3.c | 2 +-
drivers/clocksource/arm_arch_timer.c | 2 +-
drivers/firmware/smccc/kvm_guest.c | 64 ++++++++++++++++
.../coresight/coresight-etm4x-core.c | 2 +-
include/linux/arm-smccc.h | 15 ++++
tools/arch/arm64/include/uapi/asm/kvm.h | 12 +++
.../selftests/kvm/arm64/get-reg-list.c | 1 +
.../testing/selftests/kvm/arm64/hypercalls.c | 46 +++++++++---
20 files changed, 327 insertions(+), 62 deletions(-)
--
2.47.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-02-26 19:39 ` Catalin Marinas
2025-02-21 14:02 ` [PATCH v8 2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations Shameer Kolothum
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
These changes lay the groundwork for adding support for guest kernels,
allowing them to leverage target CPU implementations provided by the
VMM.
No functional changes intended.
Suggested-by: Oliver Upton <oliver.upton@linux.dev>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
arch/arm64/include/asm/cputype.h | 28 +++++++++----------
arch/arm64/include/asm/mmu.h | 3 +-
arch/arm64/kernel/cpu_errata.c | 23 ++++++++-------
arch/arm64/kernel/cpufeature.c | 6 ++--
arch/arm64/kernel/proton-pack.c | 17 ++++++-----
arch/arm64/kvm/vgic/vgic-v3.c | 2 +-
drivers/clocksource/arm_arch_timer.c | 2 +-
.../coresight/coresight-etm4x-core.c | 2 +-
8 files changed, 42 insertions(+), 41 deletions(-)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 6f3f4142e214..2a76f0e30006 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -231,6 +231,16 @@
#define read_cpuid(reg) read_sysreg_s(SYS_ ## reg)
+/*
+ * The CPU ID never changes at run time, so we might as well tell the
+ * compiler that it's constant. Use this function to read the CPU ID
+ * rather than directly reading processor_id or read_cpuid() directly.
+ */
+static inline u32 __attribute_const__ read_cpuid_id(void)
+{
+ return read_cpuid(MIDR_EL1);
+}
+
/*
* Represent a range of MIDR values for a given CPU model and a
* range of variant/revision values.
@@ -266,31 +276,21 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
return _model == model && rv >= rv_min && rv <= rv_max;
}
-static inline bool is_midr_in_range(u32 midr, struct midr_range const *range)
+static inline bool is_midr_in_range(struct midr_range const *range)
{
- return midr_is_cpu_model_range(midr, range->model,
+ return midr_is_cpu_model_range(read_cpuid_id(), range->model,
range->rv_min, range->rv_max);
}
static inline bool
-is_midr_in_range_list(u32 midr, struct midr_range const *ranges)
+is_midr_in_range_list(struct midr_range const *ranges)
{
while (ranges->model)
- if (is_midr_in_range(midr, ranges++))
+ if (is_midr_in_range(ranges++))
return true;
return false;
}
-/*
- * The CPU ID never changes at run time, so we might as well tell the
- * compiler that it's constant. Use this function to read the CPU ID
- * rather than directly reading processor_id or read_cpuid() directly.
- */
-static inline u32 __attribute_const__ read_cpuid_id(void)
-{
- return read_cpuid(MIDR_EL1);
-}
-
static inline u64 __attribute_const__ read_cpuid_mpidr(void)
{
return read_cpuid(MPIDR_EL1);
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 662471cfc536..30a29e88994b 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -101,8 +101,7 @@ static inline bool kaslr_requires_kpti(void)
if (IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) {
extern const struct midr_range cavium_erratum_27456_cpus[];
- if (is_midr_in_range_list(read_cpuid_id(),
- cavium_erratum_27456_cpus))
+ if (is_midr_in_range_list(cavium_erratum_27456_cpus))
return false;
}
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 7ce555862895..99b55893fc4e 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -15,30 +15,34 @@
#include <asm/smp_plat.h>
static bool __maybe_unused
-is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
+__is_affected_midr_range(const struct arm64_cpu_capabilities *entry,
+ u32 midr, u32 revidr)
{
const struct arm64_midr_revidr *fix;
- u32 midr = read_cpuid_id(), revidr;
-
- WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
- if (!is_midr_in_range(midr, &entry->midr_range))
+ if (!is_midr_in_range(&entry->midr_range))
return false;
midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
- revidr = read_cpuid(REVIDR_EL1);
for (fix = entry->fixed_revs; fix && fix->revidr_mask; fix++)
if (midr == fix->midr_rv && (revidr & fix->revidr_mask))
return false;
-
return true;
}
+static bool __maybe_unused
+is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+ return __is_affected_midr_range(entry, read_cpuid_id(),
+ read_cpuid(REVIDR_EL1));
+}
+
static bool __maybe_unused
is_affected_midr_range_list(const struct arm64_cpu_capabilities *entry,
int scope)
{
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
- return is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list);
+ return is_midr_in_range_list(entry->midr_range_list);
}
static bool __maybe_unused
@@ -186,12 +190,11 @@ static bool __maybe_unused
has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
int scope)
{
- u32 midr = read_cpuid_id();
bool has_dic = read_cpuid_cachetype() & BIT(CTR_EL0_DIC_SHIFT);
const struct midr_range range = MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1);
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
- return is_midr_in_range(midr, &range) && has_dic;
+ return is_midr_in_range(&range) && has_dic;
}
#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 4eb7c6698ae4..72e876f37cd4 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1792,7 +1792,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
char const *str = "kpti command line option";
bool meltdown_safe;
- meltdown_safe = is_midr_in_range_list(read_cpuid_id(), kpti_safe_list);
+ meltdown_safe = is_midr_in_range_list(kpti_safe_list);
/* Defer to CPU feature registers */
if (has_cpuid_feature(entry, scope))
@@ -1862,7 +1862,7 @@ static bool has_nv1(const struct arm64_cpu_capabilities *entry, int scope)
return (__system_matches_cap(ARM64_HAS_NESTED_VIRT) &&
!(has_cpuid_feature(entry, scope) ||
- is_midr_in_range_list(read_cpuid_id(), nv1_ni_list)));
+ is_midr_in_range_list(nv1_ni_list)));
}
#if defined(ID_AA64MMFR0_EL1_TGRAN_LPA2) && defined(ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2)
@@ -2045,7 +2045,7 @@ static bool cpu_has_broken_dbm(void)
{},
};
- return is_midr_in_range_list(read_cpuid_id(), cpus);
+ return is_midr_in_range_list(cpus);
}
static bool cpu_can_use_dbm(const struct arm64_cpu_capabilities *cap)
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
index da53722f95d4..a573fa40d4b6 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -172,7 +172,7 @@ static enum mitigation_state spectre_v2_get_cpu_hw_mitigation_state(void)
return SPECTRE_UNAFFECTED;
/* Alternatively, we have a list of unaffected CPUs */
- if (is_midr_in_range_list(read_cpuid_id(), spectre_v2_safe_list))
+ if (is_midr_in_range_list(spectre_v2_safe_list))
return SPECTRE_UNAFFECTED;
return SPECTRE_VULNERABLE;
@@ -331,7 +331,7 @@ bool has_spectre_v3a(const struct arm64_cpu_capabilities *entry, int scope)
};
WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
- return is_midr_in_range_list(read_cpuid_id(), spectre_v3a_unsafe_list);
+ return is_midr_in_range_list(spectre_v3a_unsafe_list);
}
void spectre_v3a_enable_mitigation(const struct arm64_cpu_capabilities *__unused)
@@ -475,7 +475,7 @@ static enum mitigation_state spectre_v4_get_cpu_hw_mitigation_state(void)
{ /* sentinel */ },
};
- if (is_midr_in_range_list(read_cpuid_id(), spectre_v4_safe_list))
+ if (is_midr_in_range_list(spectre_v4_safe_list))
return SPECTRE_UNAFFECTED;
/* CPU features are detected first */
@@ -878,13 +878,13 @@ u8 spectre_bhb_loop_affected(int scope)
{},
};
- if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list))
+ if (is_midr_in_range_list(spectre_bhb_k32_list))
k = 32;
- else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list))
+ else if (is_midr_in_range_list(spectre_bhb_k24_list))
k = 24;
- else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list))
+ else if (is_midr_in_range_list(spectre_bhb_k11_list))
k = 11;
- else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list))
+ else if (is_midr_in_range_list(spectre_bhb_k8_list))
k = 8;
max_bhb_k = max(max_bhb_k, k);
@@ -926,8 +926,7 @@ static bool is_spectre_bhb_fw_affected(int scope)
MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
{},
};
- bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(),
- spectre_bhb_firmware_mitigated_list);
+ bool cpu_in_list = is_midr_in_range_list(spectre_bhb_firmware_mitigated_list);
if (scope != SCOPE_LOCAL_CPU)
return system_affected;
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index d7233ab982d0..87a8a96c7a41 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -633,7 +633,7 @@ static const struct midr_range broken_seis[] = {
static bool vgic_v3_broken_seis(void)
{
return ((kvm_vgic_global_state.ich_vtr_el2 & ICH_VTR_SEIS_MASK) &&
- is_midr_in_range_list(read_cpuid_id(), broken_seis));
+ is_midr_in_range_list(broken_seis));
}
/**
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 808f259781fd..981a578043a5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -842,7 +842,7 @@ static u64 __arch_timer_check_delta(void)
{},
};
- if (is_midr_in_range_list(read_cpuid_id(), broken_cval_midrs)) {
+ if (is_midr_in_range_list(broken_cval_midrs)) {
pr_warn_once("Broken CNTx_CVAL_EL1, using 31 bit TVAL instead.\n");
return CLOCKSOURCE_MASK(31);
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2c1a60577728..3d98e3371fff 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1216,7 +1216,7 @@ static void etm4_fixup_wrong_ccitmin(struct etmv4_drvdata *drvdata)
* recorded value for 'drvdata->ccitmin' to workaround
* this problem.
*/
- if (is_midr_in_range_list(read_cpuid_id(), etm_wrong_ccitmin_cpus)) {
+ if (is_midr_in_range_list(etm_wrong_ccitmin_cpus)) {
if (drvdata->ccitmin == 256)
drvdata->ccitmin = 4;
}
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v8 2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
If the Guest requires migration to multiple targets, these hypercalls
will provide a way to retrieve the target CPU implementations from
the user space VMM.
Subsequent patch will use this to enable the associated errata.
Suggested-by: Oliver Upton <oliver.upton@linux.dev>
Suggested-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
Documentation/virt/kvm/arm/hypercalls.rst | 59 +++++++++++++++++++++++
include/linux/arm-smccc.h | 15 ++++++
2 files changed, 74 insertions(+)
diff --git a/Documentation/virt/kvm/arm/hypercalls.rst b/Documentation/virt/kvm/arm/hypercalls.rst
index af7bc2c2e0cb..7400a89aabf8 100644
--- a/Documentation/virt/kvm/arm/hypercalls.rst
+++ b/Documentation/virt/kvm/arm/hypercalls.rst
@@ -142,3 +142,62 @@ region is equal to the memory protection granule advertised by
| | | +---------------------------------------------+
| | | | ``INVALID_PARAMETER (-3)`` |
+---------------------+----------+----+---------------------------------------------+
+
+``ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID``
+-------------------------------------------------------
+Request the target CPU implementation version information and the number of target
+implementations for the Guest VM.
+
++---------------------+-------------------------------------------------------------+
+| Presence: | Optional; KVM/ARM64 Guests only |
++---------------------+-------------------------------------------------------------+
+| Calling convention: | HVC64 |
++---------------------+----------+--------------------------------------------------+
+| Function ID: | (uint32) | 0xC6000040 |
++---------------------+----------+--------------------------------------------------+
+| Arguments: | None |
++---------------------+----------+----+---------------------------------------------+
+| Return Values: | (int64) | R0 | ``SUCCESS (0)`` |
+| | | +---------------------------------------------+
+| | | | ``NOT_SUPPORTED (-1)`` |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R1 | Bits [63:32] Reserved/Must be zero |
+| | | +---------------------------------------------+
+| | | | Bits [31:16] Major version |
+| | | +---------------------------------------------+
+| | | | Bits [15:0] Minor version |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R2 | Number of target implementations |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R3 | Reserved / Must be zero |
++---------------------+----------+----+---------------------------------------------+
+
+``ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID``
+-------------------------------------------------------
+
+Request the target CPU implementation information for the Guest VM. The Guest kernel
+will use this information to enable the associated errata.
+
++---------------------+-------------------------------------------------------------+
+| Presence: | Optional; KVM/ARM64 Guests only |
++---------------------+-------------------------------------------------------------+
+| Calling convention: | HVC64 |
++---------------------+----------+--------------------------------------------------+
+| Function ID: | (uint32) | 0xC6000041 |
++---------------------+----------+----+---------------------------------------------+
+| Arguments: | (uint64) | R1 | selected implementation index |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R2 | Reserved / Must be zero |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R3 | Reserved / Must be zero |
++---------------------+----------+----+---------------------------------------------+
+| Return Values: | (int64) | R0 | ``SUCCESS (0)`` |
+| | | +---------------------------------------------+
+| | | | ``INVALID_PARAMETER (-3)`` |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R1 | MIDR_EL1 of the selected implementation |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R2 | REVIDR_EL1 of the selected implementation |
+| +----------+----+---------------------------------------------+
+| | (uint64) | R3 | AIDR_EL1 of the selected implementation |
++---------------------+----------+----+---------------------------------------------+
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 67f6fdf2e7cd..f19be5754090 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -179,6 +179,9 @@
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_62 62
#define ARM_SMCCC_KVM_FUNC_PKVM_RESV_63 63
/* End of pKVM hypercall range */
+#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER 64
+#define ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS 65
+
#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127
#define ARM_SMCCC_KVM_NUM_FUNCS 128
@@ -225,6 +228,18 @@
ARM_SMCCC_OWNER_VENDOR_HYP, \
ARM_SMCCC_KVM_FUNC_MMIO_GUARD)
+#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER)
+
+#define ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS)
+
/* ptp_kvm counter type ID */
#define KVM_PTP_VIRT_COUNTER 0
#define KVM_PTP_PHYS_COUNTER 1
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v8 3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function Shameer Kolothum
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
The vendor_hyp_bmap bitmap holds the information about the Vendor Hyp
services available to the user space and can be get/set using
{G, S}ET_ONE_REG interfaces. This is done using the pseudo-firmware
bitmap register KVM_REG_ARM_VENDOR_HYP_BMAP.
At present, this bitmap is a 64 bit one and since the function numbers
for newly added DISCOVER_IPML_* hypercalls are 64-65, introduce
another pseudo-firmware bitmap register KVM_REG_ARM_VENDOR_HYP_BMAP_2.
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
.../virt/kvm/arm/fw-pseudo-registers.rst | 15 ++++++++++++++-
arch/arm64/include/asm/kvm_host.h | 3 ++-
arch/arm64/include/uapi/asm/kvm.h | 12 ++++++++++++
arch/arm64/kvm/hypercalls.c | 13 +++++++++++++
4 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/Documentation/virt/kvm/arm/fw-pseudo-registers.rst b/Documentation/virt/kvm/arm/fw-pseudo-registers.rst
index b90fd0b0fa66..d78b53b05dfc 100644
--- a/Documentation/virt/kvm/arm/fw-pseudo-registers.rst
+++ b/Documentation/virt/kvm/arm/fw-pseudo-registers.rst
@@ -116,7 +116,7 @@ The pseudo-firmware bitmap register are as follows:
ARM DEN0057A.
* KVM_REG_ARM_VENDOR_HYP_BMAP:
- Controls the bitmap of the Vendor specific Hypervisor Service Calls.
+ Controls the bitmap of the Vendor specific Hypervisor Service Calls[0-63].
The following bits are accepted:
@@ -127,6 +127,19 @@ The pseudo-firmware bitmap register are as follows:
Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_PTP:
The bit represents the Precision Time Protocol KVM service.
+* KVM_REG_ARM_VENDOR_HYP_BMAP_2:
+ Controls the bitmap of the Vendor specific Hypervisor Service Calls[64-127].
+
+ The following bits are accepted:
+
+ Bit-0: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER
+ This represents the ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID
+ function-id. This is reset to 0.
+
+ Bit-1: KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS
+ This represents the ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID
+ function-id. This is reset to 0.
+
Errors:
======= =============================================================
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 7cfa024de4e3..4cea172ebaaa 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -237,7 +237,8 @@ struct kvm_arch_memory_slot {
struct kvm_smccc_features {
unsigned long std_bmap;
unsigned long std_hyp_bmap;
- unsigned long vendor_hyp_bmap;
+ unsigned long vendor_hyp_bmap; /* Function numbers 0-63 */
+ unsigned long vendor_hyp_bmap_2; /* Function numbers 64-127 */
};
typedef unsigned int pkvm_handle_t;
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 568bf858f319..072feeff74d0 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -371,6 +371,7 @@ enum {
#endif
};
+/* Vendor hyper call function numbers 0-63 */
#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2)
enum {
@@ -381,6 +382,17 @@ enum {
#endif
};
+/* Vendor hyper call function numbers 64-127 */
+#define KVM_REG_ARM_VENDOR_HYP_BMAP_2 KVM_REG_ARM_FW_FEAT_BMAP_REG(3)
+
+enum {
+ KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER = 0,
+ KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS = 1,
+#ifdef __KERNEL__
+ KVM_REG_ARM_VENDOR_HYP_BMAP_2_BIT_COUNT,
+#endif
+};
+
/* Device Control API on vm fd */
#define KVM_ARM_VM_SMCCC_CTRL 0
#define KVM_ARM_VM_SMCCC_FILTER 0
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 27ce4cb44904..569941eeb3fe 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -15,6 +15,8 @@
GENMASK(KVM_REG_ARM_STD_HYP_BMAP_BIT_COUNT - 1, 0)
#define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES \
GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_COUNT - 1, 0)
+#define KVM_ARM_SMCCC_VENDOR_HYP_FEATURES_2 \
+ GENMASK(KVM_REG_ARM_VENDOR_HYP_BMAP_2_BIT_COUNT - 1, 0)
static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
{
@@ -360,6 +362,8 @@ 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;
+ /* Function numbers 2-63 are reserved for pKVM for now */
+ val[2] = smccc_feat->vendor_hyp_bmap_2;
break;
case ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID:
kvm_ptp_get_time(vcpu, val);
@@ -387,6 +391,7 @@ static const u64 kvm_arm_fw_reg_ids[] = {
KVM_REG_ARM_STD_BMAP,
KVM_REG_ARM_STD_HYP_BMAP,
KVM_REG_ARM_VENDOR_HYP_BMAP,
+ KVM_REG_ARM_VENDOR_HYP_BMAP_2,
};
void kvm_arm_init_hypercalls(struct kvm *kvm)
@@ -497,6 +502,9 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_REG_ARM_VENDOR_HYP_BMAP:
val = READ_ONCE(smccc_feat->vendor_hyp_bmap);
break;
+ case KVM_REG_ARM_VENDOR_HYP_BMAP_2:
+ val = READ_ONCE(smccc_feat->vendor_hyp_bmap_2);
+ break;
default:
return -ENOENT;
}
@@ -527,6 +535,10 @@ static int kvm_arm_set_fw_reg_bmap(struct kvm_vcpu *vcpu, u64 reg_id, u64 val)
fw_reg_bmap = &smccc_feat->vendor_hyp_bmap;
fw_reg_features = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
break;
+ case KVM_REG_ARM_VENDOR_HYP_BMAP_2:
+ fw_reg_bmap = &smccc_feat->vendor_hyp_bmap_2;
+ fw_reg_features = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES_2;
+ break;
default:
return -ENOENT;
}
@@ -633,6 +645,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_REG_ARM_STD_BMAP:
case KVM_REG_ARM_STD_HYP_BMAP:
case KVM_REG_ARM_VENDOR_HYP_BMAP:
+ case KVM_REG_ARM_VENDOR_HYP_BMAP_2:
return kvm_arm_set_fw_reg_bmap(vcpu, reg->id, val);
default:
return -ENOENT;
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
` (2 preceding siblings ...)
2025-02-21 14:02 ` [PATCH v8 3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-02-26 19:40 ` Catalin Marinas
2025-04-15 10:57 ` [BUG][PATCH " Ada Couprie Diaz
2025-02-21 14:02 ` [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs Shameer Kolothum
` (2 subsequent siblings)
6 siblings, 2 replies; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
Subsequent patch will add target implementation CPU support and that
will require _midr_in_range_list() to access new data. To avoid
exporting the data make _midr_in_range_list() a normal function and
export it.
No functional changes intended.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
arch/arm64/include/asm/cputype.h | 15 +--------------
arch/arm64/kernel/cpu_errata.c | 15 +++++++++++++++
arch/arm64/kernel/image-vars.h | 1 +
3 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 2a76f0e30006..ccb4a155d118 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -276,20 +276,7 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
return _model == model && rv >= rv_min && rv <= rv_max;
}
-static inline bool is_midr_in_range(struct midr_range const *range)
-{
- return midr_is_cpu_model_range(read_cpuid_id(), range->model,
- range->rv_min, range->rv_max);
-}
-
-static inline bool
-is_midr_in_range_list(struct midr_range const *ranges)
-{
- while (ranges->model)
- if (is_midr_in_range(ranges++))
- return true;
- return false;
-}
+bool is_midr_in_range_list(struct midr_range const *ranges);
static inline u64 __attribute_const__ read_cpuid_mpidr(void)
{
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 99b55893fc4e..1f51cf6378c5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -14,6 +14,21 @@
#include <asm/kvm_asm.h>
#include <asm/smp_plat.h>
+static inline bool is_midr_in_range(struct midr_range const *range)
+{
+ return midr_is_cpu_model_range(read_cpuid_id(), range->model,
+ range->rv_min, range->rv_max);
+}
+
+bool is_midr_in_range_list(struct midr_range const *ranges)
+{
+ while (ranges->model)
+ if (is_midr_in_range(ranges++))
+ return true;
+ return false;
+}
+EXPORT_SYMBOL_GPL(is_midr_in_range_list);
+
static bool __maybe_unused
__is_affected_midr_range(const struct arm64_cpu_capabilities *entry,
u32 midr, u32 revidr)
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index ef3a69cc398e..de3d081e5a57 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -49,6 +49,7 @@ PROVIDE(__pi_arm64_sw_feature_override = arm64_sw_feature_override);
PROVIDE(__pi_arm64_use_ng_mappings = arm64_use_ng_mappings);
#ifdef CONFIG_CAVIUM_ERRATUM_27456
PROVIDE(__pi_cavium_erratum_27456_cpus = cavium_erratum_27456_cpus);
+PROVIDE(__pi_is_midr_in_range_list = is_midr_in_range_list);
#endif
PROVIDE(__pi__ctype = _ctype);
PROVIDE(__pi_memstart_offset_seed = memstart_offset_seed);
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
` (3 preceding siblings ...)
2025-02-21 14:02 ` [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-02-26 19:41 ` Catalin Marinas
2025-02-21 14:02 ` [PATCH v8 6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
2025-03-05 23:58 ` [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Oliver Upton
6 siblings, 1 reply; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
Retrieve any migration target implementation CPUs using the hypercall
and enable associated errata.
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
arch/arm64/include/asm/cputype.h | 7 ++++
arch/arm64/include/asm/hypervisor.h | 1 +
arch/arm64/kernel/cpu_errata.c | 45 +++++++++++++++++---
arch/arm64/kernel/cpufeature.c | 2 +
drivers/firmware/smccc/kvm_guest.c | 64 +++++++++++++++++++++++++++++
5 files changed, 114 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index ccb4a155d118..cc2d58141be1 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -276,6 +276,13 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
return _model == model && rv >= rv_min && rv <= rv_max;
}
+struct target_impl_cpu {
+ u64 midr;
+ u64 revidr;
+ u64 aidr;
+};
+
+bool cpu_errata_set_target_impl(u64 num, void *impl_cpus);
bool is_midr_in_range_list(struct midr_range const *ranges);
static inline u64 __attribute_const__ read_cpuid_mpidr(void)
diff --git a/arch/arm64/include/asm/hypervisor.h b/arch/arm64/include/asm/hypervisor.h
index 409e239834d1..a12fd897c877 100644
--- a/arch/arm64/include/asm/hypervisor.h
+++ b/arch/arm64/include/asm/hypervisor.h
@@ -6,6 +6,7 @@
void kvm_init_hyp_services(void);
bool kvm_arm_hyp_service_available(u32 func_id);
+void kvm_arm_target_impl_cpu_init(void);
#ifdef CONFIG_ARM_PKVM_GUEST
void pkvm_init_hyp_services(void);
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 1f51cf6378c5..66869d81c3d5 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -14,10 +14,34 @@
#include <asm/kvm_asm.h>
#include <asm/smp_plat.h>
+static u64 target_impl_cpu_num;
+static struct target_impl_cpu *target_impl_cpus;
+
+bool cpu_errata_set_target_impl(u64 num, void *impl_cpus)
+{
+ if (target_impl_cpu_num || !num || !impl_cpus)
+ return false;
+
+ target_impl_cpu_num = num;
+ target_impl_cpus = impl_cpus;
+ return true;
+}
+
static inline bool is_midr_in_range(struct midr_range const *range)
{
- return midr_is_cpu_model_range(read_cpuid_id(), range->model,
- range->rv_min, range->rv_max);
+ int i;
+
+ if (!target_impl_cpu_num)
+ return midr_is_cpu_model_range(read_cpuid_id(), range->model,
+ range->rv_min, range->rv_max);
+
+ for (i = 0; i < target_impl_cpu_num; i++) {
+ if (midr_is_cpu_model_range(target_impl_cpus[i].midr,
+ range->model,
+ range->rv_min, range->rv_max))
+ return true;
+ }
+ return false;
}
bool is_midr_in_range_list(struct midr_range const *ranges)
@@ -47,9 +71,20 @@ __is_affected_midr_range(const struct arm64_cpu_capabilities *entry,
static bool __maybe_unused
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
{
- WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
- return __is_affected_midr_range(entry, read_cpuid_id(),
- read_cpuid(REVIDR_EL1));
+ int i;
+
+ if (!target_impl_cpu_num) {
+ WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+ return __is_affected_midr_range(entry, read_cpuid_id(),
+ read_cpuid(REVIDR_EL1));
+ }
+
+ for (i = 0; i < target_impl_cpu_num; i++) {
+ if (__is_affected_midr_range(entry, target_impl_cpus[i].midr,
+ target_impl_cpus[i].midr))
+ return true;
+ }
+ return false;
}
static bool __maybe_unused
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 72e876f37cd4..5c61d9d9f097 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -86,6 +86,7 @@
#include <asm/kvm_host.h>
#include <asm/mmu_context.h>
#include <asm/mte.h>
+#include <asm/hypervisor.h>
#include <asm/processor.h>
#include <asm/smp.h>
#include <asm/sysreg.h>
@@ -3679,6 +3680,7 @@ unsigned long cpu_get_elf_hwcap3(void)
static void __init setup_boot_cpu_capabilities(void)
{
+ kvm_arm_target_impl_cpu_init();
/*
* The boot CPU's feature register values have been recorded. Detect
* boot cpucaps and local cpucaps for the boot CPU, then enable and
diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
index f3319be20b36..2f03b582c298 100644
--- a/drivers/firmware/smccc/kvm_guest.c
+++ b/drivers/firmware/smccc/kvm_guest.c
@@ -6,8 +6,11 @@
#include <linux/bitmap.h>
#include <linux/cache.h>
#include <linux/kernel.h>
+#include <linux/memblock.h>
#include <linux/string.h>
+#include <uapi/linux/psci.h>
+
#include <asm/hypervisor.h>
static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_after_init = { };
@@ -51,3 +54,64 @@ bool kvm_arm_hyp_service_available(u32 func_id)
return test_bit(func_id, __kvm_arm_hyp_services);
}
EXPORT_SYMBOL_GPL(kvm_arm_hyp_service_available);
+
+void __init kvm_arm_target_impl_cpu_init(void)
+{
+ int i;
+ u32 ver;
+ u64 max_cpus;
+ struct arm_smccc_res res;
+ struct target_impl_cpu *target;
+
+ if (!kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_VER) ||
+ !kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_DISCOVER_IMPL_CPUS))
+ return;
+
+ arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_VER_FUNC_ID,
+ 0, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS)
+ return;
+
+ /* Version info is in lower 32 bits and is in SMMCCC_VERSION format */
+ ver = lower_32_bits(res.a1);
+ if (PSCI_VERSION_MAJOR(ver) != 1) {
+ pr_warn("Unsupported target CPU implementation version v%d.%d\n",
+ PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver));
+ return;
+ }
+
+ if (!res.a2) {
+ pr_warn("No target implementation CPUs specified\n");
+ return;
+ }
+
+ max_cpus = res.a2;
+ target = memblock_alloc(sizeof(*target) * max_cpus, __alignof__(*target));
+ if (!target) {
+ pr_warn("Not enough memory for struct target_impl_cpu\n");
+ return;
+ }
+
+ for (i = 0; i < max_cpus; i++) {
+ arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_DISCOVER_IMPL_CPUS_FUNC_ID,
+ i, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS) {
+ pr_warn("Discovering target implementation CPUs failed\n");
+ goto mem_free;
+ }
+ target[i].midr = res.a1;
+ target[i].revidr = res.a2;
+ target[i].aidr = res.a3;
+ };
+
+ if (!cpu_errata_set_target_impl(max_cpus, target)) {
+ pr_warn("Failed to set target implementation CPUs\n");
+ goto mem_free;
+ }
+
+ pr_info("Number of target implementation CPUs is %lld\n", max_cpus);
+ return;
+
+mem_free:
+ memblock_free(target, sizeof(*target) * max_cpus);
+}
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v8 6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
` (4 preceding siblings ...)
2025-02-21 14:02 ` [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs Shameer Kolothum
@ 2025-02-21 14:02 ` Shameer Kolothum
2025-03-05 23:58 ` [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Oliver Upton
6 siblings, 0 replies; 16+ messages in thread
From: Shameer Kolothum @ 2025-02-21 14:02 UTC (permalink / raw)
To: kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
One difference here with other pseudo-firmware bitmap registers
is that the default/reset value for the supported hypercall
function-ids is 0 at present. Hence, modify the test accordingly.
Reviewed-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
---
tools/arch/arm64/include/uapi/asm/kvm.h | 12 +++++
.../selftests/kvm/arm64/get-reg-list.c | 1 +
.../testing/selftests/kvm/arm64/hypercalls.c | 46 +++++++++++++++----
3 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 66736ff04011..6d44f8c8a18f 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -374,6 +374,7 @@ enum {
#endif
};
+/* Vendor hyper call function numbers 0-63 */
#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2)
enum {
@@ -384,6 +385,17 @@ enum {
#endif
};
+/* Vendor hyper call function numbers 64-127 */
+#define KVM_REG_ARM_VENDOR_HYP_BMAP_2 KVM_REG_ARM_FW_FEAT_BMAP_REG(3)
+
+enum {
+ KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_VER = 0,
+ KVM_REG_ARM_VENDOR_HYP_BIT_DISCOVER_IMPL_CPUS = 1,
+#ifdef __KERNEL__
+ KVM_REG_ARM_VENDOR_HYP_BMAP_2_BIT_COUNT,
+#endif
+};
+
/* Device Control API on vm fd */
#define KVM_ARM_VM_SMCCC_CTRL 0
#define KVM_ARM_VM_SMCCC_FILTER 0
diff --git a/tools/testing/selftests/kvm/arm64/get-reg-list.c b/tools/testing/selftests/kvm/arm64/get-reg-list.c
index d43fb3f49050..d01798b6b3b4 100644
--- a/tools/testing/selftests/kvm/arm64/get-reg-list.c
+++ b/tools/testing/selftests/kvm/arm64/get-reg-list.c
@@ -332,6 +332,7 @@ static __u64 base_regs[] = {
KVM_REG_ARM_FW_FEAT_BMAP_REG(0), /* KVM_REG_ARM_STD_BMAP */
KVM_REG_ARM_FW_FEAT_BMAP_REG(1), /* KVM_REG_ARM_STD_HYP_BMAP */
KVM_REG_ARM_FW_FEAT_BMAP_REG(2), /* KVM_REG_ARM_VENDOR_HYP_BMAP */
+ KVM_REG_ARM_FW_FEAT_BMAP_REG(3), /* KVM_REG_ARM_VENDOR_HYP_BMAP_2 */
ARM64_SYS_REG(3, 3, 14, 3, 1), /* CNTV_CTL_EL0 */
ARM64_SYS_REG(3, 3, 14, 3, 2), /* CNTV_CVAL_EL0 */
ARM64_SYS_REG(3, 3, 14, 0, 2),
diff --git a/tools/testing/selftests/kvm/arm64/hypercalls.c b/tools/testing/selftests/kvm/arm64/hypercalls.c
index ec54ec7726e9..44cfcf8a7f46 100644
--- a/tools/testing/selftests/kvm/arm64/hypercalls.c
+++ b/tools/testing/selftests/kvm/arm64/hypercalls.c
@@ -21,22 +21,31 @@
#define KVM_REG_ARM_STD_BMAP_BIT_MAX 0
#define KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX 0
#define KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX 1
+#define KVM_REG_ARM_VENDOR_HYP_BMAP_2_BIT_MAX 1
+
+#define KVM_REG_ARM_STD_BMAP_RESET_VAL FW_REG_ULIMIT_VAL(KVM_REG_ARM_STD_BMAP_BIT_MAX)
+#define KVM_REG_ARM_STD_HYP_BMAP_RESET_VAL FW_REG_ULIMIT_VAL(KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX)
+#define KVM_REG_ARM_VENDOR_HYP_BMAP_RESET_VAL FW_REG_ULIMIT_VAL(KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX)
+#define KVM_REG_ARM_VENDOR_HYP_BMAP_2_RESET_VAL 0
struct kvm_fw_reg_info {
uint64_t reg; /* Register definition */
uint64_t max_feat_bit; /* Bit that represents the upper limit of the feature-map */
+ uint64_t reset_val; /* Reset value for the register */
};
#define FW_REG_INFO(r) \
{ \
.reg = r, \
.max_feat_bit = r##_BIT_MAX, \
+ .reset_val = r##_RESET_VAL \
}
static const struct kvm_fw_reg_info fw_reg_info[] = {
FW_REG_INFO(KVM_REG_ARM_STD_BMAP),
FW_REG_INFO(KVM_REG_ARM_STD_HYP_BMAP),
FW_REG_INFO(KVM_REG_ARM_VENDOR_HYP_BMAP),
+ FW_REG_INFO(KVM_REG_ARM_VENDOR_HYP_BMAP_2),
};
enum test_stage {
@@ -171,22 +180,39 @@ static void test_fw_regs_before_vm_start(struct kvm_vcpu *vcpu)
for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) {
const struct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
+ uint64_t set_val;
- /* First 'read' should be an upper limit of the features supported */
+ /* First 'read' should be the reset value for the reg */
val = vcpu_get_reg(vcpu, reg_info->reg);
- TEST_ASSERT(val == FW_REG_ULIMIT_VAL(reg_info->max_feat_bit),
- "Expected all the features to be set for reg: 0x%lx; expected: 0x%lx; read: 0x%lx",
- reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit), val);
+ TEST_ASSERT(val == reg_info->reset_val,
+ "Unexpected reset value for reg: 0x%lx; expected: 0x%lx; read: 0x%lx",
+ reg_info->reg, reg_info->reset_val, val);
+
+ if (reg_info->reset_val)
+ set_val = 0;
+ else
+ set_val = FW_REG_ULIMIT_VAL(reg_info->max_feat_bit);
- /* Test a 'write' by disabling all the features of the register map */
- ret = __vcpu_set_reg(vcpu, reg_info->reg, 0);
+ ret = __vcpu_set_reg(vcpu, reg_info->reg, set_val);
TEST_ASSERT(ret == 0,
- "Failed to clear all the features of reg: 0x%lx; ret: %d",
- reg_info->reg, errno);
+ "Failed to %s all the features of reg: 0x%lx; ret: %d",
+ (set_val ? "set" : "clear"), reg_info->reg, errno);
val = vcpu_get_reg(vcpu, reg_info->reg);
- TEST_ASSERT(val == 0,
- "Expected all the features to be cleared for reg: 0x%lx", reg_info->reg);
+ TEST_ASSERT(val == set_val,
+ "Expected all the features to be %s for reg: 0x%lx",
+ (set_val ? "set" : "cleared"), reg_info->reg);
+
+ /*
+ * If the reg has been set, clear it as test_fw_regs_after_vm_start()
+ * expects it to be cleared.
+ */
+ if (set_val) {
+ ret = __vcpu_set_reg(vcpu, reg_info->reg, 0);
+ TEST_ASSERT(ret == 0,
+ "Failed to clear all the features of reg: 0x%lx; ret: %d",
+ reg_info->reg, errno);
+ }
/*
* Test enabling a feature that's not supported.
--
2.47.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally
2025-02-21 14:02 ` [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally Shameer Kolothum
@ 2025-02-26 19:39 ` Catalin Marinas
0 siblings, 0 replies; 16+ messages in thread
From: Catalin Marinas @ 2025-02-26 19:39 UTC (permalink / raw)
To: Shameer Kolothum
Cc: kvmarm, maz, oliver.upton, will, mark.rutland, cohuck, eric.auger,
sebott, yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
On Fri, Feb 21, 2025 at 02:02:24PM +0000, Shameer Kolothum wrote:
> These changes lay the groundwork for adding support for guest kernels,
> allowing them to leverage target CPU implementations provided by the
> VMM.
>
> No functional changes intended.
>
> Suggested-by: Oliver Upton <oliver.upton@linux.dev>
> Reviewed-by: Sebastian Ott <sebott@redhat.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-02-21 14:02 ` [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function Shameer Kolothum
@ 2025-02-26 19:40 ` Catalin Marinas
2025-04-15 10:57 ` [BUG][PATCH " Ada Couprie Diaz
1 sibling, 0 replies; 16+ messages in thread
From: Catalin Marinas @ 2025-02-26 19:40 UTC (permalink / raw)
To: Shameer Kolothum
Cc: kvmarm, maz, oliver.upton, will, mark.rutland, cohuck, eric.auger,
sebott, yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
On Fri, Feb 21, 2025 at 02:02:27PM +0000, Shameer Kolothum wrote:
> Subsequent patch will add target implementation CPU support and that
> will require _midr_in_range_list() to access new data. To avoid
> exporting the data make _midr_in_range_list() a normal function and
> export it.
>
> No functional changes intended.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs
2025-02-21 14:02 ` [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs Shameer Kolothum
@ 2025-02-26 19:41 ` Catalin Marinas
0 siblings, 0 replies; 16+ messages in thread
From: Catalin Marinas @ 2025-02-26 19:41 UTC (permalink / raw)
To: Shameer Kolothum
Cc: kvmarm, maz, oliver.upton, will, mark.rutland, cohuck, eric.auger,
sebott, yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
On Fri, Feb 21, 2025 at 02:02:28PM +0000, Shameer Kolothum wrote:
> Retrieve any migration target implementation CPUs using the hypercall
> and enable associated errata.
>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Reviewed-by: Sebastian Ott <sebott@redhat.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
I can see ways in which this can go wrong but, in the absence of a
better idea:
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
` (5 preceding siblings ...)
2025-02-21 14:02 ` [PATCH v8 6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
@ 2025-03-05 23:58 ` Oliver Upton
6 siblings, 0 replies; 16+ messages in thread
From: Oliver Upton @ 2025-03-05 23:58 UTC (permalink / raw)
To: kvmarm, maz, Shameer Kolothum
Cc: Oliver Upton, catalin.marinas, will, mark.rutland, cohuck,
eric.auger, sebott, yuzenghui, wangzhou1, jiangkunkun,
jonathan.cameron, anthony.jebson, linux-arm-kernel, linuxarm
On Fri, 21 Feb 2025 14:02:23 +0000, Shameer Kolothum wrote:
> v7-->v8
> https://lore.kernel.org/kvmarm/20250214151343.61348-1-shameerali.kolothum.thodi@huawei.com/
>
> Changes:
> -Fixed the compile error issue due to CONFIG_CORESIGHT_SOURCE_ETM4X=m
> (Thanks to Sebastian for checking that config)- patch #4
> -Added R-by tags.
>
> [...]
The feature branch for all of this can be found here should the need arise.
git://git.kernel.org/pub/scm/linux/kernel/git/oupton/linux.git kvm-arm64/pv-cpuid
Applied to next, thanks!
[1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally
https://git.kernel.org/kvmarm/kvmarm/c/e3121298c7fc
[2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations
https://git.kernel.org/kvmarm/kvmarm/c/57e5cc9b8a39
[3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2
https://git.kernel.org/kvmarm/kvmarm/c/c0000e58c74e
[4/6] arm64: Make _midr_in_range_list() an exported function
https://git.kernel.org/kvmarm/kvmarm/c/c8c2647e69be
[5/6] smccc/kvm_guest: Enable errata based on implementation CPUs
https://git.kernel.org/kvmarm/kvmarm/c/86edf6bdcf05
[6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2
https://git.kernel.org/kvmarm/kvmarm/c/f69656656fa7
--
Best,
Oliver
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-02-21 14:02 ` [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function Shameer Kolothum
2025-02-26 19:40 ` Catalin Marinas
@ 2025-04-15 10:57 ` Ada Couprie Diaz
2025-04-15 15:18 ` Shameerali Kolothum Thodi
2025-04-15 15:26 ` Marc Zyngier
1 sibling, 2 replies; 16+ messages in thread
From: Ada Couprie Diaz @ 2025-04-15 10:57 UTC (permalink / raw)
To: Shameer Kolothum, kvmarm, maz, oliver.upton
Cc: catalin.marinas, will, mark.rutland, cohuck, eric.auger, sebott,
yuzenghui, wangzhou1, jiangkunkun, jonathan.cameron,
anthony.jebson, linux-arm-kernel, linuxarm
Hello,
I discovered that this patch breaks boot for some CPUs when building the
default defconfig plus KASAN. This is still the case in v6.15-rc1 and rc2.
This patch marks `is_midr_in_range_list` as position independent but it
isn't, breaking early boot when instrumented with KASAN and
`CONFIG_RANDOMIZE_BASE` enabled.
The breaking usage seems to be in `kaslr_requires_kpti()` called in
`early_map_kernel()`.
My testing on an AMD Seattle board does crash, but newer machines
implementing E0PD do not crash as they do not need to check MIDRs in
`kaslr_requires_kpti()`.
`is_mdr_in_range_list` did work in PI code previously because it was
`inline`, which this patch changes.
Best regards,
Ada Couprie Diaz
On 21/02/2025 14:02, Shameer Kolothum wrote:
> Subsequent patch will add target implementation CPU support and that
> will require _midr_in_range_list() to access new data. To avoid
> exporting the data make _midr_in_range_list() a normal function and
> export it.
>
> No functional changes intended.
>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
> ---
> arch/arm64/include/asm/cputype.h | 15 +--------------
> arch/arm64/kernel/cpu_errata.c | 15 +++++++++++++++
> arch/arm64/kernel/image-vars.h | 1 +
> 3 files changed, 17 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
> index 2a76f0e30006..ccb4a155d118 100644
> --- a/arch/arm64/include/asm/cputype.h
> +++ b/arch/arm64/include/asm/cputype.h
> @@ -276,20 +276,7 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
> return _model == model && rv >= rv_min && rv <= rv_max;
> }
>
> -static inline bool is_midr_in_range(struct midr_range const *range)
> -{
> - return midr_is_cpu_model_range(read_cpuid_id(), range->model,
> - range->rv_min, range->rv_max);
> -}
> -
> -static inline bool
> -is_midr_in_range_list(struct midr_range const *ranges)
> -{
> - while (ranges->model)
> - if (is_midr_in_range(ranges++))
> - return true;
> - return false;
> -}
> +bool is_midr_in_range_list(struct midr_range const *ranges);
>
> static inline u64 __attribute_const__ read_cpuid_mpidr(void)
> {
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 99b55893fc4e..1f51cf6378c5 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -14,6 +14,21 @@
> #include <asm/kvm_asm.h>
> #include <asm/smp_plat.h>
>
> +static inline bool is_midr_in_range(struct midr_range const *range)
> +{
> + return midr_is_cpu_model_range(read_cpuid_id(), range->model,
> + range->rv_min, range->rv_max);
> +}
> +
> +bool is_midr_in_range_list(struct midr_range const *ranges)
> +{
> + while (ranges->model)
> + if (is_midr_in_range(ranges++))
> + return true;
> + return false;
> +}
> +EXPORT_SYMBOL_GPL(is_midr_in_range_list);
> +
> static bool __maybe_unused
> __is_affected_midr_range(const struct arm64_cpu_capabilities *entry,
> u32 midr, u32 revidr)
> diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
> index ef3a69cc398e..de3d081e5a57 100644
> --- a/arch/arm64/kernel/image-vars.h
> +++ b/arch/arm64/kernel/image-vars.h
> @@ -49,6 +49,7 @@ PROVIDE(__pi_arm64_sw_feature_override = arm64_sw_feature_override);
> PROVIDE(__pi_arm64_use_ng_mappings = arm64_use_ng_mappings);
> #ifdef CONFIG_CAVIUM_ERRATUM_27456
> PROVIDE(__pi_cavium_erratum_27456_cpus = cavium_erratum_27456_cpus);
> +PROVIDE(__pi_is_midr_in_range_list = is_midr_in_range_list);
> #endif
> PROVIDE(__pi__ctype = _ctype);
> PROVIDE(__pi_memstart_offset_seed = memstart_offset_seed);
^ permalink raw reply [flat|nested] 16+ messages in thread
* RE: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-04-15 10:57 ` [BUG][PATCH " Ada Couprie Diaz
@ 2025-04-15 15:18 ` Shameerali Kolothum Thodi
2025-04-15 15:26 ` Marc Zyngier
1 sibling, 0 replies; 16+ messages in thread
From: Shameerali Kolothum Thodi @ 2025-04-15 15:18 UTC (permalink / raw)
To: Ada Couprie Diaz, kvmarm@lists.linux.dev, maz@kernel.org,
oliver.upton@linux.dev
Cc: catalin.marinas@arm.com, will@kernel.org, mark.rutland@arm.com,
cohuck@redhat.com, eric.auger@redhat.com, sebott@redhat.com,
yuzenghui, Wangzhou (B), jiangkunkun, Jonathan Cameron,
Anthony Jebson, linux-arm-kernel@lists.infradead.org, Linuxarm
Hi,
> -----Original Message-----
> From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
> Sent: Tuesday, April 15, 2025 11:58 AM
> To: Shameerali Kolothum Thodi
> <shameerali.kolothum.thodi@huawei.com>; kvmarm@lists.linux.dev;
> maz@kernel.org; oliver.upton@linux.dev
> Cc: catalin.marinas@arm.com; will@kernel.org; mark.rutland@arm.com;
> cohuck@redhat.com; eric.auger@redhat.com; sebott@redhat.com;
> yuzenghui <yuzenghui@huawei.com>; Wangzhou (B)
> <wangzhou1@hisilicon.com>; jiangkunkun <jiangkunkun@huawei.com>;
> Jonathan Cameron <jonathan.cameron@huawei.com>; Anthony Jebson
> <anthony.jebson@huawei.com>; linux-arm-kernel@lists.infradead.org;
> Linuxarm <linuxarm@huawei.com>
> Subject: Re: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an
> exported function
>
> Hello,
>
> I discovered that this patch breaks boot for some CPUs when building the
> default defconfig plus KASAN. This is still the case in v6.15-rc1 and rc2.
Thanks for testing and reporting this.
>
> This patch marks `is_midr_in_range_list` as position independent but it
> isn't, breaking early boot when instrumented with KASAN and
> `CONFIG_RANDOMIZE_BASE` enabled.
I am not sure what else is needed to make this position independent
other than,
PROVIDE(__pi_is_midr_in_range_list = is_midr_in_range_list);
May be since this is now a text session that we are making PI, it is probably
missing some other bits. My understanding of that part of the code is
very limited.
Marc/Oliver,
Any thoughts?
>
> The breaking usage seems to be in `kaslr_requires_kpti()` called in
> `early_map_kernel()`.
> My testing on an AMD Seattle board does crash, but newer machines
> implementing E0PD do not crash as they do not need to check MIDRs in
> `kaslr_requires_kpti()`.
> `is_mdr_in_range_list` did work in PI code previously because it was
> `inline`, which this patch changes.
Yeah. The change from inline happened after the v7[0]. May we could go
back to that so that only data needs to be PI if fixing above is invasive.
I just tested with the v7 version and it boots with KASAN and
CONFIG_RANDOMIZE_BASE.
Thanks,
Shameer
[0] https://lore.kernel.org/kvmarm/0557f193756f45daac4349c30d8f2f8f@huawei.com/
>
> Best regards,
> Ada Couprie Diaz
>
> On 21/02/2025 14:02, Shameer Kolothum wrote:
> > Subsequent patch will add target implementation CPU support and that
> > will require _midr_in_range_list() to access new data. To avoid
> > exporting the data make _midr_in_range_list() a normal function and
> > export it.
> >
> > No functional changes intended.
> >
> > Signed-off-by: Shameer Kolothum
> <shameerali.kolothum.thodi@huawei.com>
> > ---
> > arch/arm64/include/asm/cputype.h | 15 +--------------
> > arch/arm64/kernel/cpu_errata.c | 15 +++++++++++++++
> > arch/arm64/kernel/image-vars.h | 1 +
> > 3 files changed, 17 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/arm64/include/asm/cputype.h
> b/arch/arm64/include/asm/cputype.h
> > index 2a76f0e30006..ccb4a155d118 100644
> > --- a/arch/arm64/include/asm/cputype.h
> > +++ b/arch/arm64/include/asm/cputype.h
> > @@ -276,20 +276,7 @@ static inline bool midr_is_cpu_model_range(u32
> midr, u32 model, u32 rv_min,
> > return _model == model && rv >= rv_min && rv <= rv_max;
> > }
> >
> > -static inline bool is_midr_in_range(struct midr_range const *range)
> > -{
> > - return midr_is_cpu_model_range(read_cpuid_id(), range->model,
> > - range->rv_min, range->rv_max);
> > -}
> > -
> > -static inline bool
> > -is_midr_in_range_list(struct midr_range const *ranges)
> > -{
> > - while (ranges->model)
> > - if (is_midr_in_range(ranges++))
> > - return true;
> > - return false;
> > -}
> > +bool is_midr_in_range_list(struct midr_range const *ranges);
> >
> > static inline u64 __attribute_const__ read_cpuid_mpidr(void)
> > {
> > diff --git a/arch/arm64/kernel/cpu_errata.c
> b/arch/arm64/kernel/cpu_errata.c
> > index 99b55893fc4e..1f51cf6378c5 100644
> > --- a/arch/arm64/kernel/cpu_errata.c
> > +++ b/arch/arm64/kernel/cpu_errata.c
> > @@ -14,6 +14,21 @@
> > #include <asm/kvm_asm.h>
> > #include <asm/smp_plat.h>
> >
> > +static inline bool is_midr_in_range(struct midr_range const *range)
> > +{
> > + return midr_is_cpu_model_range(read_cpuid_id(), range->model,
> > + range->rv_min, range->rv_max);
> > +}
> > +
> > +bool is_midr_in_range_list(struct midr_range const *ranges)
> > +{
> > + while (ranges->model)
> > + if (is_midr_in_range(ranges++))
> > + return true;
> > + return false;
> > +}
> > +EXPORT_SYMBOL_GPL(is_midr_in_range_list);
> > +
> > static bool __maybe_unused
> > __is_affected_midr_range(const struct arm64_cpu_capabilities *entry,
> > u32 midr, u32 revidr)
> > diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-
> vars.h
> > index ef3a69cc398e..de3d081e5a57 100644
> > --- a/arch/arm64/kernel/image-vars.h
> > +++ b/arch/arm64/kernel/image-vars.h
> > @@ -49,6 +49,7 @@ PROVIDE(__pi_arm64_sw_feature_override =
> arm64_sw_feature_override);
> > PROVIDE(__pi_arm64_use_ng_mappings = arm64_use_ng_mappings);
> > #ifdef CONFIG_CAVIUM_ERRATUM_27456
> > PROVIDE(__pi_cavium_erratum_27456_cpus =
> cavium_erratum_27456_cpus);
> > +PROVIDE(__pi_is_midr_in_range_list = is_midr_in_range_list);
> > #endif
> > PROVIDE(__pi__ctype = _ctype);
> > PROVIDE(__pi_memstart_offset_seed = memstart_offset_seed);
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-04-15 10:57 ` [BUG][PATCH " Ada Couprie Diaz
2025-04-15 15:18 ` Shameerali Kolothum Thodi
@ 2025-04-15 15:26 ` Marc Zyngier
2025-04-15 15:54 ` Catalin Marinas
1 sibling, 1 reply; 16+ messages in thread
From: Marc Zyngier @ 2025-04-15 15:26 UTC (permalink / raw)
To: Ada Couprie Diaz
Cc: Shameer Kolothum, kvmarm, oliver.upton, catalin.marinas, will,
mark.rutland, cohuck, eric.auger, sebott, yuzenghui, wangzhou1,
jiangkunkun, jonathan.cameron, anthony.jebson, linux-arm-kernel,
linuxarm
On Tue, 15 Apr 2025 11:57:50 +0100,
Ada Couprie Diaz <ada.coupriediaz@arm.com> wrote:
>
> Hello,
>
> I discovered that this patch breaks boot for some CPUs when building
> the default defconfig plus KASAN. This is still the case in v6.15-rc1
> and rc2.
>
> This patch marks `is_midr_in_range_list` as position independent but
> it isn't, breaking early boot when instrumented with KASAN and
> `CONFIG_RANDOMIZE_BASE` enabled.
>
> The breaking usage seems to be in `kaslr_requires_kpti()` called in
> `early_map_kernel()`.
> My testing on an AMD Seattle board does crash, but newer machines
> implementing E0PD do not crash as they do not need to check MIDRs in
> `kaslr_requires_kpti()`.
> `is_mdr_in_range_list` did work in PI code previously because it was
> `inline`, which this patch changes.
OK, this is much more of a pain than I thought.
I tried bringing the various helpers into the PI section, but it ended
up being extremely ugly.
More importantly, this is something that is pretty much at odds with
the whole idea of the MIDR override -- it happens way earlier than we
can populate the table.
The thing is, the only reason we need to do this is that we need to
support the Cavium SEFAC (Sorry Excuse For A Computer) that cannot run
with KPTI.
I can restore harmony with the following hack. But maybe we should
just prune TX from the kernel and be done with this contraption.
M.
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index d1cc0571798bf..bdfefca166baa 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -292,6 +292,20 @@ static inline bool midr_is_cpu_model_range(u32 midr, u32 model, u32 rv_min,
return _model == model && rv >= rv_min && rv <= rv_max;
}
+static inline bool __is_midr_in_range(struct midr_range const *range)
+{
+ return midr_is_cpu_model_range(read_cpuid_id(), range->model,
+ range->rv_min, range->rv_max);
+}
+
+static inline bool __is_midr_in_range_list(struct midr_range const *ranges)
+{
+ while (ranges->model)
+ if (__is_midr_in_range(ranges++))
+ return true;
+ return false;
+}
+
struct target_impl_cpu {
u64 midr;
u64 revidr;
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 30a29e88994ba..e54a384826dc1 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -72,6 +72,17 @@ extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot);
extern void mark_linear_text_alias_ro(void);
+static inline bool cpu_has_e0pd(void)
+{
+ if (IS_ENABLED(CONFIG_ARM64_E0PD)) {
+ u64 mmfr2 = read_sysreg_s(SYS_ID_AA64MMFR2_EL1);
+ return (cpuid_feature_extract_unsigned_field(mmfr2,
+ ID_AA64MMFR2_EL1_E0PD_SHIFT));
+ }
+
+ return false;
+}
+
/*
* This check is triggered during the early boot before the cpufeature
* is initialised. Checking the status on the local CPU allows the boot
@@ -87,12 +98,8 @@ static inline bool kaslr_requires_kpti(void)
* E0PD does a similar job to KPTI so can be used instead
* where available.
*/
- if (IS_ENABLED(CONFIG_ARM64_E0PD)) {
- u64 mmfr2 = read_sysreg_s(SYS_ID_AA64MMFR2_EL1);
- if (cpuid_feature_extract_unsigned_field(mmfr2,
- ID_AA64MMFR2_EL1_E0PD_SHIFT))
- return false;
- }
+ if (cpu_has_e0pd())
+ return false;
/*
* Systems affected by Cavium erratum 24756 are incompatible
@@ -108,5 +115,21 @@ static inline bool kaslr_requires_kpti(void)
return true;
}
+/* Same as the above, but limited to the local CPU, ignoring the MIDR list */
+static inline bool __kaslr_requires_kpti(void)
+{
+ if (cpu_has_e0pd())
+ return false;
+
+ if (IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) {
+ extern const struct midr_range cavium_erratum_27456_cpus[];
+
+ if (__is_midr_in_range_list(cavium_erratum_27456_cpus))
+ return false;
+ }
+
+ return true;
+}
+
#endif /* !__ASSEMBLY__ */
#endif
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index b55f5f7057502..ba8e05d640c7e 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -32,8 +32,7 @@ static inline bool is_midr_in_range(struct midr_range const *range)
int i;
if (!target_impl_cpu_num)
- return midr_is_cpu_model_range(read_cpuid_id(), range->model,
- range->rv_min, range->rv_max);
+ return __is_midr_in_range(range);
for (i = 0; i < target_impl_cpu_num; i++) {
if (midr_is_cpu_model_range(target_impl_cpus[i].midr,
diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c
index e57b043f324b5..2df76d44a1072 100644
--- a/arch/arm64/kernel/pi/map_kernel.c
+++ b/arch/arm64/kernel/pi/map_kernel.c
@@ -245,7 +245,7 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
u64 kaslr_seed = kaslr_early_init(fdt, chosen);
- if (kaslr_seed && kaslr_requires_kpti())
+ if (kaslr_seed && __kaslr_requires_kpti())
arm64_use_ng_mappings = true;
kaslr_offset |= kaslr_seed & ~(MIN_KIMG_ALIGN - 1);
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-04-15 15:26 ` Marc Zyngier
@ 2025-04-15 15:54 ` Catalin Marinas
2025-04-15 16:47 ` Marc Zyngier
0 siblings, 1 reply; 16+ messages in thread
From: Catalin Marinas @ 2025-04-15 15:54 UTC (permalink / raw)
To: Marc Zyngier
Cc: mark.rutland, jiangkunkun, eric.auger, cohuck, linuxarm,
oliver.upton, yuzenghui, wangzhou1, Shameer Kolothum,
jonathan.cameron, kvmarm, sebott, will, linux-arm-kernel,
anthony.jebson
On Tue, Apr 15, 2025 at 04:26:53PM +0100, Marc Zyngier wrote:
> On Tue, 15 Apr 2025 11:57:50 +0100,
> Ada Couprie Diaz <ada.coupriediaz@arm.com> wrote:
> > I discovered that this patch breaks boot for some CPUs when building
> > the default defconfig plus KASAN. This is still the case in v6.15-rc1
> > and rc2.
> >
> > This patch marks `is_midr_in_range_list` as position independent but
> > it isn't, breaking early boot when instrumented with KASAN and
> > `CONFIG_RANDOMIZE_BASE` enabled.
> >
> > The breaking usage seems to be in `kaslr_requires_kpti()` called in
> > `early_map_kernel()`.
> > My testing on an AMD Seattle board does crash, but newer machines
> > implementing E0PD do not crash as they do not need to check MIDRs in
> > `kaslr_requires_kpti()`.
> > `is_mdr_in_range_list` did work in PI code previously because it was
> > `inline`, which this patch changes.
>
> OK, this is much more of a pain than I thought.
>
> I tried bringing the various helpers into the PI section, but it ended
> up being extremely ugly.
>
> More importantly, this is something that is pretty much at odds with
> the whole idea of the MIDR override -- it happens way earlier than we
> can populate the table.
>
> The thing is, the only reason we need to do this is that we need to
> support the Cavium SEFAC (Sorry Excuse For A Computer) that cannot run
> with KPTI.
>
> I can restore harmony with the following hack. But maybe we should
> just prune TX from the kernel and be done with this contraption.
That works for me. Well, we can still keep it around but panic on boot
if kpti is enabled on this platform. Just don't bother checking it via
early_map_kernel() from the PI code.
--
Catalin
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [BUG][PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function
2025-04-15 15:54 ` Catalin Marinas
@ 2025-04-15 16:47 ` Marc Zyngier
0 siblings, 0 replies; 16+ messages in thread
From: Marc Zyngier @ 2025-04-15 16:47 UTC (permalink / raw)
To: Catalin Marinas
Cc: mark.rutland, jiangkunkun, eric.auger, cohuck, linuxarm,
oliver.upton, yuzenghui, wangzhou1, Shameer Kolothum,
jonathan.cameron, kvmarm, sebott, will, linux-arm-kernel,
anthony.jebson
On Tue, 15 Apr 2025 16:54:58 +0100,
Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> On Tue, Apr 15, 2025 at 04:26:53PM +0100, Marc Zyngier wrote:
> > On Tue, 15 Apr 2025 11:57:50 +0100,
> > Ada Couprie Diaz <ada.coupriediaz@arm.com> wrote:
> > > I discovered that this patch breaks boot for some CPUs when building
> > > the default defconfig plus KASAN. This is still the case in v6.15-rc1
> > > and rc2.
> > >
> > > This patch marks `is_midr_in_range_list` as position independent but
> > > it isn't, breaking early boot when instrumented with KASAN and
> > > `CONFIG_RANDOMIZE_BASE` enabled.
> > >
> > > The breaking usage seems to be in `kaslr_requires_kpti()` called in
> > > `early_map_kernel()`.
> > > My testing on an AMD Seattle board does crash, but newer machines
> > > implementing E0PD do not crash as they do not need to check MIDRs in
> > > `kaslr_requires_kpti()`.
> > > `is_mdr_in_range_list` did work in PI code previously because it was
> > > `inline`, which this patch changes.
> >
> > OK, this is much more of a pain than I thought.
> >
> > I tried bringing the various helpers into the PI section, but it ended
> > up being extremely ugly.
> >
> > More importantly, this is something that is pretty much at odds with
> > the whole idea of the MIDR override -- it happens way earlier than we
> > can populate the table.
> >
> > The thing is, the only reason we need to do this is that we need to
> > support the Cavium SEFAC (Sorry Excuse For A Computer) that cannot run
> > with KPTI.
> >
> > I can restore harmony with the following hack. But maybe we should
> > just prune TX from the kernel and be done with this contraption.
>
> That works for me. Well, we can still keep it around but panic on boot
> if kpti is enabled on this platform. Just don't bother checking it via
> early_map_kernel() from the PI code.
early_map_kernel() immediately builds nG page tables, and that's a
strong guarantee to catch fire on this machine. Which means that
distro kernels (which all have KPTI enabled by default) would explode.
The only way to avoid it would be to mandate that users of these
machines have nokaslr on the command-line. I'm happy to do so on my
box, but I'm hardly representative of arm64 users...
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-04-15 17:10 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-21 14:02 [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 1/6] arm64: Modify _midr_range() functions to read MIDR/REVIDR internally Shameer Kolothum
2025-02-26 19:39 ` Catalin Marinas
2025-02-21 14:02 ` [PATCH v8 2/6] KVM: arm64: Introduce hypercall support for retrieving target implementations Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 3/6] KVM: arm64: Introduce KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
2025-02-21 14:02 ` [PATCH v8 4/6] arm64: Make _midr_in_range_list() an exported function Shameer Kolothum
2025-02-26 19:40 ` Catalin Marinas
2025-04-15 10:57 ` [BUG][PATCH " Ada Couprie Diaz
2025-04-15 15:18 ` Shameerali Kolothum Thodi
2025-04-15 15:26 ` Marc Zyngier
2025-04-15 15:54 ` Catalin Marinas
2025-04-15 16:47 ` Marc Zyngier
2025-02-21 14:02 ` [PATCH v8 5/6] smccc/kvm_guest: Enable errata based on implementation CPUs Shameer Kolothum
2025-02-26 19:41 ` Catalin Marinas
2025-02-21 14:02 ` [PATCH v8 6/6] KVM: selftests: Add test for KVM_REG_ARM_VENDOR_HYP_BMAP_2 Shameer Kolothum
2025-03-05 23:58 ` [PATCH v8 0/6] KVM: arm64: Errata management for VM Live migration Oliver Upton
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).