* [PATCH v5 01/11] target/loongarch: move some machine define to virt.h
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-11 8:59 ` [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support Song Gao
` (9 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
move some machine define to virt.h
Signed-off-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
---
include/hw/loongarch/virt.h | 19 +++++++++++++++++++
target/loongarch/cpu.h | 21 ---------------------
2 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 602feab0f0..7120b46714 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -13,6 +13,25 @@
#include "hw/block/flash.h"
#include "hw/loongarch/boot.h"
+#define IOCSRF_TEMP 0
+#define IOCSRF_NODECNT 1
+#define IOCSRF_MSI 2
+#define IOCSRF_EXTIOI 3
+#define IOCSRF_CSRIPI 4
+#define IOCSRF_FREQCSR 5
+#define IOCSRF_FREQSCALE 6
+#define IOCSRF_DVFSV1 7
+#define IOCSRF_GMOD 9
+#define IOCSRF_VM 11
+
+#define VERSION_REG 0x0
+#define FEATURE_REG 0x8
+#define VENDOR_REG 0x10
+#define CPUNAME_REG 0x20
+#define MISC_FUNC_REG 0x420
+#define IOCSRM_EXTIOI_EN 48
+#define IOCSRM_EXTIOI_INT_ENCODE 49
+
#define LOONGARCH_MAX_CPUS 256
#define VIRT_FWCFG_BASE 0x1e020000UL
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 9538e8d61d..56fc4a1459 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -21,27 +21,6 @@
#include "cpu-csr.h"
#include "cpu-qom.h"
-#define IOCSRF_TEMP 0
-#define IOCSRF_NODECNT 1
-#define IOCSRF_MSI 2
-#define IOCSRF_EXTIOI 3
-#define IOCSRF_CSRIPI 4
-#define IOCSRF_FREQCSR 5
-#define IOCSRF_FREQSCALE 6
-#define IOCSRF_DVFSV1 7
-#define IOCSRF_GMOD 9
-#define IOCSRF_VM 11
-
-#define VERSION_REG 0x0
-#define FEATURE_REG 0x8
-#define VENDOR_REG 0x10
-#define CPUNAME_REG 0x20
-#define MISC_FUNC_REG 0x420
-#define IOCSRM_EXTIOI_EN 48
-#define IOCSRM_EXTIOI_INT_ENCODE 49
-
-#define IOCSR_MEM_SIZE 0x428
-
#define FCSR0_M1 0x1f /* FCSR1 mask, Enables */
#define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */
#define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-07-11 8:59 ` [PATCH v5 01/11] target/loongarch: move some machine define to virt.h Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-15 1:02 ` Bibo Mao
2025-07-11 8:59 ` [PATCH v5 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
` (8 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Avecintc feature is added in LoongArchVirtMachinState, and it is used
to check whether virt machine supports the advanced interrupt controller
and by default set avecintc with ON_OFF_AUTO_ON.
LoongArchVirtMachineState adds misc_feature and misc_status for misc
features and status. and set the default avec feature bit.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 30 ++++++++++++++++++++++++++++++
include/hw/loongarch/virt.h | 14 ++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index b15ada2078..112cf9a9db 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -47,6 +47,27 @@
#include "hw/virtio/virtio-iommu.h"
#include "qemu/error-report.h"
+static void virt_get_avecintc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
+ OnOffAuto avecintc = lvms->avecintc;
+
+ visit_type_OnOffAuto(v, name, &avecintc, errp);
+
+}
+static void virt_set_avecintc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
+
+ visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
+ if (lvms->avecintc == ON_OFF_AUTO_OFF) {
+ lvms->misc_feature &= ~BIT(IOCSRF_AVEC);
+ lvms->misc_status &= ~BIT(IOCSRM_AVEC_EN);
+ }
+}
+
static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -846,6 +867,9 @@ static void virt_initfn(Object *obj)
if (tcg_enabled()) {
lvms->veiointc = ON_OFF_AUTO_OFF;
}
+
+ lvms->misc_feature = BIT(IOCSRF_AVEC);
+ lvms->avecintc = ON_OFF_AUTO_ON;
lvms->acpi = ON_OFF_AUTO_AUTO;
lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
@@ -1238,6 +1262,12 @@ static void virt_class_init(ObjectClass *oc, const void *data)
NULL, NULL);
object_class_property_set_description(oc, "v-eiointc",
"Enable Virt Extend I/O Interrupt Controller.");
+#ifdef CONFIG_TCG
+ object_class_property_add(oc, "avecintc", "OnOffAuto",
+ virt_get_avecintc, virt_set_avecintc, NULL, NULL);
+ object_class_property_set_description(oc, "avecintc",
+ "Enable Advance Interrupt Controller.");
+#endif
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
#ifdef CONFIG_TPM
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 7120b46714..68b8e92e99 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -23,6 +23,7 @@
#define IOCSRF_DVFSV1 7
#define IOCSRF_GMOD 9
#define IOCSRF_VM 11
+#define IOCSRF_AVEC 15
#define VERSION_REG 0x0
#define FEATURE_REG 0x8
@@ -31,6 +32,7 @@
#define MISC_FUNC_REG 0x420
#define IOCSRM_EXTIOI_EN 48
#define IOCSRM_EXTIOI_INT_ENCODE 49
+#define IOCSRM_AVEC_EN 51
#define LOONGARCH_MAX_CPUS 256
@@ -69,6 +71,7 @@ struct LoongArchVirtMachineState {
Notifier powerdown_notifier;
OnOffAuto acpi;
OnOffAuto veiointc;
+ OnOffAuto avecintc;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
@@ -84,6 +87,8 @@ struct LoongArchVirtMachineState {
DeviceState *extioi;
struct memmap_entry *memmap_table;
unsigned int memmap_entries;
+ uint64_t misc_feature;
+ uint64_t misc_status;
};
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
@@ -91,6 +96,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
void virt_acpi_setup(LoongArchVirtMachineState *lvms);
void virt_fdt_setup(LoongArchVirtMachineState *lvms);
+static inline bool virt_has_avecintc(LoongArchVirtMachineState *lvms)
+{
+ if (!(lvms->misc_feature & BIT(IOCSRF_AVEC))) {
+ return false;
+ }
+
+ return true;
+}
+
static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
{
if (lvms->veiointc == ON_OFF_AUTO_OFF) {
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support
2025-07-11 8:59 ` [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support Song Gao
@ 2025-07-15 1:02 ` Bibo Mao
2025-07-15 1:32 ` gaosong
0 siblings, 1 reply; 20+ messages in thread
From: Bibo Mao @ 2025-07-15 1:02 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> Avecintc feature is added in LoongArchVirtMachinState, and it is used
> to check whether virt machine supports the advanced interrupt controller
> and by default set avecintc with ON_OFF_AUTO_ON.
> LoongArchVirtMachineState adds misc_feature and misc_status for misc
> features and status. and set the default avec feature bit.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/virt.c | 30 ++++++++++++++++++++++++++++++
> include/hw/loongarch/virt.h | 14 ++++++++++++++
> 2 files changed, 44 insertions(+)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index b15ada2078..112cf9a9db 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -47,6 +47,27 @@
> #include "hw/virtio/virtio-iommu.h"
> #include "qemu/error-report.h"
>
> +static void virt_get_avecintc(Object *obj, Visitor *v, const char *name,
> + void *opaque, Error **errp)
> +{
> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
> + OnOffAuto avecintc = lvms->avecintc;
> +
> + visit_type_OnOffAuto(v, name, &avecintc, errp);
> +
> +}
> +static void virt_set_avecintc(Object *obj, Visitor *v, const char *name,
> + void *opaque, Error **errp)
> +{
> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
> +
> + visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
> + lvms->misc_feature &= ~BIT(IOCSRF_AVEC);
> + lvms->misc_status &= ~BIT(IOCSRM_AVEC_EN);
> + }
> +}
> +
> static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
> void *opaque, Error **errp)
> {
> @@ -846,6 +867,9 @@ static void virt_initfn(Object *obj)
> if (tcg_enabled()) {
> lvms->veiointc = ON_OFF_AUTO_OFF;
> }
> +
> + lvms->misc_feature = BIT(IOCSRF_AVEC);
> + lvms->avecintc = ON_OFF_AUTO_ON;
> lvms->acpi = ON_OFF_AUTO_AUTO;
> lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
> lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
> @@ -1238,6 +1262,12 @@ static void virt_class_init(ObjectClass *oc, const void *data)
> NULL, NULL);
> object_class_property_set_description(oc, "v-eiointc",
> "Enable Virt Extend I/O Interrupt Controller.");
> +#ifdef CONFIG_TCG
I think it will be better if tcg_enabled() is used here, since
CONFIG_TCG and CONFIG_KVM is enabled by default. It should be supported
in KVM mode now. It is suggested in V4 review process :)
Regards
Bibo Mao
> + object_class_property_add(oc, "avecintc", "OnOffAuto",
> + virt_get_avecintc, virt_set_avecintc, NULL, NULL);
> + object_class_property_set_description(oc, "avecintc",
> + "Enable Advance Interrupt Controller.");
> +#endif
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
> #ifdef CONFIG_TPM
> diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
> index 7120b46714..68b8e92e99 100644
> --- a/include/hw/loongarch/virt.h
> +++ b/include/hw/loongarch/virt.h
> @@ -23,6 +23,7 @@
> #define IOCSRF_DVFSV1 7
> #define IOCSRF_GMOD 9
> #define IOCSRF_VM 11
> +#define IOCSRF_AVEC 15
>
> #define VERSION_REG 0x0
> #define FEATURE_REG 0x8
> @@ -31,6 +32,7 @@
> #define MISC_FUNC_REG 0x420
> #define IOCSRM_EXTIOI_EN 48
> #define IOCSRM_EXTIOI_INT_ENCODE 49
> +#define IOCSRM_AVEC_EN 51
>
> #define LOONGARCH_MAX_CPUS 256
>
> @@ -69,6 +71,7 @@ struct LoongArchVirtMachineState {
> Notifier powerdown_notifier;
> OnOffAuto acpi;
> OnOffAuto veiointc;
> + OnOffAuto avecintc;
> char *oem_id;
> char *oem_table_id;
> DeviceState *acpi_ged;
> @@ -84,6 +87,8 @@ struct LoongArchVirtMachineState {
> DeviceState *extioi;
> struct memmap_entry *memmap_table;
> unsigned int memmap_entries;
> + uint64_t misc_feature;
> + uint64_t misc_status;
> };
>
> #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
> @@ -91,6 +96,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>
> +static inline bool virt_has_avecintc(LoongArchVirtMachineState *lvms)
> +{
> + if (!(lvms->misc_feature & BIT(IOCSRF_AVEC))) {
> + return false;
> + }
> +
> + return true;
> +}
> +
> static inline bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
> {
> if (lvms->veiointc == ON_OFF_AUTO_OFF) {
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support
2025-07-15 1:02 ` Bibo Mao
@ 2025-07-15 1:32 ` gaosong
0 siblings, 0 replies; 20+ messages in thread
From: gaosong @ 2025-07-15 1:32 UTC (permalink / raw)
To: Bibo Mao
Cc: qemu-devel, philmd, jiaxun.yang, Richard Henderson, Peter Maydell
在 2025/7/15 上午9:02, Bibo Mao 写道:
>
>
> On 2025/7/11 下午4:59, Song Gao wrote:
>> Avecintc feature is added in LoongArchVirtMachinState, and it is used
>> to check whether virt machine supports the advanced interrupt controller
>> and by default set avecintc with ON_OFF_AUTO_ON.
>> LoongArchVirtMachineState adds misc_feature and misc_status for misc
>> features and status. and set the default avec feature bit.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/loongarch/virt.c | 30 ++++++++++++++++++++++++++++++
>> include/hw/loongarch/virt.h | 14 ++++++++++++++
>> 2 files changed, 44 insertions(+)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index b15ada2078..112cf9a9db 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -47,6 +47,27 @@
>> #include "hw/virtio/virtio-iommu.h"
>> #include "qemu/error-report.h"
>> +static void virt_get_avecintc(Object *obj, Visitor *v, const char
>> *name,
>> + void *opaque, Error **errp)
>> +{
>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>> + OnOffAuto avecintc = lvms->avecintc;
>> +
>> + visit_type_OnOffAuto(v, name, &avecintc, errp);
>> +
>> +}
>> +static void virt_set_avecintc(Object *obj, Visitor *v, const char
>> *name,
>> + void *opaque, Error **errp)
>> +{
>> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(obj);
>> +
>> + visit_type_OnOffAuto(v, name, &lvms->avecintc, errp);
>> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
>> + lvms->misc_feature &= ~BIT(IOCSRF_AVEC);
>> + lvms->misc_status &= ~BIT(IOCSRM_AVEC_EN);
>> + }
>> +}
>> +
>> static void virt_get_veiointc(Object *obj, Visitor *v, const char
>> *name,
>> void *opaque, Error **errp)
>> {
>> @@ -846,6 +867,9 @@ static void virt_initfn(Object *obj)
>> if (tcg_enabled()) {
>> lvms->veiointc = ON_OFF_AUTO_OFF;
>> }
>> +
>> + lvms->misc_feature = BIT(IOCSRF_AVEC);
>> + lvms->avecintc = ON_OFF_AUTO_ON;
>> lvms->acpi = ON_OFF_AUTO_AUTO;
>> lvms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
>> lvms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
>> @@ -1238,6 +1262,12 @@ static void virt_class_init(ObjectClass *oc,
>> const void *data)
>> NULL, NULL);
>> object_class_property_set_description(oc, "v-eiointc",
>> "Enable Virt Extend I/O Interrupt
>> Controller.");
>> +#ifdef CONFIG_TCG
> I think it will be better if tcg_enabled() is used here, since
> CONFIG_TCG and CONFIG_KVM is enabled by default. It should be
> supported in KVM mode now. It is suggested in V4 review process :)
>
emm, I had tested again , this may be a bug , here tcg_allowed is not
set so the tcg_enabled() not work, the same with kvm_enabled()
Thanks.,
Song Gao
> Regads
> Bibo Mao
>> + object_class_property_add(oc, "avecintc", "OnOffAuto",
>> + virt_get_avecintc, virt_set_avecintc, NULL, NULL);
>> + object_class_property_set_description(oc, "avecintc",
>> + "Enable Advance Interrupt Controller.");
>> +#endif
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>> machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
>> #ifdef CONFIG_TPM
>> diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
>> index 7120b46714..68b8e92e99 100644
>> --- a/include/hw/loongarch/virt.h
>> +++ b/include/hw/loongarch/virt.h
>> @@ -23,6 +23,7 @@
>> #define IOCSRF_DVFSV1 7
>> #define IOCSRF_GMOD 9
>> #define IOCSRF_VM 11
>> +#define IOCSRF_AVEC 15
>> #define VERSION_REG 0x0
>> #define FEATURE_REG 0x8
>> @@ -31,6 +32,7 @@
>> #define MISC_FUNC_REG 0x420
>> #define IOCSRM_EXTIOI_EN 48
>> #define IOCSRM_EXTIOI_INT_ENCODE 49
>> +#define IOCSRM_AVEC_EN 51
>> #define LOONGARCH_MAX_CPUS 256
>> @@ -69,6 +71,7 @@ struct LoongArchVirtMachineState {
>> Notifier powerdown_notifier;
>> OnOffAuto acpi;
>> OnOffAuto veiointc;
>> + OnOffAuto avecintc;
>> char *oem_id;
>> char *oem_table_id;
>> DeviceState *acpi_ged;
>> @@ -84,6 +87,8 @@ struct LoongArchVirtMachineState {
>> DeviceState *extioi;
>> struct memmap_entry *memmap_table;
>> unsigned int memmap_entries;
>> + uint64_t misc_feature;
>> + uint64_t misc_status;
>> };
>> #define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
>> @@ -91,6 +96,15 @@
>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState,
>> LOONGARCH_VIRT_MACHINE)
>> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>> +static inline bool virt_has_avecintc(LoongArchVirtMachineState *lvms)
>> +{
>> + if (!(lvms->misc_feature & BIT(IOCSRF_AVEC))) {
>> + return false;
>> + }
>> +
>> + return true;
>> +}
>> +
>> static inline bool
>> virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
>> {
>> if (lvms->veiointc == ON_OFF_AUTO_OFF) {
>>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 03/11] hw/loongarch: add misc register supoort avecintc
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-07-11 8:59 ` [PATCH v5 01/11] target/loongarch: move some machine define to virt.h Song Gao
2025-07-11 8:59 ` [PATCH v5 02/11] hw/loongarch: add virt feature avecintc support Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-11 8:59 ` [PATCH v5 04/11] loongarch: add a advance interrupt controller device Song Gao
` (7 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Add feature register and misc register for avecintc feature checking and
setting
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 112cf9a9db..0d05404eb5 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -560,6 +560,10 @@ static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr,
return MEMTX_OK;
}
+ if (val & BIT(IOCSRM_AVEC_EN)) {
+ lvms->misc_status |= BIT(IOCSRM_AVEC_EN);
+ }
+
features = address_space_ldl(&lvms->as_iocsr,
EXTIOI_VIRT_BASE + EXTIOI_VIRT_CONFIG,
attrs, NULL);
@@ -595,6 +599,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
break;
case FEATURE_REG:
ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
+ if (virt_has_avecintc(lvms)) {
+ ret |= BIT(IOCSRF_AVEC);
+ }
if (kvm_enabled()) {
ret |= BIT(IOCSRF_VM);
}
@@ -624,6 +631,10 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
}
+ if (virt_has_avecintc(lvms) &&
+ (lvms->misc_status & BIT(IOCSRM_AVEC_EN))) {
+ ret |= BIT_ULL(IOCSRM_AVEC_EN);
+ }
break;
default:
g_assert_not_reached();
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 04/11] loongarch: add a advance interrupt controller device
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (2 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 03/11] hw/loongarch: add misc register supoort avecintc Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-11 8:59 ` [PATCH v5 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
` (6 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Add Loongarch advance interrupt controller device base Definition.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/Kconfig | 3 ++
hw/intc/loongarch_avec.c | 68 ++++++++++++++++++++++++++++++++
hw/intc/meson.build | 1 +
hw/loongarch/Kconfig | 1 +
include/hw/intc/loongarch_avec.h | 35 ++++++++++++++++
5 files changed, 108 insertions(+)
create mode 100644 hw/intc/loongarch_avec.c
create mode 100644 include/hw/intc/loongarch_avec.h
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 7547528f2c..b9266dc269 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -109,3 +109,6 @@ config LOONGARCH_PCH_MSI
config LOONGARCH_EXTIOI
bool
+
+config LOONGARCH_AVEC
+ bool
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
new file mode 100644
index 0000000000..5a3e7ecc03
--- /dev/null
+++ b/hw/intc/loongarch_avec.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson Advance interrupt controller.
+ *
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/intc/loongarch_avec.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+#include "hw/qdev-properties.h"
+
+
+static void loongarch_avec_realize(DeviceState *dev, Error **errp)
+{
+ LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
+
+ Error *local_err = NULL;
+ lac->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ return;
+}
+
+static void loongarch_avec_unrealize(DeviceState *dev)
+{
+ return;
+}
+
+static void loongarch_avec_init(Object *obj)
+{
+ return;
+}
+
+static void loongarch_avec_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ LoongArchAVECClass *lac = LOONGARCH_AVEC_CLASS(klass);
+
+ dc->unrealize = loongarch_avec_unrealize;
+ device_class_set_parent_realize(dc, loongarch_avec_realize,
+ &lac->parent_realize);
+}
+
+static const TypeInfo loongarch_avec_info = {
+ .name = TYPE_LOONGARCH_AVEC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LoongArchAVECState),
+ .instance_init = loongarch_avec_init,
+ .class_init = loongarch_avec_class_init,
+};
+
+static void loongarch_avec_register_types(void)
+{
+ type_register_static(&loongarch_avec_info);
+}
+
+type_init(loongarch_avec_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 3137521a4a..cf2c47cd53 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -80,3 +80,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.c'))
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_EXTIOI'],
if_true: files('loongarch_extioi_kvm.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_AVEC', if_true: files('loongarch_avec.c'))
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index bb2838b7b5..1bf240b1e2 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -15,6 +15,7 @@ config LOONGARCH_VIRT
select LOONGARCH_PCH_PIC
select LOONGARCH_PCH_MSI
select LOONGARCH_EXTIOI
+ select LOONGARCH_AVEC
select LS7A_RTC
select SMBIOS
select ACPI_CPU_HOTPLUG
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
new file mode 100644
index 0000000000..92e2ca9590
--- /dev/null
+++ b/include/hw/intc/loongarch_avec.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch Advance interrupt controller definitions
+ *
+ * Copyright (C) 2025 Loongson Technology Corporation Limited
+ */
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+
+
+#define NR_VECTORS 256
+
+#define TYPE_LOONGARCH_AVEC "loongarch_avec"
+OBJECT_DECLARE_TYPE(LoongArchAVECState, LoongArchAVECClass, LOONGARCH_AVEC)
+
+typedef struct AVECCore {
+ CPUState *cpu;
+ qemu_irq parent_irq;
+ uint64_t arch_id;
+} AVECCore;
+
+struct LoongArchAVECState {
+ SysBusDevice parent_obj;
+ AVECCore *cpu;
+ uint32_t num_cpu;
+};
+
+struct LoongArchAVECClass {
+ SysBusDeviceClass parent_class;
+
+ DeviceRealize parent_realize;
+ DeviceUnrealize parent_unrealize;
+};
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 05/11] target/loongarch: add msg interrupt CSR registers
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (3 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 04/11] loongarch: add a advance interrupt controller device Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-14 9:35 ` Bibo Mao
2025-07-11 8:59 ` [PATCH v5 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
` (5 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
include CSR_MSGIS0-3, CSR_MSGIR and CSR_MSGIE.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 3 +++
target/loongarch/cpu.h | 10 ++++++++++
target/loongarch/machine.c | 27 +++++++++++++++++++++++++--
3 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 0834e91f30..4792677086 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -186,6 +186,9 @@ FIELD(CSR_MERRCTL, ISMERR, 0, 1)
#define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */
+#define LOONGARCH_CSR_MSGIS(N) (0xa0 + N)
+#define LOONGARCH_CSR_MSGIR 0xa4
+
/* Direct map windows CSRs*/
#define LOONGARCH_CSR_DMW(N) (0x180 + N)
FIELD(CSR_DMW, PLV0, 0, 1)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 56fc4a1459..208d3e0cd3 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -233,6 +233,12 @@ FIELD(TLB_MISC, ASID, 1, 10)
FIELD(TLB_MISC, VPPN, 13, 35)
FIELD(TLB_MISC, PS, 48, 6)
+/*Msg interrupt registers */
+FIELD(CSR_MSGIS, IS, 0, 63)
+FIELD(CSR_MSGIR, INTNUM, 0, 8)
+FIELD(CSR_MSGIR, ACTIVE, 31, 1)
+FIELD(CSR_MSGIE, PT, 0, 8)
+
#define LSX_LEN (128)
#define LASX_LEN (256)
@@ -350,6 +356,10 @@ typedef struct CPUArchState {
uint64_t CSR_DBG;
uint64_t CSR_DERA;
uint64_t CSR_DSAVE;
+ /* Msg interrupt registers */
+ uint64_t CSR_MSGIS[4];
+ uint64_t CSR_MSGIR;
+ uint64_t CSR_MSGIE;
struct {
uint64_t guest_addr;
} stealtime;
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
index 4e70f5c879..9eddb9341a 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -10,6 +10,7 @@
#include "migration/cpu.h"
#include "system/tcg.h"
#include "vec.h"
+#include "hw/loongarch/virt.h"
static const VMStateDescription vmstate_fpu_reg = {
.name = "fpu_reg",
@@ -45,6 +46,27 @@ static const VMStateDescription vmstate_fpu = {
},
};
+static bool msg_needed(void *opaque)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
+
+ return !!(lvms->misc_feature & BIT(IOCSRF_AVEC));
+}
+
+static const VMStateDescription vmstate_msg = {
+ .name = "cpu/msg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = msg_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, 4),
+ VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
+ VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static const VMStateDescription vmstate_lsxh_reg = {
.name = "lsxh_reg",
.version_id = 1,
@@ -168,8 +190,8 @@ static const VMStateDescription vmstate_tlb = {
/* LoongArch CPU state */
const VMStateDescription vmstate_loongarch_cpu = {
.name = "cpu",
- .version_id = 3,
- .minimum_version_id = 3,
+ .version_id = 4,
+ .minimum_version_id = 4,
.fields = (const VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
VMSTATE_UINTTL(env.pc, LoongArchCPU),
@@ -245,6 +267,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
&vmstate_tlb,
#endif
&vmstate_lbt,
+ &vmstate_msg,
NULL
}
};
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 05/11] target/loongarch: add msg interrupt CSR registers
2025-07-11 8:59 ` [PATCH v5 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-07-14 9:35 ` Bibo Mao
0 siblings, 0 replies; 20+ messages in thread
From: Bibo Mao @ 2025-07-14 9:35 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> include CSR_MSGIS0-3, CSR_MSGIR and CSR_MSGIE.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 3 +++
> target/loongarch/cpu.h | 10 ++++++++++
> target/loongarch/machine.c | 27 +++++++++++++++++++++++++--
> 3 files changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 0834e91f30..4792677086 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -186,6 +186,9 @@ FIELD(CSR_MERRCTL, ISMERR, 0, 1)
>
> #define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */
>
> +#define LOONGARCH_CSR_MSGIS(N) (0xa0 + N)
> +#define LOONGARCH_CSR_MSGIR 0xa4
> +
> /* Direct map windows CSRs*/
> #define LOONGARCH_CSR_DMW(N) (0x180 + N)
> FIELD(CSR_DMW, PLV0, 0, 1)
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 56fc4a1459..208d3e0cd3 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -233,6 +233,12 @@ FIELD(TLB_MISC, ASID, 1, 10)
> FIELD(TLB_MISC, VPPN, 13, 35)
> FIELD(TLB_MISC, PS, 48, 6)
>
> +/*Msg interrupt registers */
> +FIELD(CSR_MSGIS, IS, 0, 63)
> +FIELD(CSR_MSGIR, INTNUM, 0, 8)
> +FIELD(CSR_MSGIR, ACTIVE, 31, 1)
> +FIELD(CSR_MSGIE, PT, 0, 8)
> +
> #define LSX_LEN (128)
> #define LASX_LEN (256)
>
> @@ -350,6 +356,10 @@ typedef struct CPUArchState {
> uint64_t CSR_DBG;
> uint64_t CSR_DERA;
> uint64_t CSR_DSAVE;
> + /* Msg interrupt registers */
> + uint64_t CSR_MSGIS[4];
It will better if there is macro replaced with 4.
> + uint64_t CSR_MSGIR;
> + uint64_t CSR_MSGIE;
> struct {
> uint64_t guest_addr;
> } stealtime;
> diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
> index 4e70f5c879..9eddb9341a 100644
> --- a/target/loongarch/machine.c
> +++ b/target/loongarch/machine.c
> @@ -10,6 +10,7 @@
> #include "migration/cpu.h"
> #include "system/tcg.h"
> #include "vec.h"
> +#include "hw/loongarch/virt.h"
>
> static const VMStateDescription vmstate_fpu_reg = {
> .name = "fpu_reg",
> @@ -45,6 +46,27 @@ static const VMStateDescription vmstate_fpu = {
> },
> };
>
> +static bool msg_needed(void *opaque)
> +{
> + MachineState *ms = MACHINE(qdev_get_machine());
> + LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
> +
> + return !!(lvms->misc_feature & BIT(IOCSRF_AVEC));
how about use virt_has_avecintc() like this?
return virt_has_avecintc(lvms);
> +}
> +
> +static const VMStateDescription vmstate_msg = {
> + .name = "cpu/msg",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = msg_needed,
> + .fields = (const VMStateField[]) {
> + VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, 4),
ditto, it will be better if there is macro replaced with 4.
Regards
Bibo Mao
> + VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
> + VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> static const VMStateDescription vmstate_lsxh_reg = {
> .name = "lsxh_reg",
> .version_id = 1,
> @@ -168,8 +190,8 @@ static const VMStateDescription vmstate_tlb = {
> /* LoongArch CPU state */
> const VMStateDescription vmstate_loongarch_cpu = {
> .name = "cpu",
> - .version_id = 3,
> - .minimum_version_id = 3,
> + .version_id = 4,
> + .minimum_version_id = 4,
> .fields = (const VMStateField[]) {
> VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
> VMSTATE_UINTTL(env.pc, LoongArchCPU),
> @@ -245,6 +267,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
> &vmstate_tlb,
> #endif
> &vmstate_lbt,
> + &vmstate_msg,
> NULL
> }
> };
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 06/11] hw/loongarch: AVEC controller add a MemoryRegion
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (4 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 05/11] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-11 8:59 ` [PATCH v5 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
the AVEC controller use [2fe00000-2ff000000) Memory.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 24 ++++++++++++++++++++
hw/loongarch/virt.c | 39 +++++++++++++++++++++++++++++++-
include/hw/intc/loongarch_avec.h | 1 +
include/hw/loongarch/virt.h | 1 +
include/hw/pci-host/ls7a.h | 2 ++
5 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 5a3e7ecc03..253bab5461 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -17,6 +17,24 @@
#include "trace.h"
#include "hw/qdev-properties.h"
+static uint64_t loongarch_avec_mem_read(void *opaque,
+ hwaddr addr, unsigned size)
+{
+ return 0;
+}
+
+static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ return;
+}
+
+
+static const MemoryRegionOps loongarch_avec_ops = {
+ .read = loongarch_avec_mem_read,
+ .write = loongarch_avec_mem_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
{
@@ -39,6 +57,12 @@ static void loongarch_avec_unrealize(DeviceState *dev)
static void loongarch_avec_init(Object *obj)
{
+ LoongArchAVECState *s = LOONGARCH_AVEC(obj);
+ SysBusDevice *shd = SYS_BUS_DEVICE(obj);
+ memory_region_init_io(&s->avec_mmio, OBJECT(s), &loongarch_avec_ops,
+ s, TYPE_LOONGARCH_AVEC, VIRT_AVEC_MSG_OFFSET);
+ sysbus_init_mmio(shd, &s->avec_mmio);
+ msi_nonbroken = true;
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 0d05404eb5..b420d1def9 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -28,6 +28,7 @@
#include "hw/intc/loongarch_extioi.h"
#include "hw/intc/loongarch_pch_pic.h"
#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_avec.h"
#include "hw/pci-host/ls7a.h"
#include "hw/pci-host/gpex.h"
#include "hw/misc/unimp.h"
@@ -382,7 +383,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
static void virt_irq_init(LoongArchVirtMachineState *lvms)
{
DeviceState *pch_pic, *pch_msi;
- DeviceState *ipi, *extioi;
+ DeviceState *ipi, *extioi, *avec;
SysBusDevice *d;
int i, start, num;
@@ -428,6 +429,33 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
* +--------+ +---------+ +---------+
* | UARTs | | Devices | | Devices |
* +--------+ +---------+ +---------+
+ *
+ *
+ * Advanced Extended IRQ model
+ *
+ * +-----+ +---------------------------------+ +-------+
+ * | IPI | --> | CPUINTC | <-- | Timer |
+ * +-----+ +---------------------------------+ +-------+
+ * ^ ^ ^
+ * | | |
+ * +-------------+ +----------+ +---------+ +-------+
+ * | EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs |
+ * +-------------+ +----------+ +---------+ +-------+
+ * ^ ^ ^
+ * | | |
+ * +---------+ +---------+ |
+ * | PCH-PIC | | PCH-MSI | |
+ * +---------+ +---------+ |
+ * ^ ^ ^ |
+ * | | | |
+ * +---------+ +---------+ +---------+
+ * | Devices | | PCH-LPC | | Devices |
+ * +---------+ +---------+ +---------+
+ * ^
+ * |
+ * +---------+
+ * | Devices |
+ * +---------+
*/
/* Create IPI device */
@@ -435,6 +463,15 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
lvms->ipi = ipi;
sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+ /* Create AVEC device*/
+ if (virt_has_avecintc(lvms)) {
+ avec = qdev_new(TYPE_LOONGARCH_AVEC);
+ lvms->avec = avec;
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
+ memory_region_add_subregion(get_system_memory(), VIRT_AVEC_BASE,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
+ }
+
/* Create EXTIOI device */
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
lvms->extioi = extioi;
diff --git a/include/hw/intc/loongarch_avec.h b/include/hw/intc/loongarch_avec.h
index 92e2ca9590..3e8cf7d2c1 100644
--- a/include/hw/intc/loongarch_avec.h
+++ b/include/hw/intc/loongarch_avec.h
@@ -23,6 +23,7 @@ typedef struct AVECCore {
struct LoongArchAVECState {
SysBusDevice parent_obj;
+ MemoryRegion avec_mmio;
AVECCore *cpu;
uint32_t num_cpu;
};
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 68b8e92e99..bc3cee705d 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -89,6 +89,7 @@ struct LoongArchVirtMachineState {
unsigned int memmap_entries;
uint64_t misc_feature;
uint64_t misc_status;
+ DeviceState *avec;
};
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index 79d4ea8501..199f47ecc0 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -24,6 +24,8 @@
#define VIRT_PCH_REG_BASE 0x10000000UL
#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE)
#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
+#define VIRT_AVEC_MSG_OFFSET 0x1000000UL
+#define VIRT_AVEC_BASE (VIRT_PCH_MSI_ADDR_LOW - VIRT_AVEC_MSG_OFFSET)
#define VIRT_PCH_REG_SIZE 0x400
#define VIRT_PCH_MSI_SIZE 0x8
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 07/11] hw/loongarch: Implement avec controller imput and output pins
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (5 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 06/11] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-14 9:38 ` Bibo Mao
2025-07-11 8:59 ` [PATCH v5 08/11] hw/loongarch: Implement avec set irq Song Gao
` (3 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
the AVEC controller supports 256*256 irqs input, all the irqs connect CPU INT_AVEC irq
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 20 ++++++++++++++++++++
hw/loongarch/virt.c | 11 +++++++++--
target/loongarch/cpu.h | 3 ++-
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 253bab5461..1f9f376898 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -38,7 +38,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
{
+ LoongArchAVECState *s = LOONGARCH_AVEC(dev);
LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
+ MachineState *machine = MACHINE(qdev_get_machine());
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ const CPUArchIdList *id_list;
+ int i;
Error *local_err = NULL;
lac->parent_realize(dev, &local_err);
@@ -47,6 +52,21 @@ static void loongarch_avec_realize(DeviceState *dev, Error **errp)
return;
}
+ assert(mc->possible_cpu_arch_ids);
+ id_list = mc->possible_cpu_arch_ids(machine);
+ s->num_cpu = id_list->len;
+ s->cpu = g_new(AVECCore, s->num_cpu);
+ if (s->cpu == NULL) {
+ error_setg(errp, "Memory allocation for AVECCore fail");
+ return;
+ }
+
+ for (i = 0; i < s->num_cpu; i++) {
+ s->cpu[i].arch_id = id_list->cpus[i].arch_id;
+ s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
+ qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
+ }
+
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index b420d1def9..e3ab165cc5 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -380,7 +380,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
}
}
-static void virt_irq_init(LoongArchVirtMachineState *lvms)
+static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
{
DeviceState *pch_pic, *pch_msi;
DeviceState *ipi, *extioi, *avec;
@@ -470,6 +470,13 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
memory_region_add_subregion(get_system_memory(), VIRT_AVEC_BASE,
sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
+ CPUState *cpu_state;
+ DeviceState *cpudev;
+ for (int cpu = 0; cpu < ms->smp.cpus; cpu++) {
+ cpu_state = qemu_get_cpu(cpu);
+ cpudev = DEVICE(cpu_state);
+ qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));
+ }
}
/* Create EXTIOI device */
@@ -838,7 +845,7 @@ static void virt_init(MachineState *machine)
}
/* Initialize the IO interrupt subsystem */
- virt_irq_init(lvms);
+ virt_irq_init(lvms, machine);
lvms->machine_done.notify = virt_done;
qemu_add_machine_init_done_notifier(&lvms->machine_done);
/* connect powerdown request */
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 208d3e0cd3..556e9dabb9 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -217,9 +217,10 @@ FIELD(CSR_CRMD, WE, 9, 1)
extern const char * const regnames[32];
extern const char * const fregnames[32];
-#define N_IRQS 13
+#define N_IRQS 15
#define IRQ_TIMER 11
#define IRQ_IPI 12
+#define INT_AVEC 14
#define LOONGARCH_STLB 2048 /* 2048 STLB */
#define LOONGARCH_MTLB 64 /* 64 MTLB */
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 07/11] hw/loongarch: Implement avec controller imput and output pins
2025-07-11 8:59 ` [PATCH v5 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-07-14 9:38 ` Bibo Mao
0 siblings, 0 replies; 20+ messages in thread
From: Bibo Mao @ 2025-07-14 9:38 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> the AVEC controller supports 256*256 irqs input, all the irqs connect CPU INT_AVEC irq
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 20 ++++++++++++++++++++
> hw/loongarch/virt.c | 11 +++++++++--
> target/loongarch/cpu.h | 3 ++-
> 3 files changed, 31 insertions(+), 3 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 253bab5461..1f9f376898 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -38,7 +38,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>
> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
> {
> + LoongArchAVECState *s = LOONGARCH_AVEC(dev);
> LoongArchAVECClass *lac = LOONGARCH_AVEC_GET_CLASS(dev);
> + MachineState *machine = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(machine);
> + const CPUArchIdList *id_list;
> + int i;
>
> Error *local_err = NULL;
> lac->parent_realize(dev, &local_err);
> @@ -47,6 +52,21 @@ static void loongarch_avec_realize(DeviceState *dev, Error **errp)
> return;
> }
>
> + assert(mc->possible_cpu_arch_ids);
> + id_list = mc->possible_cpu_arch_ids(machine);
> + s->num_cpu = id_list->len;
> + s->cpu = g_new(AVECCore, s->num_cpu);
> + if (s->cpu == NULL) {
> + error_setg(errp, "Memory allocation for AVECCore fail");
> + return;
> + }
> +
> + for (i = 0; i < s->num_cpu; i++) {
> + s->cpu[i].arch_id = id_list->cpus[i].arch_id;
> + s->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
> + qdev_init_gpio_out(dev, &s->cpu[i].parent_irq, 1);
> + }
> +
> return;
> }
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index b420d1def9..e3ab165cc5 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -380,7 +380,7 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
> }
> }
>
> -static void virt_irq_init(LoongArchVirtMachineState *lvms)
> +static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
The extra parameter machine is not necessary, it can be acquired from
the first parameter lvms, such as:
MachineState *ms = MACHINE(lvms);
> {
> DeviceState *pch_pic, *pch_msi;
> DeviceState *ipi, *extioi, *avec;
> @@ -470,6 +470,13 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
> sysbus_realize_and_unref(SYS_BUS_DEVICE(avec), &error_fatal);
> memory_region_add_subregion(get_system_memory(), VIRT_AVEC_BASE,
> sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
> + CPUState *cpu_state;
> + DeviceState *cpudev;
It is strange to declare new variable between sentences, I think it
should be put in the beginning of function.
Regards
Bibo Mao
> + for (int cpu = 0; cpu < ms->smp.cpus; cpu++) {
> + cpu_state = qemu_get_cpu(cpu);
> + cpudev = DEVICE(cpu_state);
> + qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));
> + }
> }
>
> /* Create EXTIOI device */
> @@ -838,7 +845,7 @@ static void virt_init(MachineState *machine)
> }
>
> /* Initialize the IO interrupt subsystem */
> - virt_irq_init(lvms);
> + virt_irq_init(lvms, machine);
> lvms->machine_done.notify = virt_done;
> qemu_add_machine_init_done_notifier(&lvms->machine_done);
> /* connect powerdown request */
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 208d3e0cd3..556e9dabb9 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -217,9 +217,10 @@ FIELD(CSR_CRMD, WE, 9, 1)
> extern const char * const regnames[32];
> extern const char * const fregnames[32];
>
> -#define N_IRQS 13
> +#define N_IRQS 15
> #define IRQ_TIMER 11
> #define IRQ_IPI 12
> +#define INT_AVEC 14
>
> #define LOONGARCH_STLB 2048 /* 2048 STLB */
> #define LOONGARCH_MTLB 64 /* 64 MTLB */
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 08/11] hw/loongarch: Implement avec set irq
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (6 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 07/11] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-14 9:29 ` Bibo Mao
2025-08-28 8:34 ` Bibo Mao
2025-07-11 8:59 ` [PATCH v5 09/11] target/loongarch: CPU enable msg interrupts Song Gao
` (2 subsequent siblings)
10 siblings, 2 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Implement avec set irq and update CSR_MSIS.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 1f9f376898..af6c75c4a9 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -16,6 +16,12 @@
#include "migration/vmstate.h"
#include "trace.h"
#include "hw/qdev-properties.h"
+#include "target/loongarch/cpu.h"
+
+/* msg addr field */
+FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
+FIELD(MSG_ADDR, CPU_NUM, 12, 8)
+FIELD(MSG_ADDR, FIX, 28, 12)
static uint64_t loongarch_avec_mem_read(void *opaque,
hwaddr addr, unsigned size)
@@ -23,12 +29,36 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
return 0;
}
+static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int irq_num, int level)
+{
+ MachineState *machine = MACHINE(qdev_get_machine());
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ const CPUArchIdList *id_list = NULL;
+ CPUState *cpu;
+ CPULoongArchState *env;
+
+ assert(mc->possible_cpu_arch_ids(machine));
+ id_list = mc->possible_cpu_arch_ids(machine);
+ cpu = id_list->cpus[cpu_num].cpu;
+ env = &LOONGARCH_CPU(cpu)->env;
+
+ if (level) {
+ set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
+ }
+ qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
+}
+
static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
- return;
-}
+ int irq_num, cpu_num = 0;
+ LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+ uint64_t msg_addr = addr + VIRT_AVEC_BASE;
+ cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+ irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+ avec_set_irq(s, cpu_num, irq_num, 1);
+}
static const MemoryRegionOps loongarch_avec_ops = {
.read = loongarch_avec_mem_read,
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 08/11] hw/loongarch: Implement avec set irq
2025-07-11 8:59 ` [PATCH v5 08/11] hw/loongarch: Implement avec set irq Song Gao
@ 2025-07-14 9:29 ` Bibo Mao
2025-07-17 8:33 ` gaosong
2025-08-28 8:34 ` Bibo Mao
1 sibling, 1 reply; 20+ messages in thread
From: Bibo Mao @ 2025-07-14 9:29 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> Implement avec set irq and update CSR_MSIS.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 34 ++++++++++++++++++++++++++++++++--
> 1 file changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 1f9f376898..af6c75c4a9 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -16,6 +16,12 @@
> #include "migration/vmstate.h"
> #include "trace.h"
> #include "hw/qdev-properties.h"
> +#include "target/loongarch/cpu.h"
> +
> +/* msg addr field */
> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
> +FIELD(MSG_ADDR, FIX, 28, 12)
>
> static uint64_t loongarch_avec_mem_read(void *opaque,
> hwaddr addr, unsigned size)
> @@ -23,12 +29,36 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
> return 0;
> }
>
> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int irq_num, int level)
> +{
> + MachineState *machine = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(machine);
> + const CPUArchIdList *id_list = NULL;
> + CPUState *cpu;
> + CPULoongArchState *env;
> +
> + assert(mc->possible_cpu_arch_ids(machine));
> + id_list = mc->possible_cpu_arch_ids(machine);
> + cpu = id_list->cpus[cpu_num].cpu;
> + env = &LOONGARCH_CPU(cpu)->env;
> +
> + if (level) {
> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
> + }
> + qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
> +}
> +
> static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
> uint64_t val, unsigned size)
> {
> - return;
> -}
> + int irq_num, cpu_num = 0;
> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> + uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>
> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
Here is physical cpuid rather than logic cpu index. We need convert
physical cpuid to logic cpu index.
Regards
Bibo Mao
> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> + avec_set_irq(s, cpu_num, irq_num, 1);
> +}
>
> static const MemoryRegionOps loongarch_avec_ops = {
> .read = loongarch_avec_mem_read,
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 08/11] hw/loongarch: Implement avec set irq
2025-07-14 9:29 ` Bibo Mao
@ 2025-07-17 8:33 ` gaosong
0 siblings, 0 replies; 20+ messages in thread
From: gaosong @ 2025-07-17 8:33 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/7/14 下午5:29, Bibo Mao 写道:
>
>
> On 2025/7/11 下午4:59, Song Gao wrote:
>> Implement avec set irq and update CSR_MSIS.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/intc/loongarch_avec.c | 34 ++++++++++++++++++++++++++++++++--
>> 1 file changed, 32 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index 1f9f376898..af6c75c4a9 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -16,6 +16,12 @@
>> #include "migration/vmstate.h"
>> #include "trace.h"
>> #include "hw/qdev-properties.h"
>> +#include "target/loongarch/cpu.h"
>> +
>> +/* msg addr field */
>> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
>> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
>> +FIELD(MSG_ADDR, FIX, 28, 12)
>> static uint64_t loongarch_avec_mem_read(void *opaque,
>> hwaddr addr, unsigned size)
>> @@ -23,12 +29,36 @@ static uint64_t loongarch_avec_mem_read(void
>> *opaque,
>> return 0;
>> }
>> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int
>> irq_num, int level)
>> +{
>> + MachineState *machine = MACHINE(qdev_get_machine());
>> + MachineClass *mc = MACHINE_GET_CLASS(machine);
>> + const CPUArchIdList *id_list = NULL;
>> + CPUState *cpu;
>> + CPULoongArchState *env;
>> +
>> + assert(mc->possible_cpu_arch_ids(machine));
>> + id_list = mc->possible_cpu_arch_ids(machine);
>> + cpu = id_list->cpus[cpu_num].cpu;
>> + env = &LOONGARCH_CPU(cpu)->env;
>> +
>> + if (level) {
>> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>> + }
>> + qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
>> +}
>> +
>> static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
>> uint64_t val, unsigned size)
>> {
>> - return;
>> -}
>> + int irq_num, cpu_num = 0;
>> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> + uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> Here is physical cpuid rather than logic cpu index. We need convert
> physical cpuid to logic cpu index.
How about the following code;
+ CPUState * cpu = cpu_by_arch_id(cpu_num);
+ cpu_num = cpu->cpu_index;
or like the IPI device add an function pointer in LoongsonIPICommonClass
LoongsonIPICommonClass {
[..]
int (*cpu_by_arch_id)(LoongsonIPICommonState *lics, int64_t id,
int *index, CPUState **pcs);
[...]
Thanks.
Song Gao
>
> Regards
> Bibo Mao
>> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> + avec_set_irq(s, cpu_num, irq_num, 1);
>> +}
>> static const MemoryRegionOps loongarch_avec_ops = {
>> .read = loongarch_avec_mem_read,
>>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v5 08/11] hw/loongarch: Implement avec set irq
2025-07-11 8:59 ` [PATCH v5 08/11] hw/loongarch: Implement avec set irq Song Gao
2025-07-14 9:29 ` Bibo Mao
@ 2025-08-28 8:34 ` Bibo Mao
1 sibling, 0 replies; 20+ messages in thread
From: Bibo Mao @ 2025-08-28 8:34 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> Implement avec set irq and update CSR_MSIS.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 34 ++++++++++++++++++++++++++++++++--
> 1 file changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 1f9f376898..af6c75c4a9 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -16,6 +16,12 @@
> #include "migration/vmstate.h"
> #include "trace.h"
> #include "hw/qdev-properties.h"
> +#include "target/loongarch/cpu.h"
> +
> +/* msg addr field */
> +FIELD(MSG_ADDR, IRQ_NUM, 4, 8)
> +FIELD(MSG_ADDR, CPU_NUM, 12, 8)
> +FIELD(MSG_ADDR, FIX, 28, 12)
>
> static uint64_t loongarch_avec_mem_read(void *opaque,
> hwaddr addr, unsigned size)
> @@ -23,12 +29,36 @@ static uint64_t loongarch_avec_mem_read(void *opaque,
> return 0;
> }
>
> +static void avec_set_irq(LoongArchAVECState *s, int cpu_num, int irq_num, int level)
> +{
> + MachineState *machine = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(machine);
> + const CPUArchIdList *id_list = NULL;
> + CPUState *cpu;
> + CPULoongArchState *env;
> +
> + assert(mc->possible_cpu_arch_ids(machine));
> + id_list = mc->possible_cpu_arch_ids(machine);
> + cpu = id_list->cpus[cpu_num].cpu;
> + env = &LOONGARCH_CPU(cpu)->env;
> +
> + if (level) {
> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
After a second thought, it has problem in KVM mode. In KVM mode, AVEC
irqchip is hardware-assisted rather than SW emulated.
CSR register CSR_MSGIS[] can only be set on vCPU itself and cannot be
set by other QEMU threads, since it will be overwritten when vCPU is
kicked out/in.
Maybe we need further investigation about how to inject CPU IRQ such as
IPI/timer, and then inject AVEC sub-irqchip IRQ.
Regards
Bibo Mao
> + }
> + qemu_set_irq(s->cpu[cpu_num].parent_irq, level);
> +}
> +
> static void loongarch_avec_mem_write(void *opaque, hwaddr addr,
> uint64_t val, unsigned size)
> {
> - return;
> -}
> + int irq_num, cpu_num = 0;
> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> + uint64_t msg_addr = addr + VIRT_AVEC_BASE;
>
> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> + avec_set_irq(s, cpu_num, irq_num, 1);
> +}
>
> static const MemoryRegionOps loongarch_avec_ops = {
> .read = loongarch_avec_mem_read,
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 09/11] target/loongarch: CPU enable msg interrupts.
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (7 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 08/11] hw/loongarch: Implement avec set irq Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-14 9:46 ` Bibo Mao
2025-07-11 8:59 ` [PATCH v5 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
2025-07-11 8:59 ` [PATCH v5 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
10 siblings, 1 reply; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
when loongarch cpu set irq is INT_AVEC, we need set CSR_ESTAT.MSGINT bit.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 6 ++++--
target/loongarch/cpu.c | 10 +++++++++-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 4792677086..6ec13d13d1 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -34,11 +34,13 @@ FIELD(CSR_MISC, ALCL, 12, 4)
FIELD(CSR_MISC, DWPL, 16, 3)
#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
-FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, LIE, 0, 15) /*bit 15 is msg interrupt enabled */
+FIELD(CSR_ECFG, MSGINT, 14, 1)
FIELD(CSR_ECFG, VS, 16, 3)
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
-FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, IS, 0, 15) /*bit 15 is msg interrupt enabled */
+FIELD(CSR_ESTAT, MSGINT, 14, 1)
FIELD(CSR_ESTAT, ECODE, 16, 6)
FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index abad84c054..9e21ed1d07 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -130,7 +130,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
if (kvm_enabled()) {
kvm_loongarch_set_interrupt(cpu, irq, level);
} else if (tcg_enabled()) {
- env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+ /* do INTC_AVEC irqs */
+ if (irq == INT_AVEC) {
+ irq = find_first_bit(env->CSR_MSGIS, 256);
+ if (irq < 256) {
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
+ }
+ } else {
+ env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+ }
if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v5 09/11] target/loongarch: CPU enable msg interrupts.
2025-07-11 8:59 ` [PATCH v5 09/11] target/loongarch: CPU enable msg interrupts Song Gao
@ 2025-07-14 9:46 ` Bibo Mao
0 siblings, 0 replies; 20+ messages in thread
From: Bibo Mao @ 2025-07-14 9:46 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/7/11 下午4:59, Song Gao wrote:
> when loongarch cpu set irq is INT_AVEC, we need set CSR_ESTAT.MSGINT bit.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 6 ++++--
> target/loongarch/cpu.c | 10 +++++++++-
> 2 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 4792677086..6ec13d13d1 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -34,11 +34,13 @@ FIELD(CSR_MISC, ALCL, 12, 4)
> FIELD(CSR_MISC, DWPL, 16, 3)
>
> #define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
> -FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, LIE, 0, 15) /*bit 15 is msg interrupt enabled */
> +FIELD(CSR_ECFG, MSGINT, 14, 1)
> FIELD(CSR_ECFG, VS, 16, 3)
>
> #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
> -FIELD(CSR_ESTAT, IS, 0, 13)
> +FIELD(CSR_ESTAT, IS, 0, 15) /*bit 15 is msg interrupt enabled */
> +FIELD(CSR_ESTAT, MSGINT, 14, 1)
> FIELD(CSR_ESTAT, ECODE, 16, 6)
> FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index abad84c054..9e21ed1d07 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -130,7 +130,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> if (kvm_enabled()) {
> kvm_loongarch_set_interrupt(cpu, irq, level);
> } else if (tcg_enabled()) {
> - env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
> + /* do INTC_AVEC irqs */
> + if (irq == INT_AVEC) {
> + irq = find_first_bit(env->CSR_MSGIS, 256);
> + if (irq < 256) {
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> + }
Why is there such checking for bitmap? Can the original sentence work?
env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
This piece of code is a little strange.
Regards
Bibo Mao
> + } else {
> + env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
> + }
> if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
> cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> } else {
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v5 10/11] target/loongarch:Implement csrrd CSR_MSGIR register
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (8 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 09/11] target/loongarch: CPU enable msg interrupts Song Gao
@ 2025-07-11 8:59 ` Song Gao
2025-07-11 8:59 ` [PATCH v5 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces Song Gao
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
implement the read-clear feature for CSR_MSGIR register.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/csr.c | 5 +++++
target/loongarch/tcg/csr_helper.c | 21 +++++++++++++++++++
target/loongarch/tcg/helper.h | 1 +
.../tcg/insn_trans/trans_privileged.c.inc | 1 +
4 files changed, 28 insertions(+)
diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c
index 7ea0a30450..f973780bba 100644
--- a/target/loongarch/csr.c
+++ b/target/loongarch/csr.c
@@ -97,6 +97,11 @@ static CSRInfo csr_info[] = {
CSR_OFF(DBG),
CSR_OFF(DERA),
CSR_OFF(DSAVE),
+ CSR_OFF_ARRAY(MSGIS, 0),
+ CSR_OFF_ARRAY(MSGIS, 1),
+ CSR_OFF_ARRAY(MSGIS, 2),
+ CSR_OFF_ARRAY(MSGIS, 3),
+ CSR_OFF(MSGIR),
};
CSRInfo *get_csr(unsigned int csr_num)
diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c
index 2942d7feb8..48996b62f7 100644
--- a/target/loongarch/tcg/csr_helper.c
+++ b/target/loongarch/tcg/csr_helper.c
@@ -68,6 +68,27 @@ target_ulong helper_csrrd_tval(CPULoongArchState *env)
return cpu_loongarch_get_constant_timer_ticks(cpu);
}
+target_ulong helper_csrrd_msgir(CPULoongArchState *env)
+{
+ int irq, new;
+
+ irq = find_first_bit(env->CSR_MSGIS, 256);
+ if (irq < 256) {
+ clear_bit(irq, env->CSR_MSGIS);
+ new = find_first_bit(env->CSR_MSGIS, 256);
+ if (new < 256) {
+ return irq;
+ }
+
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+ } else {
+ /* bit 31 set 1 for no invalid irq */
+ irq = BIT(31);
+ }
+
+ return irq;
+}
+
target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
{
int64_t old_v = env->CSR_ESTAT;
diff --git a/target/loongarch/tcg/helper.h b/target/loongarch/tcg/helper.h
index 1d5cb0198c..db57dbfc16 100644
--- a/target/loongarch/tcg/helper.h
+++ b/target/loongarch/tcg/helper.h
@@ -100,6 +100,7 @@ DEF_HELPER_1(rdtime_d, i64, env)
DEF_HELPER_1(csrrd_pgd, i64, env)
DEF_HELPER_1(csrrd_cpuid, i64, env)
DEF_HELPER_1(csrrd_tval, i64, env)
+DEF_HELPER_1(csrrd_msgir, i64, env)
DEF_HELPER_2(csrwr_stlbps, i64, env, tl)
DEF_HELPER_2(csrwr_estat, i64, env, tl)
DEF_HELPER_2(csrwr_asid, i64, env, tl)
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index ecbfe23b63..2619b5342b 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -83,6 +83,7 @@ void loongarch_csr_translate_init(void)
SET_CSR_FUNC(TCFG, NULL, gen_helper_csrwr_tcfg);
SET_CSR_FUNC(TVAL, gen_helper_csrrd_tval, NULL);
SET_CSR_FUNC(TICLR, NULL, gen_helper_csrwr_ticlr);
+ SET_CSR_FUNC(MSGIR, gen_helper_csrrd_msgir, NULL);
}
#undef SET_CSR_FUNC
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v5 11/11] hw/loongarch: Implement AVEC plug/unplug interfaces
2025-07-11 8:59 [PATCH v5 00/11] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (9 preceding siblings ...)
2025-07-11 8:59 ` [PATCH v5 10/11] target/loongarch:Implement csrrd CSR_MSGIR register Song Gao
@ 2025-07-11 8:59 ` Song Gao
10 siblings, 0 replies; 20+ messages in thread
From: Song Gao @ 2025-07-11 8:59 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
when cpu added, connect avec irq to cpu INT_AVEC irq pin.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 71 ++++++++++++++++++++++++++++++++++++++++
hw/loongarch/virt.c | 11 +++++++
2 files changed, 82 insertions(+)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index af6c75c4a9..820d6655ef 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -116,14 +116,81 @@ static void loongarch_avec_init(Object *obj)
return;
}
+static AVECCore *loongarch_avec_get_cpu(LoongArchAVECState *s,
+ DeviceState *dev)
+{
+ CPUClass *k = CPU_GET_CLASS(dev);
+ uint64_t arch_id = k->get_arch_id(CPU(dev));
+ int i;
+
+ for (i = 0; i < s->num_cpu; i++) {
+ if (s->cpu[i].arch_id == arch_id) {
+ return &s->cpu[i];
+ }
+ }
+
+ return NULL;
+}
+
+static void loongarch_avec_cpu_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ AVECCore *core;
+ int index;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch AVEC: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+ core = loongarch_avec_get_cpu(s, dev);
+ if (!core) {
+ return;
+ }
+
+ core->cpu = CPU(dev);
+ index = core - s->cpu;
+
+ /* connect avec msg irq to cpu irq */
+ qdev_connect_gpio_out(DEVICE(s), index, qdev_get_gpio_in(dev, INT_AVEC));
+ return;
+}
+
+static void loongarch_avec_cpu_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ LoongArchAVECState *s = LOONGARCH_AVEC(hotplug_dev);
+ Object *obj = OBJECT(dev);
+ AVECCore *core;
+
+ if (!object_dynamic_cast(obj, TYPE_LOONGARCH_CPU)) {
+ warn_report("LoongArch AVEC: Invalid %s device type",
+ object_get_typename(obj));
+ return;
+ }
+
+ core = loongarch_avec_get_cpu(s, dev);
+
+ if (!core) {
+ return;
+ }
+
+ core->cpu = NULL;
+}
+
static void loongarch_avec_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
LoongArchAVECClass *lac = LOONGARCH_AVEC_CLASS(klass);
dc->unrealize = loongarch_avec_unrealize;
device_class_set_parent_realize(dc, loongarch_avec_realize,
&lac->parent_realize);
+ hc->plug = loongarch_avec_cpu_plug;
+ hc->unplug = loongarch_avec_cpu_unplug;
}
static const TypeInfo loongarch_avec_info = {
@@ -132,6 +199,10 @@ static const TypeInfo loongarch_avec_info = {
.instance_size = sizeof(LoongArchAVECState),
.instance_init = loongarch_avec_init,
.class_init = loongarch_avec_class_init,
+ .interfaces = (const InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ },
};
static void loongarch_avec_register_types(void)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e3ab165cc5..7ea9b58f15 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -377,6 +377,10 @@ static void virt_cpu_irq_init(LoongArchVirtMachineState *lvms)
&error_abort);
hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), DEVICE(cs),
&error_abort);
+ if (lvms->avec) {
+ hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), DEVICE(cs),
+ &error_abort);
+ }
}
}
@@ -1088,6 +1092,9 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
/* Notify ipi and extioi irqchip to remove interrupt routing to CPU */
hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->ipi), dev, &error_abort);
hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
+ if (lvms->avec) {
+ hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
+ }
/* Notify acpi ged CPU removed */
hotplug_handler_unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &error_abort);
@@ -1111,6 +1118,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
hotplug_handler_plug(HOTPLUG_HANDLER(lvms->extioi), dev, &error_abort);
}
+ if (lvms->avec) {
+ hotplug_handler_plug(HOTPLUG_HANDLER(lvms->avec), dev, &error_abort);
+ }
+
if (lvms->acpi_ged) {
hotplug_handler_plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev,
&error_abort);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread