[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine
From: |
Yong-Xuan Wang |
Subject: |
[PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine |
Date: |
Wed, 21 Jun 2023 14:54:56 +0000 |
Select KVM AIA when the host kernel has in-kernel AIA chip support.
Since KVM AIA only has one APLIC instance, we map the QEMU APLIC
devices to KVM APLIC.
We also extend virt machine to specify the KVM AIA mode. The "kvm-aia"
parameter is passed along with machine name in QEMU command-line.
1) "kvm-aia=emul": IMSIC is emulated by hypervisor
2) "kvm-aia=hwaccel": use hardware guest IMSIC
3) "kvm-aia=auto": use the hardware guest IMSICs whenever available
otherwise we fallback to software emulation.
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
---
hw/riscv/virt.c | 92 ++++++++++++++++++++++++++++++++++-------
include/hw/riscv/virt.h | 1 +
2 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4a1d29a741..efa176a184 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -35,6 +35,7 @@
#include "hw/riscv/virt.h"
#include "hw/riscv/boot.h"
#include "hw/riscv/numa.h"
+#include "kvm_riscv.h"
#include "hw/intc/riscv_aclint.h"
#include "hw/intc/riscv_aplic.h"
#include "hw/intc/riscv_imsic.h"
@@ -74,6 +75,12 @@
#error "Can't accomodate all IMSIC groups in address space"
#endif
+/* KVM AIA only supports APLIC.m. APLIC.w is always emulated by QEMU. */
+static bool virt_use_kvm_aia(RISCVVirtState *s)
+{
+ return kvm_irqchip_in_kernel() && s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC;
+}
+
static const MemMapEntry virt_memmap[] = {
[VIRT_DEBUG] = { 0x0, 0x100 },
[VIRT_MROM] = { 0x1000, 0xf000 },
@@ -642,7 +649,8 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
uint32_t msi_s_phandle,
uint32_t *phandle,
uint32_t *intc_phandles,
- uint32_t *aplic_phandles)
+ uint32_t *aplic_phandles,
+ int num_harts)
{
int cpu;
char *aplic_name;
@@ -653,11 +661,11 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
aplic_m_phandle = (*phandle)++;
aplic_s_phandle = (*phandle)++;
- aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+ aplic_cells = g_new0(uint32_t, num_harts * 2);
if (!kvm_enabled()) {
/* M-level APLIC node */
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
+ for (cpu = 0; cpu < num_harts; cpu++) {
aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
}
@@ -691,7 +699,7 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
}
/* S-level APLIC node */
- for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
+ for (cpu = 0; cpu < num_harts; cpu++) {
aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
aplic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT);
}
@@ -798,17 +806,25 @@ static void create_fdt_sockets(RISCVVirtState *s, const
MemMapEntry *memmap,
*msi_pcie_phandle = msi_s_phandle;
}
- phandle_pos = ms->smp.cpus;
- for (socket = (socket_count - 1); socket >= 0; socket--) {
- phandle_pos -= s->soc[socket].num_harts;
+ /* KVM AIA only has one APLIC instance */
+ if (virt_use_kvm_aia(s)) {
+ create_fdt_socket_aplic(s, memmap, 0,
+ msi_m_phandle, msi_s_phandle, phandle,
+ &intc_phandles[0], xplic_phandles, ms->smp.cpus);
+ } else {
+ phandle_pos = ms->smp.cpus;
+ for (socket = (socket_count - 1); socket >= 0; socket--) {
+ phandle_pos -= s->soc[socket].num_harts;
- if (s->aia_type == VIRT_AIA_TYPE_NONE) {
- create_fdt_socket_plic(s, memmap, socket, phandle,
- &intc_phandles[phandle_pos], xplic_phandles);
- } else {
- create_fdt_socket_aplic(s, memmap, socket,
- msi_m_phandle, msi_s_phandle, phandle,
- &intc_phandles[phandle_pos], xplic_phandles);
+ if (s->aia_type == VIRT_AIA_TYPE_NONE) {
+ create_fdt_socket_plic(s, memmap, socket, phandle,
+ &intc_phandles[phandle_pos], xplic_phandles);
+ } else {
+ create_fdt_socket_aplic(s, memmap, socket,
+ msi_m_phandle, msi_s_phandle, phandle,
+ &intc_phandles[phandle_pos], xplic_phandles,
+ s->soc[socket].num_harts);
+ }
}
}
@@ -819,6 +835,9 @@ static void create_fdt_sockets(RISCVVirtState *s, const
MemMapEntry *memmap,
*irq_mmio_phandle = xplic_phandles[socket];
*irq_virtio_phandle = xplic_phandles[socket];
*irq_pcie_phandle = xplic_phandles[socket];
+
+ if (virt_use_kvm_aia(s))
+ break;
}
if (socket == 1) {
*irq_virtio_phandle = xplic_phandles[socket];
@@ -1454,6 +1473,14 @@ static void virt_machine_init(MachineState *machine)
}
}
+ if (virt_use_kvm_aia(s)) {
+ kvm_riscv_aia_create(
+ machine, s->kvm_aia_mode, IMSIC_MMIO_GROUP_MIN_SHIFT,
+ VIRT_IRQCHIP_NUM_SOURCES, VIRT_IRQCHIP_NUM_MSIS,
+ memmap[VIRT_APLIC_S].base, memmap[VIRT_IMSIC_S].base,
+ s->aia_guests);
+ }
+
if (riscv_is_32bit(&s->soc[0])) {
#if HOST_LONG_BITS == 64
/* limit RAM size in a 32-bit system */
@@ -1610,6 +1637,31 @@ static void virt_set_aia(Object *obj, const char *val,
Error **errp)
}
}
+#if defined(CONFIG_KVM)
+static char *virt_get_kvm_aia(Object *obj, Error **errp)
+{
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+
+ return kvm_aia_mode_str(s->kvm_aia_mode);
+}
+
+static void virt_set_kvm_aia(Object *obj, const char *val, Error **errp)
+{
+ RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+
+ if (!strcmp(val, "emul")) {
+ s->kvm_aia_mode = KVM_DEV_RISCV_AIA_MODE_EMUL;
+ } else if (!strcmp(val, "hwaccel")) {
+ s->kvm_aia_mode = KVM_DEV_RISCV_AIA_MODE_HWACCEL;
+ } else if (!strcmp(val, "auto")) {
+ s->kvm_aia_mode = KVM_DEV_RISCV_AIA_MODE_AUTO;
+ } else {
+ error_setg(errp, "Invalid KVM AIA mode");
+ error_append_hint(errp, "Valid values are emul, hwaccel, and auto.\n");
+ }
+}
+#endif
+
static bool virt_get_aclint(Object *obj, Error **errp)
{
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
@@ -1717,6 +1769,18 @@ static void virt_machine_class_init(ObjectClass *oc,
void *data)
sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value "
"should be between 0 and %d.", VIRT_IRQCHIP_MAX_GUESTS);
object_class_property_set_description(oc, "aia-guests", str);
+
+#if defined(CONFIG_KVM)
+ object_class_property_add_str(oc, "kvm-aia", virt_get_kvm_aia,
+ virt_set_kvm_aia);
+ object_class_property_set_description(oc, "kvm-aia",
+ "Set KVM AIA mode. Valid values are "
+ "emul, hwaccel, and auto. Default "
+ "is auto.");
+ object_property_set_default_str(object_class_property_find(oc, "kvm-aia"),
+ "auto");
+
+#endif
object_class_property_add(oc, "acpi", "OnOffAuto",
virt_get_acpi, virt_set_acpi,
NULL, NULL);
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index e5c474b26e..d0140feeff 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -56,6 +56,7 @@ struct RISCVVirtState {
bool have_aclint;
RISCVVirtAIAType aia_type;
int aia_guests;
+ uint64_t kvm_aia_mode;
char *oem_id;
char *oem_table_id;
OnOffAuto acpi;
--
2.17.1
- [PATCH v4 0/6] Add RISC-V KVM AIA Support, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA, Yong-Xuan Wang, 2023/06/21
- [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine,
Yong-Xuan Wang <=