* [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-06-30 10:00 ` Daniel Henrique Barboza
2023-06-21 14:54 ` [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled Yong-Xuan Wang
` (5 subsequent siblings)
6 siblings, 1 reply; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Michael S. Tsirkin,
Cornelia Huck, Paolo Bonzini, Juan Quintela, Thomas Huth,
Peter Xu, kvm
Sync-up Linux header to get latest KVM RISC-V headers having AIA support.
Note: This is a placeholder commit and could be replaced when all referenced Linux patchsets are mainlined.
The linux-headers changes are from 2 different patchsets.
[1] https://lore.kernel.org/lkml/20230404153452.2405681-1-apatel@ventanamicro.com/
[2] https://www.spinics.net/lists/kernel/msg4791872.html
Currently, patchset 1 is already merged into mainline kernel in v6.4-rc1 and patchset 2 is not.
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
---
| 123 +++++++++++++++++++++++++++++++++-
| 2 +
2 files changed, 124 insertions(+), 1 deletion(-)
--git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h
index 92af6f3f05..a16ca62419 100644
--- a/linux-headers/asm-riscv/kvm.h
+++ b/linux-headers/asm-riscv/kvm.h
@@ -12,8 +12,10 @@
#ifndef __ASSEMBLY__
#include <linux/types.h>
+#include <asm/bitsperlong.h>
#include <asm/ptrace.h>
+#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_READONLY_MEM
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -64,7 +66,7 @@ struct kvm_riscv_core {
#define KVM_RISCV_MODE_S 1
#define KVM_RISCV_MODE_U 0
-/* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
+/* General CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
struct kvm_riscv_csr {
unsigned long sstatus;
unsigned long sie;
@@ -78,6 +80,17 @@ struct kvm_riscv_csr {
unsigned long scounteren;
};
+/* AIA CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
+struct kvm_riscv_aia_csr {
+ unsigned long siselect;
+ unsigned long iprio1;
+ unsigned long iprio2;
+ unsigned long sieh;
+ unsigned long siph;
+ unsigned long iprio1h;
+ unsigned long iprio2h;
+};
+
/* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
struct kvm_riscv_timer {
__u64 frequency;
@@ -105,9 +118,28 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_SVINVAL,
KVM_RISCV_ISA_EXT_ZIHINTPAUSE,
KVM_RISCV_ISA_EXT_ZICBOM,
+ KVM_RISCV_ISA_EXT_ZBB,
+ KVM_RISCV_ISA_EXT_SSAIA,
KVM_RISCV_ISA_EXT_MAX,
};
+/*
+ * SBI extension IDs specific to KVM. This is not the same as the SBI
+ * extension IDs defined by the RISC-V SBI specification.
+ */
+enum KVM_RISCV_SBI_EXT_ID {
+ KVM_RISCV_SBI_EXT_V01 = 0,
+ KVM_RISCV_SBI_EXT_TIME,
+ KVM_RISCV_SBI_EXT_IPI,
+ KVM_RISCV_SBI_EXT_RFENCE,
+ KVM_RISCV_SBI_EXT_SRST,
+ KVM_RISCV_SBI_EXT_HSM,
+ KVM_RISCV_SBI_EXT_PMU,
+ KVM_RISCV_SBI_EXT_EXPERIMENTAL,
+ KVM_RISCV_SBI_EXT_VENDOR,
+ KVM_RISCV_SBI_EXT_MAX,
+};
+
/* Possible states for kvm_riscv_timer */
#define KVM_RISCV_TIMER_STATE_OFF 0
#define KVM_RISCV_TIMER_STATE_ON 1
@@ -118,6 +150,8 @@ enum KVM_RISCV_ISA_EXT_ID {
/* If you need to interpret the index values, here is the key: */
#define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000
#define KVM_REG_RISCV_TYPE_SHIFT 24
+#define KVM_REG_RISCV_SUBTYPE_MASK 0x0000000000FF0000
+#define KVM_REG_RISCV_SUBTYPE_SHIFT 16
/* Config registers are mapped as type 1 */
#define KVM_REG_RISCV_CONFIG (0x01 << KVM_REG_RISCV_TYPE_SHIFT)
@@ -131,8 +165,12 @@ enum KVM_RISCV_ISA_EXT_ID {
/* Control and status registers are mapped as type 3 */
#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_CSR_AIA (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_CSR_REG(name) \
(offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_CSR_AIA_REG(name) \
+ (offsetof(struct kvm_riscv_aia_csr, name) / sizeof(unsigned long))
/* Timer registers are mapped as type 4 */
#define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT)
@@ -152,6 +190,89 @@ enum KVM_RISCV_ISA_EXT_ID {
/* ISA Extension registers are mapped as type 7 */
#define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT)
+/* SBI extension registers are mapped as type 8 */
+#define KVM_REG_RISCV_SBI_EXT (0x08 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_SBI_SINGLE (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_SBI_MULTI_EN (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_SBI_MULTI_DIS (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT)
+#define KVM_REG_RISCV_SBI_MULTI_REG(__ext_id) \
+ ((__ext_id) / __BITS_PER_LONG)
+#define KVM_REG_RISCV_SBI_MULTI_MASK(__ext_id) \
+ (1UL << ((__ext_id) % __BITS_PER_LONG))
+#define KVM_REG_RISCV_SBI_MULTI_REG_LAST \
+ KVM_REG_RISCV_SBI_MULTI_REG(KVM_RISCV_SBI_EXT_MAX - 1)
+
+/* Device Control API: RISC-V AIA */
+#define KVM_DEV_RISCV_APLIC_ALIGN 0x1000
+#define KVM_DEV_RISCV_APLIC_SIZE 0x4000
+#define KVM_DEV_RISCV_APLIC_MAX_HARTS 0x4000
+#define KVM_DEV_RISCV_IMSIC_ALIGN 0x1000
+#define KVM_DEV_RISCV_IMSIC_SIZE 0x1000
+
+#define KVM_DEV_RISCV_AIA_GRP_CONFIG 0
+#define KVM_DEV_RISCV_AIA_CONFIG_MODE 0
+#define KVM_DEV_RISCV_AIA_CONFIG_IDS 1
+#define KVM_DEV_RISCV_AIA_CONFIG_SRCS 2
+#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS 3
+#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT 4
+#define KVM_DEV_RISCV_AIA_CONFIG_HART_BITS 5
+#define KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS 6
+
+/*
+ * Modes of RISC-V AIA device:
+ * 1) EMUL (aka Emulation): Trap-n-emulate IMSIC
+ * 2) HWACCEL (aka HW Acceleration): Virtualize IMSIC using IMSIC guest files
+ * 3) AUTO (aka Automatic): Virtualize IMSIC using IMSIC guest files whenever
+ * available otherwise fallback to trap-n-emulation
+ */
+#define KVM_DEV_RISCV_AIA_MODE_EMUL 0
+#define KVM_DEV_RISCV_AIA_MODE_HWACCEL 1
+#define KVM_DEV_RISCV_AIA_MODE_AUTO 2
+
+#define KVM_DEV_RISCV_AIA_IDS_MIN 63
+#define KVM_DEV_RISCV_AIA_IDS_MAX 2048
+#define KVM_DEV_RISCV_AIA_SRCS_MAX 1024
+#define KVM_DEV_RISCV_AIA_GROUP_BITS_MAX 8
+#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN 24
+#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MAX 56
+#define KVM_DEV_RISCV_AIA_HART_BITS_MAX 16
+#define KVM_DEV_RISCV_AIA_GUEST_BITS_MAX 8
+
+#define KVM_DEV_RISCV_AIA_GRP_ADDR 1
+#define KVM_DEV_RISCV_AIA_ADDR_APLIC 0
+#define KVM_DEV_RISCV_AIA_ADDR_IMSIC(__vcpu) (1 + (__vcpu))
+#define KVM_DEV_RISCV_AIA_ADDR_MAX \
+ (1 + KVM_DEV_RISCV_APLIC_MAX_HARTS)
+
+#define KVM_DEV_RISCV_AIA_GRP_CTRL 2
+#define KVM_DEV_RISCV_AIA_CTRL_INIT 0
+
+/*
+ * The device attribute type contains the memory mapped offset of the
+ * APLIC register (range 0x0000-0x3FFF) and it must be 4-byte aligned.
+ */
+#define KVM_DEV_RISCV_AIA_GRP_APLIC 3
+
+/*
+ * The lower 12-bits of the device attribute type contains the iselect
+ * value of the IMSIC register (range 0x70-0xFF) whereas the higher order
+ * bits contains the VCPU id.
+ */
+#define KVM_DEV_RISCV_AIA_GRP_IMSIC 4
+#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS 12
+#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK \
+ ((1U << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) - 1)
+#define KVM_DEV_RISCV_AIA_IMSIC_MKATTR(__vcpu, __isel) \
+ (((__vcpu) << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) | \
+ ((__isel) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK))
+#define KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(__attr) \
+ ((__attr) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK)
+#define KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(__attr) \
+ ((__attr) >> KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS)
+
+/* One single KVM irqchip, ie. the AIA */
+#define KVM_NR_IRQCHIPS 1
+
#endif
#endif /* __LINUX_KVM_RISCV_H */
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 599de3c6e3..a9a4f5791d 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1434,6 +1434,8 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
KVM_DEV_TYPE_ARM_PV_TIME,
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
+ KVM_DEV_TYPE_RISCV_AIA,
+#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
KVM_DEV_TYPE_MAX,
};
--
2.17.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder
2023-06-21 14:54 ` [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder Yong-Xuan Wang
@ 2023-06-30 10:00 ` Daniel Henrique Barboza
2023-06-30 10:11 ` Cornelia Huck
0 siblings, 1 reply; 20+ messages in thread
From: Daniel Henrique Barboza @ 2023-06-30 10:00 UTC (permalink / raw)
To: Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Michael S. Tsirkin, Cornelia Huck, Paolo Bonzini,
Juan Quintela, Thomas Huth, Peter Xu, kvm
On 6/21/23 11:54, Yong-Xuan Wang wrote:
> Sync-up Linux header to get latest KVM RISC-V headers having AIA support.
>
> Note: This is a placeholder commit and could be replaced when all referenced Linux patchsets are mainlined.
>
> The linux-headers changes are from 2 different patchsets.
> [1] https://lore.kernel.org/lkml/20230404153452.2405681-1-apatel@ventanamicro.com/
> [2] https://www.spinics.net/lists/kernel/msg4791872.html
It looks like Anup sent a PR for [2] for Linux 6.5. IIUC this would be then a 6.5
linux-header update.
In this case I'm not sure whether we can pick this up for QEMU 8.1 (code freeze is
July 10th) since we can't keep a 6.5 placeholder header. I'll let Alistair comment
on that.
Thanks,
Daniel
>
> Currently, patchset 1 is already merged into mainline kernel in v6.4-rc1 and patchset 2 is not.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
> linux-headers/asm-riscv/kvm.h | 123 +++++++++++++++++++++++++++++++++-
> linux-headers/linux/kvm.h | 2 +
> 2 files changed, 124 insertions(+), 1 deletion(-)
>
> diff --git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h
> index 92af6f3f05..a16ca62419 100644
> --- a/linux-headers/asm-riscv/kvm.h
> +++ b/linux-headers/asm-riscv/kvm.h
> @@ -12,8 +12,10 @@
> #ifndef __ASSEMBLY__
>
> #include <linux/types.h>
> +#include <asm/bitsperlong.h>
> #include <asm/ptrace.h>
>
> +#define __KVM_HAVE_IRQ_LINE
> #define __KVM_HAVE_READONLY_MEM
>
> #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
> @@ -64,7 +66,7 @@ struct kvm_riscv_core {
> #define KVM_RISCV_MODE_S 1
> #define KVM_RISCV_MODE_U 0
>
> -/* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
> +/* General CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
> struct kvm_riscv_csr {
> unsigned long sstatus;
> unsigned long sie;
> @@ -78,6 +80,17 @@ struct kvm_riscv_csr {
> unsigned long scounteren;
> };
>
> +/* AIA CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
> +struct kvm_riscv_aia_csr {
> + unsigned long siselect;
> + unsigned long iprio1;
> + unsigned long iprio2;
> + unsigned long sieh;
> + unsigned long siph;
> + unsigned long iprio1h;
> + unsigned long iprio2h;
> +};
> +
> /* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
> struct kvm_riscv_timer {
> __u64 frequency;
> @@ -105,9 +118,28 @@ enum KVM_RISCV_ISA_EXT_ID {
> KVM_RISCV_ISA_EXT_SVINVAL,
> KVM_RISCV_ISA_EXT_ZIHINTPAUSE,
> KVM_RISCV_ISA_EXT_ZICBOM,
> + KVM_RISCV_ISA_EXT_ZBB,
> + KVM_RISCV_ISA_EXT_SSAIA,
> KVM_RISCV_ISA_EXT_MAX,
> };
>
> +/*
> + * SBI extension IDs specific to KVM. This is not the same as the SBI
> + * extension IDs defined by the RISC-V SBI specification.
> + */
> +enum KVM_RISCV_SBI_EXT_ID {
> + KVM_RISCV_SBI_EXT_V01 = 0,
> + KVM_RISCV_SBI_EXT_TIME,
> + KVM_RISCV_SBI_EXT_IPI,
> + KVM_RISCV_SBI_EXT_RFENCE,
> + KVM_RISCV_SBI_EXT_SRST,
> + KVM_RISCV_SBI_EXT_HSM,
> + KVM_RISCV_SBI_EXT_PMU,
> + KVM_RISCV_SBI_EXT_EXPERIMENTAL,
> + KVM_RISCV_SBI_EXT_VENDOR,
> + KVM_RISCV_SBI_EXT_MAX,
> +};
> +
> /* Possible states for kvm_riscv_timer */
> #define KVM_RISCV_TIMER_STATE_OFF 0
> #define KVM_RISCV_TIMER_STATE_ON 1
> @@ -118,6 +150,8 @@ enum KVM_RISCV_ISA_EXT_ID {
> /* If you need to interpret the index values, here is the key: */
> #define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000
> #define KVM_REG_RISCV_TYPE_SHIFT 24
> +#define KVM_REG_RISCV_SUBTYPE_MASK 0x0000000000FF0000
> +#define KVM_REG_RISCV_SUBTYPE_SHIFT 16
>
> /* Config registers are mapped as type 1 */
> #define KVM_REG_RISCV_CONFIG (0x01 << KVM_REG_RISCV_TYPE_SHIFT)
> @@ -131,8 +165,12 @@ enum KVM_RISCV_ISA_EXT_ID {
>
> /* Control and status registers are mapped as type 3 */
> #define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT)
> +#define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
> +#define KVM_REG_RISCV_CSR_AIA (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
> #define KVM_REG_RISCV_CSR_REG(name) \
> (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long))
> +#define KVM_REG_RISCV_CSR_AIA_REG(name) \
> + (offsetof(struct kvm_riscv_aia_csr, name) / sizeof(unsigned long))
>
> /* Timer registers are mapped as type 4 */
> #define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT)
> @@ -152,6 +190,89 @@ enum KVM_RISCV_ISA_EXT_ID {
> /* ISA Extension registers are mapped as type 7 */
> #define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT)
>
> +/* SBI extension registers are mapped as type 8 */
> +#define KVM_REG_RISCV_SBI_EXT (0x08 << KVM_REG_RISCV_TYPE_SHIFT)
> +#define KVM_REG_RISCV_SBI_SINGLE (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
> +#define KVM_REG_RISCV_SBI_MULTI_EN (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
> +#define KVM_REG_RISCV_SBI_MULTI_DIS (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT)
> +#define KVM_REG_RISCV_SBI_MULTI_REG(__ext_id) \
> + ((__ext_id) / __BITS_PER_LONG)
> +#define KVM_REG_RISCV_SBI_MULTI_MASK(__ext_id) \
> + (1UL << ((__ext_id) % __BITS_PER_LONG))
> +#define KVM_REG_RISCV_SBI_MULTI_REG_LAST \
> + KVM_REG_RISCV_SBI_MULTI_REG(KVM_RISCV_SBI_EXT_MAX - 1)
> +
> +/* Device Control API: RISC-V AIA */
> +#define KVM_DEV_RISCV_APLIC_ALIGN 0x1000
> +#define KVM_DEV_RISCV_APLIC_SIZE 0x4000
> +#define KVM_DEV_RISCV_APLIC_MAX_HARTS 0x4000
> +#define KVM_DEV_RISCV_IMSIC_ALIGN 0x1000
> +#define KVM_DEV_RISCV_IMSIC_SIZE 0x1000
> +
> +#define KVM_DEV_RISCV_AIA_GRP_CONFIG 0
> +#define KVM_DEV_RISCV_AIA_CONFIG_MODE 0
> +#define KVM_DEV_RISCV_AIA_CONFIG_IDS 1
> +#define KVM_DEV_RISCV_AIA_CONFIG_SRCS 2
> +#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS 3
> +#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT 4
> +#define KVM_DEV_RISCV_AIA_CONFIG_HART_BITS 5
> +#define KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS 6
> +
> +/*
> + * Modes of RISC-V AIA device:
> + * 1) EMUL (aka Emulation): Trap-n-emulate IMSIC
> + * 2) HWACCEL (aka HW Acceleration): Virtualize IMSIC using IMSIC guest files
> + * 3) AUTO (aka Automatic): Virtualize IMSIC using IMSIC guest files whenever
> + * available otherwise fallback to trap-n-emulation
> + */
> +#define KVM_DEV_RISCV_AIA_MODE_EMUL 0
> +#define KVM_DEV_RISCV_AIA_MODE_HWACCEL 1
> +#define KVM_DEV_RISCV_AIA_MODE_AUTO 2
> +
> +#define KVM_DEV_RISCV_AIA_IDS_MIN 63
> +#define KVM_DEV_RISCV_AIA_IDS_MAX 2048
> +#define KVM_DEV_RISCV_AIA_SRCS_MAX 1024
> +#define KVM_DEV_RISCV_AIA_GROUP_BITS_MAX 8
> +#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN 24
> +#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MAX 56
> +#define KVM_DEV_RISCV_AIA_HART_BITS_MAX 16
> +#define KVM_DEV_RISCV_AIA_GUEST_BITS_MAX 8
> +
> +#define KVM_DEV_RISCV_AIA_GRP_ADDR 1
> +#define KVM_DEV_RISCV_AIA_ADDR_APLIC 0
> +#define KVM_DEV_RISCV_AIA_ADDR_IMSIC(__vcpu) (1 + (__vcpu))
> +#define KVM_DEV_RISCV_AIA_ADDR_MAX \
> + (1 + KVM_DEV_RISCV_APLIC_MAX_HARTS)
> +
> +#define KVM_DEV_RISCV_AIA_GRP_CTRL 2
> +#define KVM_DEV_RISCV_AIA_CTRL_INIT 0
> +
> +/*
> + * The device attribute type contains the memory mapped offset of the
> + * APLIC register (range 0x0000-0x3FFF) and it must be 4-byte aligned.
> + */
> +#define KVM_DEV_RISCV_AIA_GRP_APLIC 3
> +
> +/*
> + * The lower 12-bits of the device attribute type contains the iselect
> + * value of the IMSIC register (range 0x70-0xFF) whereas the higher order
> + * bits contains the VCPU id.
> + */
> +#define KVM_DEV_RISCV_AIA_GRP_IMSIC 4
> +#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS 12
> +#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK \
> + ((1U << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) - 1)
> +#define KVM_DEV_RISCV_AIA_IMSIC_MKATTR(__vcpu, __isel) \
> + (((__vcpu) << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) | \
> + ((__isel) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK))
> +#define KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(__attr) \
> + ((__attr) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK)
> +#define KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(__attr) \
> + ((__attr) >> KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS)
> +
> +/* One single KVM irqchip, ie. the AIA */
> +#define KVM_NR_IRQCHIPS 1
> +
> #endif
>
> #endif /* __LINUX_KVM_RISCV_H */
> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
> index 599de3c6e3..a9a4f5791d 100644
> --- a/linux-headers/linux/kvm.h
> +++ b/linux-headers/linux/kvm.h
> @@ -1434,6 +1434,8 @@ enum kvm_device_type {
> #define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
> KVM_DEV_TYPE_ARM_PV_TIME,
> #define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
> + KVM_DEV_TYPE_RISCV_AIA,
> +#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
> KVM_DEV_TYPE_MAX,
> };
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder
2023-06-30 10:00 ` Daniel Henrique Barboza
@ 2023-06-30 10:11 ` Cornelia Huck
0 siblings, 0 replies; 20+ messages in thread
From: Cornelia Huck @ 2023-06-30 10:11 UTC (permalink / raw)
To: Daniel Henrique Barboza, Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Michael S. Tsirkin, Paolo Bonzini, Juan Quintela,
Thomas Huth, Peter Xu, kvm
On Fri, Jun 30 2023, Daniel Henrique Barboza <dbarboza@ventanamicro.com> wrote:
> On 6/21/23 11:54, Yong-Xuan Wang wrote:
>> Sync-up Linux header to get latest KVM RISC-V headers having AIA support.
>>
>> Note: This is a placeholder commit and could be replaced when all referenced Linux patchsets are mainlined.
>>
>> The linux-headers changes are from 2 different patchsets.
>> [1] https://lore.kernel.org/lkml/20230404153452.2405681-1-apatel@ventanamicro.com/
>> [2] https://www.spinics.net/lists/kernel/msg4791872.html
>
>
> It looks like Anup sent a PR for [2] for Linux 6.5. IIUC this would be then a 6.5
> linux-header update.
>
> In this case I'm not sure whether we can pick this up for QEMU 8.1 (code freeze is
> July 10th) since we can't keep a 6.5 placeholder header. I'll let Alistair comment
> on that.
My crystal ball says that we'll have Linux 6.5-rc1 on July 9th, which
is... probably too late, given the need for a repost with a proper
headers update etc. (I'd generally prefer not to do the headers update
on a random middle-of-the-merge-window commit...)
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
2023-06-21 14:54 ` [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-06-30 9:39 ` Daniel Henrique Barboza
2023-07-04 14:35 ` Andrew Jones
2023-06-21 14:54 ` [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support Yong-Xuan Wang
` (4 subsequent siblings)
6 siblings, 2 replies; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei
Remove M mode AIA devices when using KVM acceleration
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
---
hw/riscv/virt.c | 207 +++++++++++++++++++++++++-----------------------
1 file changed, 108 insertions(+), 99 deletions(-)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 245c7b97b2..4a1d29a741 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -531,52 +531,54 @@ static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
imsic_regs = g_new0(uint32_t, socket_count * 4);
- /* M-level IMSIC node */
- for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
- imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
- imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
- }
- imsic_max_hart_per_socket = 0;
- for (socket = 0; socket < socket_count; socket++) {
- imsic_addr = memmap[VIRT_IMSIC_M].base +
- socket * VIRT_IMSIC_GROUP_MAX_SIZE;
- imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
- imsic_regs[socket * 4 + 0] = 0;
- imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
- imsic_regs[socket * 4 + 2] = 0;
- imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
- if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
- imsic_max_hart_per_socket = s->soc[socket].num_harts;
+ if (!kvm_enabled()) {
+ /* M-level IMSIC node */
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+ imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+ imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
}
- }
- imsic_name = g_strdup_printf("/soc/imsics@%lx",
- (unsigned long)memmap[VIRT_IMSIC_M].base);
- qemu_fdt_add_subnode(ms->fdt, imsic_name);
- qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
- "riscv,imsics");
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
- FDT_IMSIC_INT_CELLS);
- qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
- NULL, 0);
- qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
- NULL, 0);
- qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
- imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
- qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
- socket_count * sizeof(uint32_t) * 4);
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
- VIRT_IRQCHIP_NUM_MSIS);
- if (socket_count > 1) {
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
- imsic_num_bits(imsic_max_hart_per_socket));
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
- imsic_num_bits(socket_count));
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
- IMSIC_MMIO_GROUP_MIN_SHIFT);
- }
- qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
+ imsic_max_hart_per_socket = 0;
+ for (socket = 0; socket < socket_count; socket++) {
+ imsic_addr = memmap[VIRT_IMSIC_M].base +
+ socket * VIRT_IMSIC_GROUP_MAX_SIZE;
+ imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
+ imsic_regs[socket * 4 + 0] = 0;
+ imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
+ imsic_regs[socket * 4 + 2] = 0;
+ imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
+ if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
+ imsic_max_hart_per_socket = s->soc[socket].num_harts;
+ }
+ }
+ imsic_name = g_strdup_printf("/soc/imsics@%lx",
+ (unsigned long)memmap[VIRT_IMSIC_M].base);
+ qemu_fdt_add_subnode(ms->fdt, imsic_name);
+ qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
+ "riscv,imsics");
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
+ FDT_IMSIC_INT_CELLS);
+ qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
+ NULL, 0);
+ qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
+ NULL, 0);
+ qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
+ imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
+ qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
+ socket_count * sizeof(uint32_t) * 4);
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
+ VIRT_IRQCHIP_NUM_MSIS);
+ if (socket_count > 1) {
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
+ imsic_num_bits(imsic_max_hart_per_socket));
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
+ imsic_num_bits(socket_count));
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name,
+ "riscv,group-index-shift", IMSIC_MMIO_GROUP_MIN_SHIFT);
+ }
+ qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
- g_free(imsic_name);
+ g_free(imsic_name);
+ }
/* S-level IMSIC node */
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
@@ -653,37 +655,40 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
aplic_s_phandle = (*phandle)++;
aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
- /* M-level APLIC node */
- for (cpu = 0; cpu < s->soc[socket].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);
- }
- aplic_addr = memmap[VIRT_APLIC_M].base +
- (memmap[VIRT_APLIC_M].size * socket);
- aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
- qemu_fdt_add_subnode(ms->fdt, aplic_name);
- qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
- qemu_fdt_setprop_cell(ms->fdt, aplic_name,
- "#interrupt-cells", FDT_APLIC_INT_CELLS);
- qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
- if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
- qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
- aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
- } else {
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
- msi_m_phandle);
+ if (!kvm_enabled()) {
+ /* M-level APLIC node */
+ for (cpu = 0; cpu < s->soc[socket].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);
+ }
+ aplic_addr = memmap[VIRT_APLIC_M].base +
+ (memmap[VIRT_APLIC_M].size * socket);
+ aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
+ qemu_fdt_add_subnode(ms->fdt, aplic_name);
+ qemu_fdt_setprop_string(ms->fdt, aplic_name,
+ "compatible", "riscv,aplic");
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name,
+ "#interrupt-cells", FDT_APLIC_INT_CELLS);
+ qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
+ if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
+ qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
+ aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
+ } else {
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
+ msi_m_phandle);
+ }
+ qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
+ 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
+ VIRT_IRQCHIP_NUM_SOURCES);
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
+ aplic_s_phandle);
+ qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
+ aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
+ riscv_socket_fdt_write_id(ms, aplic_name, socket);
+ qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
+ g_free(aplic_name);
}
- qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
- 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
- VIRT_IRQCHIP_NUM_SOURCES);
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
- aplic_s_phandle);
- qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
- aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
- riscv_socket_fdt_write_id(ms, aplic_name, socket);
- qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
- g_free(aplic_name);
/* S-level APLIC node */
for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
@@ -1162,16 +1167,20 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
int i;
hwaddr addr;
uint32_t guest_bits;
- DeviceState *aplic_m;
+ DeviceState *aplic_s = NULL;
+ DeviceState *aplic_m = NULL;
bool msimode = (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) ? true : false;
if (msimode) {
- /* Per-socket M-level IMSICs */
- addr = memmap[VIRT_IMSIC_M].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
- for (i = 0; i < hart_count; i++) {
- riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
- base_hartid + i, true, 1,
- VIRT_IRQCHIP_NUM_MSIS);
+ if (!kvm_enabled()) {
+ /* Per-socket M-level IMSICs */
+ addr = memmap[VIRT_IMSIC_M].base +
+ socket * VIRT_IMSIC_GROUP_MAX_SIZE;
+ for (i = 0; i < hart_count; i++) {
+ riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
+ base_hartid + i, true, 1,
+ VIRT_IRQCHIP_NUM_MSIS);
+ }
}
/* Per-socket S-level IMSICs */
@@ -1184,29 +1193,29 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
}
}
- /* Per-socket M-level APLIC */
- aplic_m = riscv_aplic_create(
- memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
- memmap[VIRT_APLIC_M].size,
+ if (!kvm_enabled()) {
+ /* Per-socket M-level APLIC */
+ aplic_m = riscv_aplic_create(
+ memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
+ memmap[VIRT_APLIC_M].size,
+ (msimode) ? 0 : base_hartid,
+ (msimode) ? 0 : hart_count,
+ VIRT_IRQCHIP_NUM_SOURCES,
+ VIRT_IRQCHIP_NUM_PRIO_BITS,
+ msimode, true, NULL);
+ }
+
+ /* Per-socket S-level APLIC */
+ aplic_s = riscv_aplic_create(
+ memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
+ memmap[VIRT_APLIC_S].size,
(msimode) ? 0 : base_hartid,
(msimode) ? 0 : hart_count,
VIRT_IRQCHIP_NUM_SOURCES,
VIRT_IRQCHIP_NUM_PRIO_BITS,
- msimode, true, NULL);
-
- if (aplic_m) {
- /* Per-socket S-level APLIC */
- riscv_aplic_create(
- memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
- memmap[VIRT_APLIC_S].size,
- (msimode) ? 0 : base_hartid,
- (msimode) ? 0 : hart_count,
- VIRT_IRQCHIP_NUM_SOURCES,
- VIRT_IRQCHIP_NUM_PRIO_BITS,
- msimode, false, aplic_m);
- }
+ msimode, false, aplic_m);
- return aplic_m;
+ return kvm_enabled() ? aplic_s : aplic_m;
}
static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
--
2.17.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled
2023-06-21 14:54 ` [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled Yong-Xuan Wang
@ 2023-06-30 9:39 ` Daniel Henrique Barboza
2023-07-04 14:35 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Daniel Henrique Barboza @ 2023-06-30 9:39 UTC (permalink / raw)
To: Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
Liu Zhiwei
On 6/21/23 11:54, Yong-Xuan Wang wrote:
> Remove M mode AIA devices when using KVM acceleration
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> hw/riscv/virt.c | 207 +++++++++++++++++++++++++-----------------------
> 1 file changed, 108 insertions(+), 99 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 245c7b97b2..4a1d29a741 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -531,52 +531,54 @@ static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
> imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
> imsic_regs = g_new0(uint32_t, socket_count * 4);
>
> - /* M-level IMSIC node */
> - for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> - imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
> - imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
> - }
> - imsic_max_hart_per_socket = 0;
> - for (socket = 0; socket < socket_count; socket++) {
> - imsic_addr = memmap[VIRT_IMSIC_M].base +
> - socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> - imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
> - imsic_regs[socket * 4 + 0] = 0;
> - imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
> - imsic_regs[socket * 4 + 2] = 0;
> - imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
> - if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
> - imsic_max_hart_per_socket = s->soc[socket].num_harts;
> + if (!kvm_enabled()) {
> + /* M-level IMSIC node */
> + for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> + imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
> + imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
> }
> - }
> - imsic_name = g_strdup_printf("/soc/imsics@%lx",
> - (unsigned long)memmap[VIRT_IMSIC_M].base);
> - qemu_fdt_add_subnode(ms->fdt, imsic_name);
> - qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
> - "riscv,imsics");
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
> - FDT_IMSIC_INT_CELLS);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
> - NULL, 0);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
> - NULL, 0);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
> - imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
> - socket_count * sizeof(uint32_t) * 4);
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
> - VIRT_IRQCHIP_NUM_MSIS);
> - if (socket_count > 1) {
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
> - imsic_num_bits(imsic_max_hart_per_socket));
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
> - imsic_num_bits(socket_count));
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
> - IMSIC_MMIO_GROUP_MIN_SHIFT);
> - }
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
> + imsic_max_hart_per_socket = 0;
> + for (socket = 0; socket < socket_count; socket++) {
> + imsic_addr = memmap[VIRT_IMSIC_M].base +
> + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> + imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
> + imsic_regs[socket * 4 + 0] = 0;
> + imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
> + imsic_regs[socket * 4 + 2] = 0;
> + imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
> + if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
> + imsic_max_hart_per_socket = s->soc[socket].num_harts;
> + }
> + }
> + imsic_name = g_strdup_printf("/soc/imsics@%lx",
> + (unsigned long)memmap[VIRT_IMSIC_M].base);
> + qemu_fdt_add_subnode(ms->fdt, imsic_name);
> + qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
> + "riscv,imsics");
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
> + FDT_IMSIC_INT_CELLS);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
> + NULL, 0);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
> + NULL, 0);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
> + imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
> + socket_count * sizeof(uint32_t) * 4);
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
> + VIRT_IRQCHIP_NUM_MSIS);
> + if (socket_count > 1) {
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
> + imsic_num_bits(imsic_max_hart_per_socket));
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
> + imsic_num_bits(socket_count));
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name,
> + "riscv,group-index-shift", IMSIC_MMIO_GROUP_MIN_SHIFT);
> + }
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
>
> - g_free(imsic_name);
> + g_free(imsic_name);
> + }
>
> /* S-level IMSIC node */
> for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> @@ -653,37 +655,40 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
> aplic_s_phandle = (*phandle)++;
> aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
>
> - /* M-level APLIC node */
> - for (cpu = 0; cpu < s->soc[socket].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);
> - }
> - aplic_addr = memmap[VIRT_APLIC_M].base +
> - (memmap[VIRT_APLIC_M].size * socket);
> - aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
> - qemu_fdt_add_subnode(ms->fdt, aplic_name);
> - qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name,
> - "#interrupt-cells", FDT_APLIC_INT_CELLS);
> - qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
> - if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
> - qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
> - aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
> - } else {
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
> - msi_m_phandle);
> + if (!kvm_enabled()) {
> + /* M-level APLIC node */
> + for (cpu = 0; cpu < s->soc[socket].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);
> + }
> + aplic_addr = memmap[VIRT_APLIC_M].base +
> + (memmap[VIRT_APLIC_M].size * socket);
> + aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
> + qemu_fdt_add_subnode(ms->fdt, aplic_name);
> + qemu_fdt_setprop_string(ms->fdt, aplic_name,
> + "compatible", "riscv,aplic");
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name,
> + "#interrupt-cells", FDT_APLIC_INT_CELLS);
> + qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
> + if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
> + qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
> + aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
> + } else {
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
> + msi_m_phandle);
> + }
> + qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
> + 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
> + VIRT_IRQCHIP_NUM_SOURCES);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
> + aplic_s_phandle);
> + qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> + aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
> + riscv_socket_fdt_write_id(ms, aplic_name, socket);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
> + g_free(aplic_name);
> }
> - qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
> - 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
> - VIRT_IRQCHIP_NUM_SOURCES);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
> - aplic_s_phandle);
> - qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> - aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
> - riscv_socket_fdt_write_id(ms, aplic_name, socket);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
> - g_free(aplic_name);
>
> /* S-level APLIC node */
> for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
> @@ -1162,16 +1167,20 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
> int i;
> hwaddr addr;
> uint32_t guest_bits;
> - DeviceState *aplic_m;
> + DeviceState *aplic_s = NULL;
> + DeviceState *aplic_m = NULL;
> bool msimode = (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) ? true : false;
>
> if (msimode) {
> - /* Per-socket M-level IMSICs */
> - addr = memmap[VIRT_IMSIC_M].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> - for (i = 0; i < hart_count; i++) {
> - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
> - base_hartid + i, true, 1,
> - VIRT_IRQCHIP_NUM_MSIS);
> + if (!kvm_enabled()) {
> + /* Per-socket M-level IMSICs */
> + addr = memmap[VIRT_IMSIC_M].base +
> + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> + for (i = 0; i < hart_count; i++) {
> + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
> + base_hartid + i, true, 1,
> + VIRT_IRQCHIP_NUM_MSIS);
> + }
> }
>
> /* Per-socket S-level IMSICs */
> @@ -1184,29 +1193,29 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
> }
> }
>
> - /* Per-socket M-level APLIC */
> - aplic_m = riscv_aplic_create(
> - memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
> - memmap[VIRT_APLIC_M].size,
> + if (!kvm_enabled()) {
> + /* Per-socket M-level APLIC */
> + aplic_m = riscv_aplic_create(
> + memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
> + memmap[VIRT_APLIC_M].size,
> + (msimode) ? 0 : base_hartid,
> + (msimode) ? 0 : hart_count,
> + VIRT_IRQCHIP_NUM_SOURCES,
> + VIRT_IRQCHIP_NUM_PRIO_BITS,
> + msimode, true, NULL);
> + }
> +
> + /* Per-socket S-level APLIC */
> + aplic_s = riscv_aplic_create(
> + memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
> + memmap[VIRT_APLIC_S].size,
> (msimode) ? 0 : base_hartid,
> (msimode) ? 0 : hart_count,
> VIRT_IRQCHIP_NUM_SOURCES,
> VIRT_IRQCHIP_NUM_PRIO_BITS,
> - msimode, true, NULL);
> -
> - if (aplic_m) {
> - /* Per-socket S-level APLIC */
> - riscv_aplic_create(
> - memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
> - memmap[VIRT_APLIC_S].size,
> - (msimode) ? 0 : base_hartid,
> - (msimode) ? 0 : hart_count,
> - VIRT_IRQCHIP_NUM_SOURCES,
> - VIRT_IRQCHIP_NUM_PRIO_BITS,
> - msimode, false, aplic_m);
> - }
> + msimode, false, aplic_m);
>
> - return aplic_m;
> + return kvm_enabled() ? aplic_s : aplic_m;
> }
>
> static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled
2023-06-21 14:54 ` [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled Yong-Xuan Wang
2023-06-30 9:39 ` Daniel Henrique Barboza
@ 2023-07-04 14:35 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Andrew Jones @ 2023-07-04 14:35 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei
On Wed, Jun 21, 2023 at 02:54:52PM +0000, Yong-Xuan Wang wrote:
> Remove M mode AIA devices when using KVM acceleration
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
> hw/riscv/virt.c | 207 +++++++++++++++++++++++++-----------------------
> 1 file changed, 108 insertions(+), 99 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 245c7b97b2..4a1d29a741 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -531,52 +531,54 @@ static void create_fdt_imsic(RISCVVirtState *s, const MemMapEntry *memmap,
> imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
> imsic_regs = g_new0(uint32_t, socket_count * 4);
>
> - /* M-level IMSIC node */
> - for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> - imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
> - imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
> - }
> - imsic_max_hart_per_socket = 0;
> - for (socket = 0; socket < socket_count; socket++) {
> - imsic_addr = memmap[VIRT_IMSIC_M].base +
> - socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> - imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
> - imsic_regs[socket * 4 + 0] = 0;
> - imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
> - imsic_regs[socket * 4 + 2] = 0;
> - imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
> - if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
> - imsic_max_hart_per_socket = s->soc[socket].num_harts;
> + if (!kvm_enabled()) {
> + /* M-level IMSIC node */
> + for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> + imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
> + imsic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_EXT);
> }
> - }
> - imsic_name = g_strdup_printf("/soc/imsics@%lx",
> - (unsigned long)memmap[VIRT_IMSIC_M].base);
> - qemu_fdt_add_subnode(ms->fdt, imsic_name);
> - qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
> - "riscv,imsics");
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
> - FDT_IMSIC_INT_CELLS);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
> - NULL, 0);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
> - NULL, 0);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
> - imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
> - qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
> - socket_count * sizeof(uint32_t) * 4);
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
> - VIRT_IRQCHIP_NUM_MSIS);
> - if (socket_count > 1) {
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
> - imsic_num_bits(imsic_max_hart_per_socket));
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
> - imsic_num_bits(socket_count));
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-shift",
> - IMSIC_MMIO_GROUP_MIN_SHIFT);
> - }
> - qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
> + imsic_max_hart_per_socket = 0;
> + for (socket = 0; socket < socket_count; socket++) {
> + imsic_addr = memmap[VIRT_IMSIC_M].base +
> + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> + imsic_size = IMSIC_HART_SIZE(0) * s->soc[socket].num_harts;
> + imsic_regs[socket * 4 + 0] = 0;
> + imsic_regs[socket * 4 + 1] = cpu_to_be32(imsic_addr);
> + imsic_regs[socket * 4 + 2] = 0;
> + imsic_regs[socket * 4 + 3] = cpu_to_be32(imsic_size);
> + if (imsic_max_hart_per_socket < s->soc[socket].num_harts) {
> + imsic_max_hart_per_socket = s->soc[socket].num_harts;
> + }
> + }
> + imsic_name = g_strdup_printf("/soc/imsics@%lx",
> + (unsigned long)memmap[VIRT_IMSIC_M].base);
> + qemu_fdt_add_subnode(ms->fdt, imsic_name);
> + qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible",
> + "riscv,imsics");
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
> + FDT_IMSIC_INT_CELLS);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller",
> + NULL, 0);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller",
> + NULL, 0);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
> + imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
> + qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
> + socket_count * sizeof(uint32_t) * 4);
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,num-ids",
> + VIRT_IRQCHIP_NUM_MSIS);
> + if (socket_count > 1) {
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,hart-index-bits",
> + imsic_num_bits(imsic_max_hart_per_socket));
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "riscv,group-index-bits",
> + imsic_num_bits(socket_count));
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name,
> + "riscv,group-index-shift", IMSIC_MMIO_GROUP_MIN_SHIFT);
> + }
> + qemu_fdt_setprop_cell(ms->fdt, imsic_name, "phandle", *msi_m_phandle);
>
> - g_free(imsic_name);
> + g_free(imsic_name);
> + }
The create_fdt_imsic() code for M-mode and S-mode is nearly identical. I
suggest creating a helper function where the differences have been
parameterized so we can write this something like
void create_fdt_imsic(...)
{
if (!kvm_enabled()) {
create_fdt_one_imsic(VIRT_IMSIC_M, 0, ...);
}
create_fdt_one_imsic(VIRT_IMSIC_S, imsic_num_bits(s->aia_guests + 1), ...);
}
>
> /* S-level IMSIC node */
> for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
> @@ -653,37 +655,40 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
> aplic_s_phandle = (*phandle)++;
> aplic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
>
> - /* M-level APLIC node */
> - for (cpu = 0; cpu < s->soc[socket].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);
> - }
> - aplic_addr = memmap[VIRT_APLIC_M].base +
> - (memmap[VIRT_APLIC_M].size * socket);
> - aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
> - qemu_fdt_add_subnode(ms->fdt, aplic_name);
> - qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name,
> - "#interrupt-cells", FDT_APLIC_INT_CELLS);
> - qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
> - if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
> - qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
> - aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
> - } else {
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
> - msi_m_phandle);
> + if (!kvm_enabled()) {
> + /* M-level APLIC node */
> + for (cpu = 0; cpu < s->soc[socket].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);
> + }
> + aplic_addr = memmap[VIRT_APLIC_M].base +
> + (memmap[VIRT_APLIC_M].size * socket);
> + aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
> + qemu_fdt_add_subnode(ms->fdt, aplic_name);
> + qemu_fdt_setprop_string(ms->fdt, aplic_name,
> + "compatible", "riscv,aplic");
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name,
> + "#interrupt-cells", FDT_APLIC_INT_CELLS);
> + qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
> + if (s->aia_type == VIRT_AIA_TYPE_APLIC) {
> + qemu_fdt_setprop(ms->fdt, aplic_name, "interrupts-extended",
> + aplic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 2);
> + } else {
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "msi-parent",
> + msi_m_phandle);
> + }
> + qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
> + 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
> + VIRT_IRQCHIP_NUM_SOURCES);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
> + aplic_s_phandle);
> + qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> + aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
> + riscv_socket_fdt_write_id(ms, aplic_name, socket);
> + qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
> + g_free(aplic_name);
> }
> - qemu_fdt_setprop_cells(ms->fdt, aplic_name, "reg",
> - 0x0, aplic_addr, 0x0, memmap[VIRT_APLIC_M].size);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,num-sources",
> - VIRT_IRQCHIP_NUM_SOURCES);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
> - aplic_s_phandle);
> - qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> - aplic_s_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES);
> - riscv_socket_fdt_write_id(ms, aplic_name, socket);
> - qemu_fdt_setprop_cell(ms->fdt, aplic_name, "phandle", aplic_m_phandle);
> - g_free(aplic_name);
I think it should be possible to parameterize an aplic helper as well.
>
> /* S-level APLIC node */
> for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
> @@ -1162,16 +1167,20 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
> int i;
> hwaddr addr;
> uint32_t guest_bits;
> - DeviceState *aplic_m;
> + DeviceState *aplic_s = NULL;
> + DeviceState *aplic_m = NULL;
> bool msimode = (aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) ? true : false;
Not introduced with this patch, but we should drop the unnecessary () and
'? true : false' on this line.
>
> if (msimode) {
> - /* Per-socket M-level IMSICs */
> - addr = memmap[VIRT_IMSIC_M].base + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> - for (i = 0; i < hart_count; i++) {
> - riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
> - base_hartid + i, true, 1,
> - VIRT_IRQCHIP_NUM_MSIS);
> + if (!kvm_enabled()) {
> + /* Per-socket M-level IMSICs */
> + addr = memmap[VIRT_IMSIC_M].base +
> + socket * VIRT_IMSIC_GROUP_MAX_SIZE;
> + for (i = 0; i < hart_count; i++) {
> + riscv_imsic_create(addr + i * IMSIC_HART_SIZE(0),
> + base_hartid + i, true, 1,
> + VIRT_IRQCHIP_NUM_MSIS);
> + }
> }
>
> /* Per-socket S-level IMSICs */
> @@ -1184,29 +1193,29 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
> }
> }
>
> - /* Per-socket M-level APLIC */
> - aplic_m = riscv_aplic_create(
> - memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
> - memmap[VIRT_APLIC_M].size,
> + if (!kvm_enabled()) {
> + /* Per-socket M-level APLIC */
> + aplic_m = riscv_aplic_create(
> + memmap[VIRT_APLIC_M].base + socket * memmap[VIRT_APLIC_M].size,
> + memmap[VIRT_APLIC_M].size,
> + (msimode) ? 0 : base_hartid,
> + (msimode) ? 0 : hart_count,
> + VIRT_IRQCHIP_NUM_SOURCES,
> + VIRT_IRQCHIP_NUM_PRIO_BITS,
> + msimode, true, NULL);
> + }
> +
> + /* Per-socket S-level APLIC */
> + aplic_s = riscv_aplic_create(
> + memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
> + memmap[VIRT_APLIC_S].size,
> (msimode) ? 0 : base_hartid,
> (msimode) ? 0 : hart_count,
> VIRT_IRQCHIP_NUM_SOURCES,
> VIRT_IRQCHIP_NUM_PRIO_BITS,
> - msimode, true, NULL);
> -
> - if (aplic_m) {
> - /* Per-socket S-level APLIC */
> - riscv_aplic_create(
> - memmap[VIRT_APLIC_S].base + socket * memmap[VIRT_APLIC_S].size,
> - memmap[VIRT_APLIC_S].size,
> - (msimode) ? 0 : base_hartid,
> - (msimode) ? 0 : hart_count,
> - VIRT_IRQCHIP_NUM_SOURCES,
> - VIRT_IRQCHIP_NUM_PRIO_BITS,
> - msimode, false, aplic_m);
> - }
> + msimode, false, aplic_m);
>
> - return aplic_m;
> + return kvm_enabled() ? aplic_s : aplic_m;
> }
>
> static void create_platform_bus(RISCVVirtState *s, DeviceState *irqchip)
> --
> 2.17.1
>
>
Thanks,
drew
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
2023-06-21 14:54 ` [PATCH v4 1/6] update-linux-headers: sync-up header with Linux for KVM AIA support placeholder Yong-Xuan Wang
2023-06-21 14:54 ` [PATCH v4 2/6] target/riscv: support the AIA device emulation with KVM enabled Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-07-04 14:46 ` Andrew Jones
2023-06-21 14:54 ` [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip Yong-Xuan Wang
` (3 subsequent siblings)
6 siblings, 1 reply; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei, Paolo Bonzini,
kvm
We check the in-kernel irqchip support when using KVM acceleration.
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
target/riscv/kvm.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index 0f932a5b96..eb469e8ca5 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -433,7 +433,18 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
int kvm_arch_irqchip_create(KVMState *s)
{
- return 0;
+ if (kvm_kernel_irqchip_split()) {
+ error_report("-machine kernel_irqchip=split is not supported "
+ "on RISC-V.");
+ exit(1);
+ }
+
+ /*
+ * If we can create the VAIA using the newer device control API, we
+ * let the device do this when it initializes itself, otherwise we
+ * fall back to the old API
+ */
+ return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
}
int kvm_arch_process_async_events(CPUState *cs)
--
2.17.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support
2023-06-21 14:54 ` [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support Yong-Xuan Wang
@ 2023-07-04 14:46 ` Andrew Jones
0 siblings, 0 replies; 20+ messages in thread
From: Andrew Jones @ 2023-07-04 14:46 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei, Paolo Bonzini,
kvm
On Wed, Jun 21, 2023 at 02:54:53PM +0000, Yong-Xuan Wang wrote:
> We check the in-kernel irqchip support when using KVM acceleration.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
> target/riscv/kvm.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index 0f932a5b96..eb469e8ca5 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -433,7 +433,18 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>
> int kvm_arch_irqchip_create(KVMState *s)
> {
> - return 0;
> + if (kvm_kernel_irqchip_split()) {
> + error_report("-machine kernel_irqchip=split is not supported "
> + "on RISC-V.");
It's best to not split error messages across lines. We can go to 90 chars
before checkpatch considers it an error, and I'd still consider it worse
to split an error message than to ignore checkpatch and exceed 90 chars.
> + exit(1);
> + }
> +
> + /*
> + * If we can create the VAIA using the newer device control API, we
> + * let the device do this when it initializes itself, otherwise we
> + * fall back to the old API
This comment appears lifted from arm, but the "fall back to the old API"
doesn't apply to riscv since riscv doesn't support KVM_CREATE_IRQCHIP.
> + */
> + return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
> }
>
> int kvm_arch_process_async_events(CPUState *cs)
> --
> 2.17.1
>
>
Thanks,
drew
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
` (2 preceding siblings ...)
2023-06-21 14:54 ` [PATCH v4 3/6] target/riscv: check the in-kernel irqchip support Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-06-30 9:40 ` Daniel Henrique Barboza
2023-07-04 15:12 ` Andrew Jones
2023-06-21 14:54 ` [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA Yong-Xuan Wang
` (2 subsequent siblings)
6 siblings, 2 replies; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei, Paolo Bonzini,
kvm
implement a function to create an KVM AIA chip
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
---
target/riscv/kvm.c | 163 +++++++++++++++++++++++++++++++++++++++
target/riscv/kvm_riscv.h | 6 ++
2 files changed, 169 insertions(+)
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
index eb469e8ca5..3dd8467031 100644
--- a/target/riscv/kvm.c
+++ b/target/riscv/kvm.c
@@ -34,6 +34,7 @@
#include "exec/address-spaces.h"
#include "hw/boards.h"
#include "hw/irq.h"
+#include "hw/intc/riscv_imsic.h"
#include "qemu/log.h"
#include "hw/loader.h"
#include "kvm_riscv.h"
@@ -41,6 +42,7 @@
#include "chardev/char-fe.h"
#include "migration/migration.h"
#include "sysemu/runstate.h"
+#include "hw/riscv/numa.h"
static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
uint64_t idx)
@@ -548,3 +550,164 @@ bool kvm_arch_cpu_check_are_resettable(void)
void kvm_arch_accel_class_init(ObjectClass *oc)
{
}
+
+char *kvm_aia_mode_str(uint64_t aia_mode)
+{
+ const char *val;
+
+ switch (aia_mode) {
+ case KVM_DEV_RISCV_AIA_MODE_EMUL:
+ val = "emul";
+ break;
+ case KVM_DEV_RISCV_AIA_MODE_HWACCEL:
+ val = "hwaccel";
+ break;
+ case KVM_DEV_RISCV_AIA_MODE_AUTO:
+ default:
+ val = "auto";
+ break;
+ };
+
+ return g_strdup(val);
+}
+
+void kvm_riscv_aia_create(MachineState *machine,
+ uint64_t aia_mode, uint64_t group_shift,
+ uint64_t aia_irq_num, uint64_t aia_msi_num,
+ uint64_t aplic_base, uint64_t imsic_base,
+ uint64_t guest_num)
+{
+ int ret, i;
+ int aia_fd = -1;
+ uint64_t default_aia_mode;
+ uint64_t socket_count = riscv_socket_count(machine);
+ uint64_t max_hart_per_socket = 0;
+ uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
+ uint64_t socket_bits, hart_bits, guest_bits;
+
+ aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
+
+ if (aia_fd < 0) {
+ error_report("Unable to create in-kernel irqchip");
+ exit(1);
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_MODE,
+ &default_aia_mode, false, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to get current KVM AIA mode");
+ exit(1);
+ }
+ qemu_log("KVM AIA: default mode is %s\n",
+ kvm_aia_mode_str(default_aia_mode));
+
+ if (default_aia_mode != aia_mode) {
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_MODE,
+ &aia_mode, true, NULL);
+ if (ret < 0)
+ warn_report("KVM AIA: fail to set KVM AIA mode");
+ else
+ qemu_log("KVM AIA: set current mode to %s\n",
+ kvm_aia_mode_str(aia_mode));
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_SRCS,
+ &aia_irq_num, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set number of input irq lines");
+ exit(1);
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_IDS,
+ &aia_msi_num, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set number of msi");
+ exit(1);
+ }
+
+ socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1;
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
+ &socket_bits, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set group_bits");
+ exit(1);
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT,
+ &group_shift, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set group_shift");
+ exit(1);
+ }
+
+ guest_bits = guest_num == 0 ? 0 :
+ find_last_bit(&guest_num, BITS_PER_LONG) + 1;
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS,
+ &guest_bits, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set guest_bits");
+ exit(1);
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
+ KVM_DEV_RISCV_AIA_ADDR_APLIC,
+ &aplic_base, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set the base address of APLIC");
+ exit(1);
+ }
+
+ for (socket = 0; socket < socket_count; socket++) {
+ socket_imsic_base = imsic_base + socket * (1U << group_shift);
+ hart_count = riscv_socket_hart_count(machine, socket);
+ base_hart = riscv_socket_first_hartid(machine, socket);
+
+ if (max_hart_per_socket < hart_count) {
+ max_hart_per_socket = hart_count;
+ }
+
+ for (i = 0; i < hart_count; i++) {
+ imsic_addr = socket_imsic_base + i * IMSIC_HART_SIZE(guest_bits);
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
+ KVM_DEV_RISCV_AIA_ADDR_IMSIC(i + base_hart),
+ &imsic_addr, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set the address of IMSICs");
+ exit(1);
+ }
+ }
+ }
+
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
+ KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
+ &hart_bits, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: fail to set hart_bits");
+ exit(1);
+ }
+
+ if (kvm_has_gsi_routing()) {
+ for (uint64_t idx = 0; idx < aia_irq_num + 1; ++idx) {
+ /* KVM AIA only has one APLIC instance */
+ kvm_irqchip_add_irq_route(kvm_state, idx, 0, idx);
+ }
+ kvm_gsi_routing_allowed = true;
+ kvm_irqchip_commit_routes(kvm_state);
+ }
+
+ ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CTRL,
+ KVM_DEV_RISCV_AIA_CTRL_INIT,
+ NULL, true, NULL);
+ if (ret < 0) {
+ error_report("KVM AIA: initialized fail");
+ exit(1);
+ }
+}
diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
index ed281bdce0..a61f552d1d 100644
--- a/target/riscv/kvm_riscv.h
+++ b/target/riscv/kvm_riscv.h
@@ -21,5 +21,11 @@
void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
+char *kvm_aia_mode_str(uint64_t aia_mode);
+void kvm_riscv_aia_create(MachineState *machine,
+ uint64_t aia_mode, uint64_t group_shift,
+ uint64_t aia_irq_num, uint64_t aia_msi_num,
+ uint64_t aplic_base, uint64_t imsic_base,
+ uint64_t guest_num);
#endif
--
2.17.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip
2023-06-21 14:54 ` [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip Yong-Xuan Wang
@ 2023-06-30 9:40 ` Daniel Henrique Barboza
2023-07-04 15:12 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Daniel Henrique Barboza @ 2023-06-30 9:40 UTC (permalink / raw)
To: Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
Liu Zhiwei, Paolo Bonzini, kvm
On 6/21/23 11:54, Yong-Xuan Wang wrote:
> implement a function to create an KVM AIA chip
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> target/riscv/kvm.c | 163 +++++++++++++++++++++++++++++++++++++++
> target/riscv/kvm_riscv.h | 6 ++
> 2 files changed, 169 insertions(+)
>
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index eb469e8ca5..3dd8467031 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -34,6 +34,7 @@
> #include "exec/address-spaces.h"
> #include "hw/boards.h"
> #include "hw/irq.h"
> +#include "hw/intc/riscv_imsic.h"
> #include "qemu/log.h"
> #include "hw/loader.h"
> #include "kvm_riscv.h"
> @@ -41,6 +42,7 @@
> #include "chardev/char-fe.h"
> #include "migration/migration.h"
> #include "sysemu/runstate.h"
> +#include "hw/riscv/numa.h"
>
> static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
> uint64_t idx)
> @@ -548,3 +550,164 @@ bool kvm_arch_cpu_check_are_resettable(void)
> void kvm_arch_accel_class_init(ObjectClass *oc)
> {
> }
> +
> +char *kvm_aia_mode_str(uint64_t aia_mode)
> +{
> + const char *val;
> +
> + switch (aia_mode) {
> + case KVM_DEV_RISCV_AIA_MODE_EMUL:
> + val = "emul";
> + break;
> + case KVM_DEV_RISCV_AIA_MODE_HWACCEL:
> + val = "hwaccel";
> + break;
> + case KVM_DEV_RISCV_AIA_MODE_AUTO:
> + default:
> + val = "auto";
> + break;
> + };
> +
> + return g_strdup(val);
> +}
> +
> +void kvm_riscv_aia_create(MachineState *machine,
> + uint64_t aia_mode, uint64_t group_shift,
> + uint64_t aia_irq_num, uint64_t aia_msi_num,
> + uint64_t aplic_base, uint64_t imsic_base,
> + uint64_t guest_num)
> +{
> + int ret, i;
> + int aia_fd = -1;
> + uint64_t default_aia_mode;
> + uint64_t socket_count = riscv_socket_count(machine);
> + uint64_t max_hart_per_socket = 0;
> + uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
> + uint64_t socket_bits, hart_bits, guest_bits;
> +
> + aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
> +
> + if (aia_fd < 0) {
> + error_report("Unable to create in-kernel irqchip");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_MODE,
> + &default_aia_mode, false, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to get current KVM AIA mode");
> + exit(1);
> + }
> + qemu_log("KVM AIA: default mode is %s\n",
> + kvm_aia_mode_str(default_aia_mode));
> +
> + if (default_aia_mode != aia_mode) {
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_MODE,
> + &aia_mode, true, NULL);
> + if (ret < 0)
> + warn_report("KVM AIA: fail to set KVM AIA mode");
> + else
> + qemu_log("KVM AIA: set current mode to %s\n",
> + kvm_aia_mode_str(aia_mode));
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_SRCS,
> + &aia_irq_num, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set number of input irq lines");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_IDS,
> + &aia_msi_num, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set number of msi");
> + exit(1);
> + }
> +
> + socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
> + &socket_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set group_bits");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT,
> + &group_shift, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set group_shift");
> + exit(1);
> + }
> +
> + guest_bits = guest_num == 0 ? 0 :
> + find_last_bit(&guest_num, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS,
> + &guest_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set guest_bits");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
> + KVM_DEV_RISCV_AIA_ADDR_APLIC,
> + &aplic_base, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set the base address of APLIC");
> + exit(1);
> + }
> +
> + for (socket = 0; socket < socket_count; socket++) {
> + socket_imsic_base = imsic_base + socket * (1U << group_shift);
> + hart_count = riscv_socket_hart_count(machine, socket);
> + base_hart = riscv_socket_first_hartid(machine, socket);
> +
> + if (max_hart_per_socket < hart_count) {
> + max_hart_per_socket = hart_count;
> + }
> +
> + for (i = 0; i < hart_count; i++) {
> + imsic_addr = socket_imsic_base + i * IMSIC_HART_SIZE(guest_bits);
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
> + KVM_DEV_RISCV_AIA_ADDR_IMSIC(i + base_hart),
> + &imsic_addr, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set the address of IMSICs");
> + exit(1);
> + }
> + }
> + }
> +
> + hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
> + &hart_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set hart_bits");
> + exit(1);
> + }
> +
> + if (kvm_has_gsi_routing()) {
> + for (uint64_t idx = 0; idx < aia_irq_num + 1; ++idx) {
> + /* KVM AIA only has one APLIC instance */
> + kvm_irqchip_add_irq_route(kvm_state, idx, 0, idx);
> + }
> + kvm_gsi_routing_allowed = true;
> + kvm_irqchip_commit_routes(kvm_state);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CTRL,
> + KVM_DEV_RISCV_AIA_CTRL_INIT,
> + NULL, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: initialized fail");
> + exit(1);
> + }
> +}
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index ed281bdce0..a61f552d1d 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -21,5 +21,11 @@
>
> void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
> void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
> +char *kvm_aia_mode_str(uint64_t aia_mode);
> +void kvm_riscv_aia_create(MachineState *machine,
> + uint64_t aia_mode, uint64_t group_shift,
> + uint64_t aia_irq_num, uint64_t aia_msi_num,
> + uint64_t aplic_base, uint64_t imsic_base,
> + uint64_t guest_num);
>
> #endif
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip
2023-06-21 14:54 ` [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip Yong-Xuan Wang
2023-06-30 9:40 ` Daniel Henrique Barboza
@ 2023-07-04 15:12 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Andrew Jones @ 2023-07-04 15:12 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei, Paolo Bonzini,
kvm
On Wed, Jun 21, 2023 at 02:54:54PM +0000, Yong-Xuan Wang wrote:
> implement a function to create an KVM AIA chip
This is a bit too terse. We should at least summarize the KVM API this
uses.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
> target/riscv/kvm.c | 163 +++++++++++++++++++++++++++++++++++++++
> target/riscv/kvm_riscv.h | 6 ++
> 2 files changed, 169 insertions(+)
>
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index eb469e8ca5..3dd8467031 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -34,6 +34,7 @@
> #include "exec/address-spaces.h"
> #include "hw/boards.h"
> #include "hw/irq.h"
> +#include "hw/intc/riscv_imsic.h"
> #include "qemu/log.h"
> #include "hw/loader.h"
> #include "kvm_riscv.h"
> @@ -41,6 +42,7 @@
> #include "chardev/char-fe.h"
> #include "migration/migration.h"
> #include "sysemu/runstate.h"
> +#include "hw/riscv/numa.h"
>
> static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type,
> uint64_t idx)
> @@ -548,3 +550,164 @@ bool kvm_arch_cpu_check_are_resettable(void)
> void kvm_arch_accel_class_init(ObjectClass *oc)
> {
> }
> +
> +char *kvm_aia_mode_str(uint64_t aia_mode)
> +{
> + const char *val;
> +
> + switch (aia_mode) {
> + case KVM_DEV_RISCV_AIA_MODE_EMUL:
> + val = "emul";
> + break;
> + case KVM_DEV_RISCV_AIA_MODE_HWACCEL:
> + val = "hwaccel";
> + break;
> + case KVM_DEV_RISCV_AIA_MODE_AUTO:
> + default:
> + val = "auto";
> + break;
> + };
> +
> + return g_strdup(val);
There's no need to duplicate statically allocated strings unless they need
to be manipulated. These strings do not, so this should just be
const char *kvm_aia_mode_str(uint64_t aia_mode)
{
switch (aia_mode) {
case KVM_DEV_RISCV_AIA_MODE_EMUL:
return "emul";
...
or even just an array
const char *kvm_aia_mode_str[] = { "emul", "hwaccel", "auto" };
> +}
> +
> +void kvm_riscv_aia_create(MachineState *machine,
> + uint64_t aia_mode, uint64_t group_shift,
> + uint64_t aia_irq_num, uint64_t aia_msi_num,
> + uint64_t aplic_base, uint64_t imsic_base,
> + uint64_t guest_num)
> +{
> + int ret, i;
> + int aia_fd = -1;
> + uint64_t default_aia_mode;
> + uint64_t socket_count = riscv_socket_count(machine);
> + uint64_t max_hart_per_socket = 0;
> + uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
> + uint64_t socket_bits, hart_bits, guest_bits;
> +
> + aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
> +
> + if (aia_fd < 0) {
> + error_report("Unable to create in-kernel irqchip");
> + exit(1);
> + }
> +
For all the "fail to..." error messages below I would change them to
"failed to..."
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_MODE,
> + &default_aia_mode, false, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to get current KVM AIA mode");
> + exit(1);
> + }
> + qemu_log("KVM AIA: default mode is %s\n",
> + kvm_aia_mode_str(default_aia_mode));
> +
> + if (default_aia_mode != aia_mode) {
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_MODE,
> + &aia_mode, true, NULL);
> + if (ret < 0)
> + warn_report("KVM AIA: fail to set KVM AIA mode");
> + else
> + qemu_log("KVM AIA: set current mode to %s\n",
> + kvm_aia_mode_str(aia_mode));
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_SRCS,
> + &aia_irq_num, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set number of input irq lines");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_IDS,
> + &aia_msi_num, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set number of msi");
> + exit(1);
> + }
> +
> + socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
> + &socket_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set group_bits");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT,
> + &group_shift, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set group_shift");
> + exit(1);
> + }
> +
> + guest_bits = guest_num == 0 ? 0 :
> + find_last_bit(&guest_num, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS,
> + &guest_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set guest_bits");
> + exit(1);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
> + KVM_DEV_RISCV_AIA_ADDR_APLIC,
> + &aplic_base, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set the base address of APLIC");
> + exit(1);
> + }
> +
> + for (socket = 0; socket < socket_count; socket++) {
> + socket_imsic_base = imsic_base + socket * (1U << group_shift);
> + hart_count = riscv_socket_hart_count(machine, socket);
> + base_hart = riscv_socket_first_hartid(machine, socket);
> +
> + if (max_hart_per_socket < hart_count) {
> + max_hart_per_socket = hart_count;
> + }
> +
> + for (i = 0; i < hart_count; i++) {
> + imsic_addr = socket_imsic_base + i * IMSIC_HART_SIZE(guest_bits);
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_ADDR,
> + KVM_DEV_RISCV_AIA_ADDR_IMSIC(i + base_hart),
> + &imsic_addr, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set the address of IMSICs");
("KVM AIA: failed to set the IMSIC address for hart index %d", i)
> + exit(1);
> + }
> + }
> + }
> +
> + hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
> + KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
> + &hart_bits, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: fail to set hart_bits");
> + exit(1);
> + }
> +
> + if (kvm_has_gsi_routing()) {
> + for (uint64_t idx = 0; idx < aia_irq_num + 1; ++idx) {
> + /* KVM AIA only has one APLIC instance */
> + kvm_irqchip_add_irq_route(kvm_state, idx, 0, idx);
> + }
> + kvm_gsi_routing_allowed = true;
> + kvm_irqchip_commit_routes(kvm_state);
> + }
> +
> + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CTRL,
> + KVM_DEV_RISCV_AIA_CTRL_INIT,
> + NULL, true, NULL);
> + if (ret < 0) {
> + error_report("KVM AIA: initialized fail");
"KVM AIA: failed to initialize"
> + exit(1);
> + }
> +}
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index ed281bdce0..a61f552d1d 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -21,5 +21,11 @@
>
> void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
> void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
> +char *kvm_aia_mode_str(uint64_t aia_mode);
> +void kvm_riscv_aia_create(MachineState *machine,
> + uint64_t aia_mode, uint64_t group_shift,
> + uint64_t aia_irq_num, uint64_t aia_msi_num,
> + uint64_t aplic_base, uint64_t imsic_base,
> + uint64_t guest_num);
>
> #endif
> --
> 2.17.1
>
>
Thanks,
drew
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
` (3 preceding siblings ...)
2023-06-21 14:54 ` [PATCH v4 4/6] target/riscv: Create an KVM AIA irqchip Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-06-30 9:41 ` Daniel Henrique Barboza
2023-07-04 16:18 ` Andrew Jones
2023-06-21 14:54 ` [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine Yong-Xuan Wang
2023-07-05 8:14 ` [PATCH v4 0/6] Add RISC-V KVM AIA Support Andrew Jones
6 siblings, 2 replies; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Alistair Francis,
Ivan Klokov, Palmer Dabbelt, Mayuresh Chitale
KVM AIA can't emulate APLIC only. When "aia=aplic" parameter is passed,
APLIC devices is emulated by QEMU. For "aia=aplic-imsic", remove the
mmio operations of APLIC when using KVM AIA and send wired interrupt
signal via KVM_IRQ_LINE API.
After KVM AIA enabled, MSI messages are delivered by KVM_SIGNAL_MSI API
when the IMSICs receive mmio write requests.
Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
---
hw/intc/riscv_aplic.c | 58 +++++++++++++++++++++++++++++++------------
hw/intc/riscv_imsic.c | 26 +++++++++++++++----
2 files changed, 63 insertions(+), 21 deletions(-)
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index afc5b54dbb..b1949636b6 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -31,6 +31,7 @@
#include "hw/irq.h"
#include "target/riscv/cpu.h"
#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
#include "migration/vmstate.h"
#define APLIC_MAX_IDC (1UL << 14)
@@ -148,6 +149,15 @@
#define APLIC_IDC_CLAIMI 0x1c
+/*
+ * KVM AIA only supports APLIC.m, fallback to QEMU emulation if we want to use
+ * APLIC.w.
+ */
+static bool is_kvm_aia(bool msimode)
+{
+ return kvm_irqchip_in_kernel() && msimode;
+}
+
static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
uint32_t word)
{
@@ -471,6 +481,13 @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
return topi;
}
+static void riscv_kvm_aplic_request(void *opaque, int irq, int level)
+{
+ kvm_set_irq(kvm_state, irq, !!level);
+
+ return;
+}
+
static void riscv_aplic_request(void *opaque, int irq, int level)
{
bool update = false;
@@ -801,29 +818,35 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
uint32_t i;
RISCVAPLICState *aplic = RISCV_APLIC(dev);
- aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
- aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
- aplic->state = g_new0(uint32_t, aplic->num_irqs);
- aplic->target = g_new0(uint32_t, aplic->num_irqs);
- if (!aplic->msimode) {
- for (i = 0; i < aplic->num_irqs; i++) {
- aplic->target[i] = 1;
+ if (!is_kvm_aia(aplic->msimode)) {
+ aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
+ aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
+ aplic->state = g_new0(uint32_t, aplic->num_irqs);
+ aplic->target = g_new0(uint32_t, aplic->num_irqs);
+ if (!aplic->msimode) {
+ for (i = 0; i < aplic->num_irqs; i++) {
+ aplic->target[i] = 1;
+ }
}
- }
- aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
- aplic->iforce = g_new0(uint32_t, aplic->num_harts);
- aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
+ aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
+ aplic->iforce = g_new0(uint32_t, aplic->num_harts);
+ aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
- memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic,
- TYPE_RISCV_APLIC, aplic->aperture_size);
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
+ memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops,
+ aplic, TYPE_RISCV_APLIC, aplic->aperture_size);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
+ }
/*
* Only root APLICs have hardware IRQ lines. All non-root APLICs
* have IRQ lines delegated by their parent APLIC.
*/
if (!aplic->parent) {
- qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
+ if (is_kvm_aia(aplic->msimode)) {
+ qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
+ } else {
+ qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
+ }
}
/* Create output IRQ lines for non-MSI mode */
@@ -958,7 +981,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
qdev_prop_set_bit(dev, "mmode", mmode);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+
+ if (!is_kvm_aia(msimode)) {
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+ }
if (parent) {
riscv_aplic_add_child(parent, dev);
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index fea3385b51..00fdb60fc6 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -32,6 +32,7 @@
#include "target/riscv/cpu.h"
#include "target/riscv/cpu_bits.h"
#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
#include "migration/vmstate.h"
#define IMSIC_MMIO_PAGE_LE 0x00
@@ -283,6 +284,20 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
goto err;
}
+#if defined(CONFIG_KVM)
+ if (kvm_irqchip_in_kernel()) {
+ struct kvm_msi msi;
+
+ msi.address_lo = extract64(imsic->mmio.addr + addr, 0, 32);
+ msi.address_hi = extract64(imsic->mmio.addr + addr, 32, 32);
+ msi.data = le32_to_cpu(value);
+
+ kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
+
+ return;
+ }
+#endif
+
/* Writes only supported for MSI little-endian registers */
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
@@ -296,7 +311,6 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
riscv_imsic_update(imsic, page);
return;
-
err:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Invalid register write 0x%" HWADDR_PRIx "\n",
@@ -320,10 +334,12 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
CPUState *cpu = cpu_by_arch_id(imsic->hartid);
CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
- imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
- imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
- imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
- imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
+ if (!kvm_irqchip_in_kernel()) {
+ imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
+ imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
+ imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
+ imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
+ }
memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
imsic, TYPE_RISCV_IMSIC,
--
2.17.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA
2023-06-21 14:54 ` [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA Yong-Xuan Wang
@ 2023-06-30 9:41 ` Daniel Henrique Barboza
2023-07-04 16:18 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Daniel Henrique Barboza @ 2023-06-30 9:41 UTC (permalink / raw)
To: Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Alistair Francis, Ivan Klokov, Palmer Dabbelt,
Mayuresh Chitale
On 6/21/23 11:54, Yong-Xuan Wang wrote:
> KVM AIA can't emulate APLIC only. When "aia=aplic" parameter is passed,
> APLIC devices is emulated by QEMU. For "aia=aplic-imsic", remove the
> mmio operations of APLIC when using KVM AIA and send wired interrupt
> signal via KVM_IRQ_LINE API.
> After KVM AIA enabled, MSI messages are delivered by KVM_SIGNAL_MSI API
> when the IMSICs receive mmio write requests.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> hw/intc/riscv_aplic.c | 58 +++++++++++++++++++++++++++++++------------
> hw/intc/riscv_imsic.c | 26 +++++++++++++++----
> 2 files changed, 63 insertions(+), 21 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index afc5b54dbb..b1949636b6 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -31,6 +31,7 @@
> #include "hw/irq.h"
> #include "target/riscv/cpu.h"
> #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
> #include "migration/vmstate.h"
>
> #define APLIC_MAX_IDC (1UL << 14)
> @@ -148,6 +149,15 @@
>
> #define APLIC_IDC_CLAIMI 0x1c
>
> +/*
> + * KVM AIA only supports APLIC.m, fallback to QEMU emulation if we want to use
> + * APLIC.w.
> + */
> +static bool is_kvm_aia(bool msimode)
> +{
> + return kvm_irqchip_in_kernel() && msimode;
> +}
> +
> static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
> uint32_t word)
> {
> @@ -471,6 +481,13 @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
> return topi;
> }
>
> +static void riscv_kvm_aplic_request(void *opaque, int irq, int level)
> +{
> + kvm_set_irq(kvm_state, irq, !!level);
> +
> + return;
> +}
> +
> static void riscv_aplic_request(void *opaque, int irq, int level)
> {
> bool update = false;
> @@ -801,29 +818,35 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
> uint32_t i;
> RISCVAPLICState *aplic = RISCV_APLIC(dev);
>
> - aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
> - aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> - aplic->state = g_new0(uint32_t, aplic->num_irqs);
> - aplic->target = g_new0(uint32_t, aplic->num_irqs);
> - if (!aplic->msimode) {
> - for (i = 0; i < aplic->num_irqs; i++) {
> - aplic->target[i] = 1;
> + if (!is_kvm_aia(aplic->msimode)) {
> + aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
> + aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> + aplic->state = g_new0(uint32_t, aplic->num_irqs);
> + aplic->target = g_new0(uint32_t, aplic->num_irqs);
> + if (!aplic->msimode) {
> + for (i = 0; i < aplic->num_irqs; i++) {
> + aplic->target[i] = 1;
> + }
> }
> - }
> - aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
> - aplic->iforce = g_new0(uint32_t, aplic->num_harts);
> - aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
> + aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
> + aplic->iforce = g_new0(uint32_t, aplic->num_harts);
> + aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
>
> - memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic,
> - TYPE_RISCV_APLIC, aplic->aperture_size);
> - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
> + memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops,
> + aplic, TYPE_RISCV_APLIC, aplic->aperture_size);
> + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
> + }
>
> /*
> * Only root APLICs have hardware IRQ lines. All non-root APLICs
> * have IRQ lines delegated by their parent APLIC.
> */
> if (!aplic->parent) {
> - qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
> + if (is_kvm_aia(aplic->msimode)) {
> + qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
> + } else {
> + qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
> + }
> }
>
> /* Create output IRQ lines for non-MSI mode */
> @@ -958,7 +981,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
> qdev_prop_set_bit(dev, "mmode", mmode);
>
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> +
> + if (!is_kvm_aia(msimode)) {
> + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> + }
>
> if (parent) {
> riscv_aplic_add_child(parent, dev);
> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> index fea3385b51..00fdb60fc6 100644
> --- a/hw/intc/riscv_imsic.c
> +++ b/hw/intc/riscv_imsic.c
> @@ -32,6 +32,7 @@
> #include "target/riscv/cpu.h"
> #include "target/riscv/cpu_bits.h"
> #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
> #include "migration/vmstate.h"
>
> #define IMSIC_MMIO_PAGE_LE 0x00
> @@ -283,6 +284,20 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
> goto err;
> }
>
> +#if defined(CONFIG_KVM)
> + if (kvm_irqchip_in_kernel()) {
> + struct kvm_msi msi;
> +
> + msi.address_lo = extract64(imsic->mmio.addr + addr, 0, 32);
> + msi.address_hi = extract64(imsic->mmio.addr + addr, 32, 32);
> + msi.data = le32_to_cpu(value);
> +
> + kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
> +
> + return;
> + }
> +#endif
> +
> /* Writes only supported for MSI little-endian registers */
> page = addr >> IMSIC_MMIO_PAGE_SHIFT;
> if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
> @@ -296,7 +311,6 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
> riscv_imsic_update(imsic, page);
>
> return;
> -
> err:
> qemu_log_mask(LOG_GUEST_ERROR,
> "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
> @@ -320,10 +334,12 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
> CPUState *cpu = cpu_by_arch_id(imsic->hartid);
> CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
>
> - imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
> - imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
> - imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
> - imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
> + if (!kvm_irqchip_in_kernel()) {
> + imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
> + imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
> + imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
> + imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
> + }
>
> memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
> imsic, TYPE_RISCV_IMSIC,
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA
2023-06-21 14:54 ` [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA Yong-Xuan Wang
2023-06-30 9:41 ` Daniel Henrique Barboza
@ 2023-07-04 16:18 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Andrew Jones @ 2023-07-04 16:18 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu,
Alistair Francis, Ivan Klokov, Palmer Dabbelt, Mayuresh Chitale
On Wed, Jun 21, 2023 at 02:54:55PM +0000, Yong-Xuan Wang wrote:
> KVM AIA can't emulate APLIC only.
I think you mean "KVM AIA can't emulate the APLIC alone." ?
> When "aia=aplic" parameter is passed,
> APLIC devices is emulated by QEMU. For "aia=aplic-imsic", remove the
> mmio operations of APLIC when using KVM AIA and send wired interrupt
> signal via KVM_IRQ_LINE API.
> After KVM AIA enabled, MSI messages are delivered by KVM_SIGNAL_MSI API
> when the IMSICs receive mmio write requests.
>
> Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
> hw/intc/riscv_aplic.c | 58 +++++++++++++++++++++++++++++++------------
> hw/intc/riscv_imsic.c | 26 +++++++++++++++----
> 2 files changed, 63 insertions(+), 21 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index afc5b54dbb..b1949636b6 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -31,6 +31,7 @@
> #include "hw/irq.h"
> #include "target/riscv/cpu.h"
> #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
> #include "migration/vmstate.h"
>
> #define APLIC_MAX_IDC (1UL << 14)
> @@ -148,6 +149,15 @@
>
> #define APLIC_IDC_CLAIMI 0x1c
>
> +/*
> + * KVM AIA only supports APLIC.m, fallback to QEMU emulation if we want to use
> + * APLIC.w.
I assume APLIC.m and APLIC.w mean "APLIC MSI" and "APLIC Wired". Can you
please spell that out?
> + */
> +static bool is_kvm_aia(bool msimode)
> +{
> + return kvm_irqchip_in_kernel() && msimode;
> +}
> +
> static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
> uint32_t word)
> {
> @@ -471,6 +481,13 @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState *aplic, uint32_t idc)
> return topi;
> }
>
> +static void riscv_kvm_aplic_request(void *opaque, int irq, int level)
> +{
> + kvm_set_irq(kvm_state, irq, !!level);
> +
> + return;
Unnecessary 'return'
> +}
> +
> static void riscv_aplic_request(void *opaque, int irq, int level)
> {
> bool update = false;
> @@ -801,29 +818,35 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)
> uint32_t i;
> RISCVAPLICState *aplic = RISCV_APLIC(dev);
>
> - aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
> - aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> - aplic->state = g_new0(uint32_t, aplic->num_irqs);
> - aplic->target = g_new0(uint32_t, aplic->num_irqs);
> - if (!aplic->msimode) {
> - for (i = 0; i < aplic->num_irqs; i++) {
> - aplic->target[i] = 1;
> + if (!is_kvm_aia(aplic->msimode)) {
> + aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
> + aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> + aplic->state = g_new0(uint32_t, aplic->num_irqs);
> + aplic->target = g_new0(uint32_t, aplic->num_irqs);
> + if (!aplic->msimode) {
> + for (i = 0; i < aplic->num_irqs; i++) {
> + aplic->target[i] = 1;
> + }
> }
> - }
> - aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
> - aplic->iforce = g_new0(uint32_t, aplic->num_harts);
> - aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
> + aplic->idelivery = g_new0(uint32_t, aplic->num_harts);
> + aplic->iforce = g_new0(uint32_t, aplic->num_harts);
> + aplic->ithreshold = g_new0(uint32_t, aplic->num_harts);
>
> - memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops, aplic,
> - TYPE_RISCV_APLIC, aplic->aperture_size);
> - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
> + memory_region_init_io(&aplic->mmio, OBJECT(dev), &riscv_aplic_ops,
> + aplic, TYPE_RISCV_APLIC, aplic->aperture_size);
> + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &aplic->mmio);
> + }
>
> /*
> * Only root APLICs have hardware IRQ lines. All non-root APLICs
> * have IRQ lines delegated by their parent APLIC.
> */
> if (!aplic->parent) {
> - qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
> + if (is_kvm_aia(aplic->msimode)) {
> + qdev_init_gpio_in(dev, riscv_kvm_aplic_request, aplic->num_irqs);
> + } else {
> + qdev_init_gpio_in(dev, riscv_aplic_request, aplic->num_irqs);
> + }
> }
>
> /* Create output IRQ lines for non-MSI mode */
> @@ -958,7 +981,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
> qdev_prop_set_bit(dev, "mmode", mmode);
>
> sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> +
> + if (!is_kvm_aia(msimode)) {
> + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
> + }
>
> if (parent) {
> riscv_aplic_add_child(parent, dev);
> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> index fea3385b51..00fdb60fc6 100644
> --- a/hw/intc/riscv_imsic.c
> +++ b/hw/intc/riscv_imsic.c
> @@ -32,6 +32,7 @@
> #include "target/riscv/cpu.h"
> #include "target/riscv/cpu_bits.h"
> #include "sysemu/sysemu.h"
> +#include "sysemu/kvm.h"
> #include "migration/vmstate.h"
>
> #define IMSIC_MMIO_PAGE_LE 0x00
> @@ -283,6 +284,20 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
> goto err;
> }
>
> +#if defined(CONFIG_KVM)
> + if (kvm_irqchip_in_kernel()) {
> + struct kvm_msi msi;
> +
> + msi.address_lo = extract64(imsic->mmio.addr + addr, 0, 32);
> + msi.address_hi = extract64(imsic->mmio.addr + addr, 32, 32);
> + msi.data = le32_to_cpu(value);
> +
> + kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
> +
> + return;
> + }
> +#endif
> +
> /* Writes only supported for MSI little-endian registers */
> page = addr >> IMSIC_MMIO_PAGE_SHIFT;
> if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
> @@ -296,7 +311,6 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
> riscv_imsic_update(imsic, page);
>
> return;
> -
Stray line removal. IMO it's better to leave it.
> err:
> qemu_log_mask(LOG_GUEST_ERROR,
> "%s: Invalid register write 0x%" HWADDR_PRIx "\n",
> @@ -320,10 +334,12 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
> CPUState *cpu = cpu_by_arch_id(imsic->hartid);
> CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
>
> - imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
> - imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
> - imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
> - imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
> + if (!kvm_irqchip_in_kernel()) {
> + imsic->num_eistate = imsic->num_pages * imsic->num_irqs;
> + imsic->eidelivery = g_new0(uint32_t, imsic->num_pages);
> + imsic->eithreshold = g_new0(uint32_t, imsic->num_pages);
> + imsic->eistate = g_new0(uint32_t, imsic->num_eistate);
> + }
>
> memory_region_init_io(&imsic->mmio, OBJECT(dev), &riscv_imsic_ops,
> imsic, TYPE_RISCV_IMSIC,
> --
> 2.17.1
>
>
Otherwise,
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Thanks,
drew
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
` (4 preceding siblings ...)
2023-06-21 14:54 ` [PATCH v4 5/6] target/riscv: update APLIC and IMSIC to support KVM AIA Yong-Xuan Wang
@ 2023-06-21 14:54 ` Yong-Xuan Wang
2023-06-30 9:43 ` Daniel Henrique Barboza
2023-07-04 16:47 ` Andrew Jones
2023-07-05 8:14 ` [PATCH v4 0/6] Add RISC-V KVM AIA Support Andrew Jones
6 siblings, 2 replies; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-06-21 14:54 UTC (permalink / raw)
To: qemu-devel, qemu-riscv
Cc: rkanwal, anup, dbarboza, atishp, vincent.chen, greentime.hu,
frank.chang, jim.shu, Yong-Xuan Wang, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei
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
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine
2023-06-21 14:54 ` [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine Yong-Xuan Wang
@ 2023-06-30 9:43 ` Daniel Henrique Barboza
2023-07-04 16:47 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Daniel Henrique Barboza @ 2023-06-30 9:43 UTC (permalink / raw)
To: Yong-Xuan Wang, qemu-devel, qemu-riscv
Cc: rkanwal, anup, atishp, vincent.chen, greentime.hu, frank.chang,
jim.shu, Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
Liu Zhiwei
On 6/21/23 11:54, Yong-Xuan Wang wrote:
> 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>
> ---
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.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;
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine
2023-06-21 14:54 ` [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine Yong-Xuan Wang
2023-06-30 9:43 ` Daniel Henrique Barboza
@ 2023-07-04 16:47 ` Andrew Jones
1 sibling, 0 replies; 20+ messages in thread
From: Andrew Jones @ 2023-07-04 16:47 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu, Palmer Dabbelt,
Alistair Francis, Bin Meng, Weiwei Li, Liu Zhiwei
On Wed, Jun 21, 2023 at 02:54:56PM +0000, Yong-Xuan Wang wrote:
> 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. */
"APLIC MSI" and "APLIC Wired"
> +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);
> }
There are a couple other instances of s->soc[socket].num_harts in this
function that can be changed to num_harts.
> @@ -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;
Need {}. Doesn't checkpatch complain about that? But this break is a bit
hacky. Duplicating the three phandle assignments above into the 'if
(virt_use_kvm_aia(s)) {' block above and putting this for loop into the
else block above would be neater.
> }
> 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);
I was wondering why kvm_aia_mode_str() was export from target/riscv/kvm.c
and now I see why it was also using strdup. I'd just do the strdup here
though and return static strings from kvm_aia_mode_str().
> +}
> +
> +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
>
>
Thanks,
drew
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 0/6] Add RISC-V KVM AIA Support
2023-06-21 14:54 [PATCH v4 0/6] Add RISC-V KVM AIA Support Yong-Xuan Wang
` (5 preceding siblings ...)
2023-06-21 14:54 ` [PATCH v4 6/6] target/riscv: select KVM AIA in riscv virt machine Yong-Xuan Wang
@ 2023-07-05 8:14 ` Andrew Jones
2023-07-10 4:00 ` Yong-Xuan Wang
6 siblings, 1 reply; 20+ messages in thread
From: Andrew Jones @ 2023-07-05 8:14 UTC (permalink / raw)
To: Yong-Xuan Wang
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu
On Wed, Jun 21, 2023 at 02:54:50PM +0000, Yong-Xuan Wang wrote:
> This series adds support for KVM AIA in RISC-V architecture.
>
> In order to test these patches, we require Linux with KVM AIA support which can
> be found in the riscv_kvm_aia_hwaccel_v1 branch at
> https://github.com/avpatel/linux.git
Is it possible to add irqfd support? Maybe even as simply as the diff
below? If not, can you explain what still needs to be done in order
to do so?
Thanks,
drew
diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 00fdb60fc6ab..b38d9bb5506a 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -371,6 +371,7 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
}
msi_nonbroken = true;
+ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
}
static Property riscv_imsic_properties[] = {
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 0/6] Add RISC-V KVM AIA Support
2023-07-05 8:14 ` [PATCH v4 0/6] Add RISC-V KVM AIA Support Andrew Jones
@ 2023-07-10 4:00 ` Yong-Xuan Wang
0 siblings, 0 replies; 20+ messages in thread
From: Yong-Xuan Wang @ 2023-07-10 4:00 UTC (permalink / raw)
To: Andrew Jones
Cc: qemu-devel, qemu-riscv, rkanwal, anup, dbarboza, atishp,
vincent.chen, greentime.hu, frank.chang, jim.shu
Hi Andrew,
I'll add it into patch v5. Thank you!
Regards,
Yong-Xuan
On Wed, Jul 5, 2023 at 4:14 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Wed, Jun 21, 2023 at 02:54:50PM +0000, Yong-Xuan Wang wrote:
> > This series adds support for KVM AIA in RISC-V architecture.
> >
> > In order to test these patches, we require Linux with KVM AIA support which can
> > be found in the riscv_kvm_aia_hwaccel_v1 branch at
> > https://github.com/avpatel/linux.git
>
> Is it possible to add irqfd support? Maybe even as simply as the diff
> below? If not, can you explain what still needs to be done in order
> to do so?
>
> Thanks,
> drew
>
>
> diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> index 00fdb60fc6ab..b38d9bb5506a 100644
> --- a/hw/intc/riscv_imsic.c
> +++ b/hw/intc/riscv_imsic.c
> @@ -371,6 +371,7 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)
> }
>
> msi_nonbroken = true;
> + kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
> }
>
> static Property riscv_imsic_properties[] = {
>
^ permalink raw reply [flat|nested] 20+ messages in thread