hw/arm/imx8mp-evk: Add KVM support

Allows the imx8mp-evk machine to run guests with KVM acceleration.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-id: 20251101120130.236721-2-shentey@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Bernhard Beschow
2025-11-01 13:01:29 +01:00
committed by Peter Maydell
parent 53b41bb789
commit 094fd7d36f
4 changed files with 61 additions and 6 deletions

View File

@@ -60,3 +60,22 @@ Now that everything is prepared the machine can be started as follows:
-dtb imx8mp-evk.dtb \
-append "root=/dev/mmcblk2p2" \
-drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
KVM Acceleration
----------------
To enable hardware-assisted acceleration via KVM, append
``-accel kvm -cpu host`` to the command line. While this speeds up performance
significantly, be aware of the following limitations:
* The ``imx8mp-evk`` machine is not included under the "virtualization use case"
of :doc:`QEMU's security policy </system/security>`. This means that you
should not trust that it can contain malicious guests, whether it is run
using TCG or KVM. If you don't trust your guests and you're relying on QEMU to
be the security boundary, you want to choose another machine such as ``virt``.
* Rather than Cortex-A53 CPUs, the same CPU type as the host's will be used.
This is a limitation of KVM and may not work with guests with a tight
dependency on Cortex-A53.
* No EL2 and EL3 exception levels are available which is also a KVM limitation.
Direct kernel boot should work but running U-Boot, TF-A, etc. won't succeed.

View File

@@ -622,7 +622,8 @@ config FSL_IMX8MP
config FSL_IMX8MP_EVK
bool
default y
depends on TCG && AARCH64
depends on AARCH64
depends on TCG || KVM
select FSL_IMX8MP
config ARM_SMMUV3

View File

@@ -12,11 +12,13 @@
#include "system/address-spaces.h"
#include "hw/arm/bsa.h"
#include "hw/arm/fsl-imx8mp.h"
#include "hw/intc/arm_gicv3.h"
#include "hw/misc/unimp.h"
#include "hw/boards.h"
#include "system/kvm.h"
#include "system/system.h"
#include "target/arm/cpu.h"
#include "target/arm/cpu-qom.h"
#include "target/arm/kvm_arm.h"
#include "qapi/error.h"
#include "qobject/qlist.h"
@@ -193,15 +195,15 @@ static void fsl_imx8mp_init(Object *obj)
{
MachineState *ms = MACHINE(qdev_get_machine());
FslImx8mpState *s = FSL_IMX8MP(obj);
const char *cpu_type = ms->cpu_type ?: ARM_CPU_TYPE_NAME("cortex-a53");
int i;
for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX8MP_NUM_CPUS); i++) {
g_autofree char *name = g_strdup_printf("cpu%d", i);
object_initialize_child(obj, name, &s->cpu[i],
ARM_CPU_TYPE_NAME("cortex-a53"));
object_initialize_child(obj, name, &s->cpu[i], cpu_type);
}
object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GICV3);
object_initialize_child(obj, "gic", &s->gic, gicv3_class_name());
object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
@@ -274,7 +276,8 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
/* CPUs */
for (i = 0; i < ms->smp.cpus; i++) {
/* On uniprocessor, the CBAR is set to 0 */
if (ms->smp.cpus > 1) {
if (ms->smp.cpus > 1 &&
object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
object_property_set_int(OBJECT(&s->cpu[i]), "reset-cbar",
fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
&error_abort);
@@ -286,6 +289,16 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
object_property_set_int(OBJECT(&s->cpu[i]), "cntfrq", 8000000,
&error_abort);
if (object_property_find(OBJECT(&s->cpu[i]), "has_el2")) {
object_property_set_bool(OBJECT(&s->cpu[i]), "has_el2",
!kvm_enabled(), &error_abort);
}
if (object_property_find(OBJECT(&s->cpu[i]), "has_el3")) {
object_property_set_bool(OBJECT(&s->cpu[i]), "has_el3",
!kvm_enabled(), &error_abort);
}
if (i) {
/*
* Secondary CPUs start in powered-down state (and can be
@@ -304,6 +317,7 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *gicsbd = SYS_BUS_DEVICE(&s->gic);
QList *redist_region_count;
bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL);
qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
qdev_prop_set_uint32(gicdev, "num-irq",
@@ -360,6 +374,16 @@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
if (kvm_enabled()) {
if (pmu) {
assert(arm_feature(&s->cpu[i].env, ARM_FEATURE_PMU));
if (kvm_irqchip_in_kernel()) {
kvm_arm_pmu_set_irq(&s->cpu[i], VIRTUAL_PMU_IRQ);
}
kvm_arm_pmu_init(&s->cpu[i]);
}
}
}
}

View File

@@ -13,6 +13,7 @@
#include "hw/arm/machines-qom.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
#include "system/kvm.h"
#include "system/qtest.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
@@ -94,12 +95,22 @@ static void imx8mp_evk_init(MachineState *machine)
}
}
static const char *imx8mp_evk_get_default_cpu_type(const MachineState *ms)
{
if (kvm_enabled()) {
return ARM_CPU_TYPE_NAME("host");
}
return ARM_CPU_TYPE_NAME("cortex-a53");
}
static void imx8mp_evk_machine_init(MachineClass *mc)
{
mc->desc = "NXP i.MX 8M Plus EVK Board";
mc->init = imx8mp_evk_init;
mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
mc->default_ram_id = "imx8mp-evk.ram";
mc->get_default_cpu_type = imx8mp_evk_get_default_cpu_type;
}
DEFINE_MACHINE_AARCH64("imx8mp-evk", imx8mp_evk_machine_init)