* [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
` (8 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Use the IOCSRF_AVEC bit for avdance interrupt controller drivers
avecintc_enable[1] and set the default value of the MISC_FUNC_REG bit IOCSRM_AVEC_EN.
and set the default value of the MISC_FUNC_REG bit IOCSRM_AVEC_EN.
[1]:https://github.com/torvalds/linux/blob/master/drivers/irqchip/irq-loongarch-avec.c
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 4 ++++
target/loongarch/cpu.h | 2 ++
2 files changed, 6 insertions(+)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 1b504047db..90d4643721 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -548,6 +548,8 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
break;
case FEATURE_REG:
ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
+ /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
+ ret |= BIT(IOCSRF_AVEC);
if (kvm_enabled()) {
ret |= BIT(IOCSRF_VM);
}
@@ -573,6 +575,8 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
}
+ /* enable avec default */
+ ret |= BIT_ULL(IOCSRM_AVEC_EN);
break;
default:
g_assert_not_reached();
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 262bf87f7b..7cceec1204 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -31,6 +31,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
@@ -39,6 +40,7 @@
#define MISC_FUNC_REG 0x420
#define IOCSRM_EXTIOI_EN 48
#define IOCSRM_EXTIOI_INT_ENCODE 49
+#define IOCSRM_AVEC_EN 51
#define IOCSR_MEM_SIZE 0x428
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:46 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 03/10] loongarch: add a advance interrupt controller device Song Gao
` (7 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
LoongArchVirtMachinState add avecintc features, and
it use to check whether virt machine support advance interrupt controller
and default is on.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
include/hw/loongarch/virt.h | 9 +++++++++
2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 90d4643721..35643a4e0b 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -47,6 +47,23 @@
#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);
+}
+
static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -548,8 +565,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);
- /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
- ret |= BIT(IOCSRF_AVEC);
+ if (virt_is_avecintc_enabled(lvms)) {
+ ret |= BIT(IOCSRF_AVEC);
+ }
if (kvm_enabled()) {
ret |= BIT(IOCSRF_VM);
}
@@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
}
- /* enable avec default */
- ret |= BIT_ULL(IOCSRM_AVEC_EN);
+ if (virt_is_avecintc_enabled(lvms)) {
+ ret |= BIT_ULL(IOCSRM_AVEC_EN);
+ }
break;
default:
g_assert_not_reached();
@@ -1212,6 +1231,10 @@ 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.");
+ 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.");
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 2b7d19953f..3a81f048e8 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
Notifier powerdown_notifier;
OnOffAuto acpi;
OnOffAuto veiointc;
+ OnOffAuto avecintc;
char *oem_id;
char *oem_table_id;
DeviceState *acpi_ged;
@@ -70,6 +71,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
void virt_acpi_setup(LoongArchVirtMachineState *lvms);
void virt_fdt_setup(LoongArchVirtMachineState *lvms);
+static inline bool virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
+{
+ if (lvms->avecintc == ON_OFF_AUTO_OFF) {
+ 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] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
@ 2025-06-11 6:46 ` Bibo Mao
2025-06-13 7:54 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:46 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> LoongArchVirtMachinState add avecintc features, and
> it use to check whether virt machine support advance interrupt controller
> and default is on.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
> include/hw/loongarch/virt.h | 9 +++++++++
> 2 files changed, 36 insertions(+), 4 deletions(-)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 90d4643721..35643a4e0b 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -47,6 +47,23 @@
> #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);
> +}
> +
> static void virt_get_veiointc(Object *obj, Visitor *v, const char *name,
> void *opaque, Error **errp)
> {
> @@ -548,8 +565,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);
> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
> - ret |= BIT(IOCSRF_AVEC);
> + if (virt_is_avecintc_enabled(lvms)) {
> + ret |= BIT(IOCSRF_AVEC);
> + }
> if (kvm_enabled()) {
> ret |= BIT(IOCSRF_VM);
> }
> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
> }
> - /* enable avec default */
> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
> + if (virt_is_avecintc_enabled(lvms)) {
> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
> + }
Is it really that reading of MISC_FUNC_REG will return
BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
Where is the write operation with register MISC_FUNC_REG?
Regard
Bibo Mao
> break;
> default:
> g_assert_not_reached();
> @@ -1212,6 +1231,10 @@ 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.");
> + 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.");
> 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 2b7d19953f..3a81f048e8 100644
> --- a/include/hw/loongarch/virt.h
> +++ b/include/hw/loongarch/virt.h
> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
> Notifier powerdown_notifier;
> OnOffAuto acpi;
> OnOffAuto veiointc;
> + OnOffAuto avecintc;
> char *oem_id;
> char *oem_table_id;
> DeviceState *acpi_ged;
> @@ -70,6 +71,14 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>
> +static inline bool virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
> +{
> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
> + 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] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-11 6:46 ` Bibo Mao
@ 2025-06-13 7:54 ` gaosong
2025-06-16 1:09 ` Bibo Mao
0 siblings, 1 reply; 24+ messages in thread
From: gaosong @ 2025-06-13 7:54 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:46, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> LoongArchVirtMachinState add avecintc features, and
>> it use to check whether virt machine support advance interrupt
>> controller
>> and default is on.
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
>> include/hw/loongarch/virt.h | 9 +++++++++
>> 2 files changed, 36 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 90d4643721..35643a4e0b 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -47,6 +47,23 @@
>> #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);
>> +}
>> +
>> static void virt_get_veiointc(Object *obj, Visitor *v, const char
>> *name,
>> void *opaque, Error **errp)
>> {
>> @@ -548,8 +565,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);
>> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
>> - ret |= BIT(IOCSRF_AVEC);
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + ret |= BIT(IOCSRF_AVEC);
>> + }
>> if (kvm_enabled()) {
>> ret |= BIT(IOCSRF_VM);
>> }
>> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void
>> *opaque, hwaddr addr,
>> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>> }
>> - /* enable avec default */
>> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
>> + }
> Is it really that reading of MISC_FUNC_REG will return
> BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
>
no, it is IOCSRM_AVEC_EN after drivier enable avecintc.
static inline void avecintc_enable(void)
{
u64 value;
value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
value |= IOCSR_MISC_FUNC_AVEC_EN;
iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC);
}
my thought is that qemu has enabled avec by default,
so I just add a variable OnOffAuto avecintc on
LoongArchVirtMachineState,
> Where is the write operation with register MISC_FUNC_REG?
>
no, I will add it on v2?
how about add features and status on LoongArchVirtMachineState for the
macine misc fetureas and status?
like LoongArchExtIOICommonState
Thanks.
Song Gao
> Regard
> Bibo Mao
>> break;
>> default:
>> g_assert_not_reached();
>> @@ -1212,6 +1231,10 @@ 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.");
>> + 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.");
>> 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 2b7d19953f..3a81f048e8 100644
>> --- a/include/hw/loongarch/virt.h
>> +++ b/include/hw/loongarch/virt.h
>> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
>> Notifier powerdown_notifier;
>> OnOffAuto acpi;
>> OnOffAuto veiointc;
>> + OnOffAuto avecintc;
>> char *oem_id;
>> char *oem_table_id;
>> DeviceState *acpi_ged;
>> @@ -70,6 +71,14 @@
>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState,
>> LOONGARCH_VIRT_MACHINE)
>> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>> +static inline bool
>> virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
>> +{
>> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
>> + 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] 24+ messages in thread
* Re: [PATCH 02/10] loongarch: add virt feature avecintc support
2025-06-13 7:54 ` gaosong
@ 2025-06-16 1:09 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-16 1:09 UTC (permalink / raw)
To: gaosong; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/13 下午3:54, gaosong wrote:
> 在 2025/6/11 下午2:46, Bibo Mao 写道:
>>
>>
>> On 2025/6/9 下午6:48, Song Gao wrote:
>>> LoongArchVirtMachinState add avecintc features, and
>>> it use to check whether virt machine support advance interrupt
>>> controller
>>> and default is on.
>>>
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>> hw/loongarch/virt.c | 31 +++++++++++++++++++++++++++----
>>> include/hw/loongarch/virt.h | 9 +++++++++
>>> 2 files changed, 36 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>>> index 90d4643721..35643a4e0b 100644
>>> --- a/hw/loongarch/virt.c
>>> +++ b/hw/loongarch/virt.c
>>> @@ -47,6 +47,23 @@
>>> #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);
>>> +}
>>> +
>>> static void virt_get_veiointc(Object *obj, Visitor *v, const char
>>> *name,
>>> void *opaque, Error **errp)
>>> {
>>> @@ -548,8 +565,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);
>>> - /*TODO: check bit IOCSRF_AVEC with virt_is_avec_enabled */
>>> - ret |= BIT(IOCSRF_AVEC);
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + ret |= BIT(IOCSRF_AVEC);
>>> + }
>>> if (kvm_enabled()) {
>>> ret |= BIT(IOCSRF_VM);
>>> }
>>> @@ -575,8 +593,9 @@ static MemTxResult virt_iocsr_misc_read(void
>>> *opaque, hwaddr addr,
>>> if (features & BIT(EXTIOI_ENABLE_INT_ENCODE)) {
>>> ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
>>> }
>>> - /* enable avec default */
>>> - ret |= BIT_ULL(IOCSRM_AVEC_EN);
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + ret |= BIT_ULL(IOCSRM_AVEC_EN);
>>> + }
>> Is it really that reading of MISC_FUNC_REG will return
>> BIT_ULL(IOCSRM_AVEC_EN) if there is avec?
>>
> no, it is IOCSRM_AVEC_EN after drivier enable avecintc.
> static inline void avecintc_enable(void)
> {
> u64 value;
>
> value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC);
> value |= IOCSR_MISC_FUNC_AVEC_EN;
> iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC);
> }
>
> my thought is that qemu has enabled avec by default,
> so I just add a variable OnOffAuto avecintc on
> LoongArchVirtMachineState,
>> Where is the write operation with register MISC_FUNC_REG?
>>
> no, I will add it on v2?
>
> how about add features and status on LoongArchVirtMachineState for the
> macine misc fetureas and status?
> like LoongArchExtIOICommonState
That sounds good to me.
Regards
Bibo Mao
>
> Thanks.
> Song Gao
>> Regard
>> Bibo Mao
>>> break;
>>> default:
>>> g_assert_not_reached();
>>> @@ -1212,6 +1231,10 @@ 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.");
>>> + 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.");
>>> 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 2b7d19953f..3a81f048e8 100644
>>> --- a/include/hw/loongarch/virt.h
>>> +++ b/include/hw/loongarch/virt.h
>>> @@ -50,6 +50,7 @@ struct LoongArchVirtMachineState {
>>> Notifier powerdown_notifier;
>>> OnOffAuto acpi;
>>> OnOffAuto veiointc;
>>> + OnOffAuto avecintc;
>>> char *oem_id;
>>> char *oem_table_id;
>>> DeviceState *acpi_ged;
>>> @@ -70,6 +71,14 @@
>>> OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState,
>>> LOONGARCH_VIRT_MACHINE)
>>> void virt_acpi_setup(LoongArchVirtMachineState *lvms);
>>> void virt_fdt_setup(LoongArchVirtMachineState *lvms);
>>> +static inline bool
>>> virt_is_avecintc_enabled(LoongArchVirtMachineState *lvms)
>>> +{
>>> + if (lvms->avecintc == ON_OFF_AUTO_OFF) {
>>> + 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] 24+ messages in thread
* [PATCH 03/10] loongarch: add a advance interrupt controller device
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
2025-06-09 10:48 ` [PATCH 01/10] hw/loongarch: add a new type iocsr read for Avdance interrupt controller Song Gao
2025-06-09 10:48 ` [PATCH 02/10] loongarch: add virt feature avecintc support Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 04/10] target/loongarch: add msg interrupt CSR registers Song Gao
` (6 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 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 602da304b0..6c7c0c6468 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -74,3 +74,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c', 'loongarch_pic_common.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c', 'loongarch_extioi_common.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..3c68593a7c
--- /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[NR_VECTORS];
+ 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] 24+ messages in thread
* [PATCH 04/10] target/loongarch: add msg interrupt CSR registers
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (2 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 03/10] loongarch: add a advance interrupt controller device Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
` (5 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 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.c | 7 +++++++
target/loongarch/cpu.h | 10 ++++++++++
target/loongarch/machine.c | 5 +++++
3 files changed, 22 insertions(+)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index abad84c054..bde9f917fc 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -523,6 +523,13 @@ static void loongarch_la464_initfn(Object *obj)
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_WAYS, 7);
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, STLB_SETS, 8);
+ env->CSR_MSGIS[0] = 0;
+ env->CSR_MSGIS[1] = 0;
+ env->CSR_MSGIS[2] = 0;
+ env->CSR_MSGIS[3] = 0;
+ env->CSR_MSGIR = 0;
+ env->CSR_MSGIE = 0;
+
loongarch_la464_init_csr(obj);
loongarch_cpu_post_init(obj);
}
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 7cceec1204..a1918a85da 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -256,6 +256,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)
@@ -373,6 +379,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..7d5ee34f90 100644
--- a/target/loongarch/machine.c
+++ b/target/loongarch/machine.c
@@ -231,6 +231,11 @@ const VMStateDescription vmstate_loongarch_cpu = {
VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU),
VMSTATE_UINT64(env.CSR_DSAVE, LoongArchCPU),
+ /* Msg interrupt CSRs */
+ VMSTATE_UINT64_ARRAY(env.CSR_MSGIS, LoongArchCPU, 4),
+ VMSTATE_UINT64(env.CSR_MSGIR, LoongArchCPU),
+ VMSTATE_UINT64(env.CSR_MSGIE, LoongArchCPU),
+
VMSTATE_UINT64(kvm_state_counter, LoongArchCPU),
/* PV steal time */
VMSTATE_UINT64(env.stealtime.guest_addr, LoongArchCPU),
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (3 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 04/10] target/loongarch: add msg interrupt CSR registers Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
` (4 subsequent siblings)
9 siblings, 0 replies; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
the AVEC controller use 2ff00000-2fffffff Memory.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 25 ++++++++++++++++++++
hw/loongarch/virt.c | 39 +++++++++++++++++++++++++++++++-
include/hw/intc/loongarch_avec.h | 1 +
include/hw/loongarch/virt.h | 1 +
4 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 5a3e7ecc03..50956e7e4e 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,13 @@ 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, 0x100000);
+ sysbus_init_mmio(shd, &s->avec_mmio);
+ msi_nonbroken = true;
+
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 35643a4e0b..272355da2d 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"
@@ -365,7 +366,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;
@@ -411,6 +412,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 */
@@ -424,6 +452,15 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
+ /* Create AVEC device*/
+ if (virt_is_avecintc_enabled(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_PCH_MSI_ADDR_LOW,
+ 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 3c68593a7c..274b284641 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 3a81f048e8..172f40711d 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -64,6 +64,7 @@ struct LoongArchVirtMachineState {
struct loongarch_boot_info bootinfo;
DeviceState *ipi;
DeviceState *extioi;
+ DeviceState *avec;
};
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (4 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 05/10] hw/loongarch: AVEC controller add a MemoryRegion Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:40 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
` (3 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
the AVEC controller supports 256*256 irqs, all the irqs connect CPU INT_AVEC irq
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
hw/loongarch/virt.c | 11 +++++++++--
target/loongarch/cpu.h | 3 ++-
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index 50956e7e4e..c692fef43c 100644
--- a/hw/intc/loongarch_avec.c
+++ b/hw/intc/loongarch_avec.c
@@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static void avec_irq_handler(void *opaque, int irq, int level)
+{
+ return;
+}
+
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, irq;
Error *local_err = NULL;
lac->parent_realize(dev, &local_err);
@@ -47,6 +57,24 @@ 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);
+ for (irq = 0; irq < NR_VECTORS; irq++) {
+ qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
+ }
+ }
+ qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
+
return;
}
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 272355da2d..718b5b4f92 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -363,7 +363,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;
@@ -459,6 +459,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_PCH_MSI_ADDR_LOW,
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 */
@@ -799,7 +806,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 a1918a85da..b96df1cb2a 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -240,9 +240,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] 24+ messages in thread
* Re: [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-06-11 6:40 ` Bibo Mao
2025-06-17 1:28 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:40 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> the AVEC controller supports 256*256 irqs, all the irqs connect CPU INT_AVEC irq
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
> hw/loongarch/virt.c | 11 +++++++++--
> target/loongarch/cpu.h | 3 ++-
> 3 files changed, 39 insertions(+), 3 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index 50956e7e4e..c692fef43c 100644
> --- a/hw/intc/loongarch_avec.c
> +++ b/hw/intc/loongarch_avec.c
> @@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
> .endianness = DEVICE_LITTLE_ENDIAN,
> };
>
> +static void avec_irq_handler(void *opaque, int irq, int level)
> +{
> + return;
> +}
> +
> 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, irq;
>
> Error *local_err = NULL;
> lac->parent_realize(dev, &local_err);
> @@ -47,6 +57,24 @@ 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);
> + for (irq = 0; irq < NR_VECTORS; irq++) {
> + qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
> + }
One parent irqline for per-cpu is ok, so the total number of parent
irqline is s->num_cpu, the number of possible cpu.
> + }
> + qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
avec_irq_handler() can be removed here.
Regards
Bibo Mao
> +
> return;
> }
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 272355da2d..718b5b4f92 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -363,7 +363,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;
> @@ -459,6 +459,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_PCH_MSI_ADDR_LOW,
> 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 */
> @@ -799,7 +806,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 a1918a85da..b96df1cb2a 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -240,9 +240,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] 24+ messages in thread
* Re: [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins
2025-06-11 6:40 ` Bibo Mao
@ 2025-06-17 1:28 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-17 1:28 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:40, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> the AVEC controller supports 256*256 irqs, all the irqs connect CPU
>> INT_AVEC irq
>>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/intc/loongarch_avec.c | 28 ++++++++++++++++++++++++++++
>> hw/loongarch/virt.c | 11 +++++++++--
>> target/loongarch/cpu.h | 3 ++-
>> 3 files changed, 39 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index 50956e7e4e..c692fef43c 100644
>> --- a/hw/intc/loongarch_avec.c
>> +++ b/hw/intc/loongarch_avec.c
>> @@ -36,9 +36,19 @@ static const MemoryRegionOps loongarch_avec_ops = {
>> .endianness = DEVICE_LITTLE_ENDIAN,
>> };
>> +static void avec_irq_handler(void *opaque, int irq, int level)
>> +{
>> + return;
>> +}
>> +
>> 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, irq;
>> Error *local_err = NULL;
>> lac->parent_realize(dev, &local_err);
>> @@ -47,6 +57,24 @@ 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);
>> + for (irq = 0; irq < NR_VECTORS; irq++) {
>> + qdev_init_gpio_out(dev, &s->cpu[i].parent_irq[irq], 1);
>> + }
> One parent irqline for per-cpu is ok, so the total number of parent
> irqline is s->num_cpu, the number of possible cpu.
>
emm, yes , so the avec gpio out num is s->num_cpu * s->num_cpu.,
my thought avec should gpio_out = aveec gpio in, and the avec gpio
in is NR_VECTORS * s->num_cpu.
>> + }
>> + qdev_init_gpio_in(dev, avec_irq_handler, NR_VECTORS * s->num_cpu);
> avec_irq_handler() can be removed here.
>
yes. i 'll remove on v2.
thanks.
Song Gao
> Regards
> Bibo Mao
>> +
>> return;
>> }
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 272355da2d..718b5b4f92 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -363,7 +363,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;
>> @@ -459,6 +459,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_PCH_MSI_ADDR_LOW,
>> 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));
here connect all avec gpio_out to cpu gpio_in INT_AVEC.
>> + }
>> }
>> /* Create EXTIOI device */
>> @@ -799,7 +806,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 a1918a85da..b96df1cb2a 100644
>> --- a/target/loongarch/cpu.h
>> +++ b/target/loongarch/cpu.h
>> @@ -240,9 +240,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] 24+ messages in thread
* [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (5 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 06/10] hw/loongarch: Implement avec controller imput and output pins Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:36 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
` (2 subsequent siblings)
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/loongarch/virt.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 718b5b4f92..6b670e7936 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -503,11 +503,19 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
d = SYS_BUS_DEVICE(pch_msi);
sysbus_realize_and_unref(d, &error_fatal);
- sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
- for (i = 0; i < num; i++) {
- /* Connect pch_msi irqs to extioi */
- qdev_connect_gpio_out(DEVICE(d), i,
- qdev_get_gpio_in(extioi, i + start));
+ if (virt_is_avecintc_enabled(lvms)) {
+ for (i = 0; i < num; i++) {
+ /* Connect pch_msi irqs to avec */
+ qdev_connect_gpio_out(DEVICE(d), i,
+ qdev_get_gpio_in(avec, i + start));
+ }
+ } else {
+ sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
+ for (i = 0; i < num; i++) {
+ /* Connect pch_msi irqs to extioi */
+ qdev_connect_gpio_out(DEVICE(d), i,
+ qdev_get_gpio_in(extioi, i + start));
+ }
}
virt_devices_init(pch_pic, lvms);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
@ 2025-06-11 6:36 ` Bibo Mao
2025-06-17 1:58 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:36 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/loongarch/virt.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 718b5b4f92..6b670e7936 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -503,11 +503,19 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
> d = SYS_BUS_DEVICE(pch_msi);
> sysbus_realize_and_unref(d, &error_fatal);
> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
> - for (i = 0; i < num; i++) {
> - /* Connect pch_msi irqs to extioi */
> - qdev_connect_gpio_out(DEVICE(d), i,
> - qdev_get_gpio_in(extioi, i + start));
> + if (virt_is_avecintc_enabled(lvms)) {
> + for (i = 0; i < num; i++) {
> + /* Connect pch_msi irqs to avec */
> + qdev_connect_gpio_out(DEVICE(d), i,
> + qdev_get_gpio_in(avec, i + start));
one parent irqline for avec is enough. Variable num is the number
allocated for pch_msi when connecting to extioi. So variable num is
meaningless with avec.
Also there is no msi memory map region for avec such as
sysbus_mmio_map() in the following.
> + }
> + } else {In the first, I think irqchip avec and pch_msi can coexist together.
MSI memory area for avec is
[VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
for pch_msi is
[VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
connected to extioi.
So they can coexists together, it only depends on how guest kernel use
MSI controller.
Regards
Bibo Mao
> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
> + for (i = 0; i < num; i++) {
> + /* Connect pch_msi irqs to extioi */
> + qdev_connect_gpio_out(DEVICE(d), i,
> + qdev_get_gpio_in(extioi, i + start));
> + }
> }
>
> virt_devices_init(pch_pic, lvms);
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-11 6:36 ` Bibo Mao
@ 2025-06-17 1:58 ` gaosong
2025-06-17 7:34 ` Bibo Mao
0 siblings, 1 reply; 24+ messages in thread
From: gaosong @ 2025-06-17 1:58 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:36, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/loongarch/virt.c | 18 +++++++++++++-----
>> 1 file changed, 13 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>> index 718b5b4f92..6b670e7936 100644
>> --- a/hw/loongarch/virt.c
>> +++ b/hw/loongarch/virt.c
>> @@ -503,11 +503,19 @@ static void
>> virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
>> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
>> d = SYS_BUS_DEVICE(pch_msi);
>> sysbus_realize_and_unref(d, &error_fatal);
>> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>> - for (i = 0; i < num; i++) {
>> - /* Connect pch_msi irqs to extioi */
>> - qdev_connect_gpio_out(DEVICE(d), i,
>> - qdev_get_gpio_in(extioi, i + start));
>> + if (virt_is_avecintc_enabled(lvms)) {
>> + for (i = 0; i < num; i++) {
>> + /* Connect pch_msi irqs to avec */
>> + qdev_connect_gpio_out(DEVICE(d), i,
>> + qdev_get_gpio_in(avec, i + start));
> one parent irqline for avec is enough. Variable num is the number
> allocated for pch_msi when connecting to extioi. So variable num is
> meaningless with avec.
>
hi,
here is pch_msi [start-256] gpio_out connect to avec gpio_in [start,
256], not the avec connect to cpu.
and I think the 'one parent lrqline for avec' is avec connect cpu
gpio_in INT_AVEC at patch 6
'qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));'
or all pch_msi gpio_out connect one avec gpio_in ? I'm a little
confused here.
> Also there is no msi memory map region for avec such as
> sysbus_mmio_map() in the following.
>
emm, the region add at patch 6
memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
I will adjust the patch order and the code order.
>> + }
>> + } else {In the first, I think irqchip avec and pch_msi can
>> coexist together.
> MSI memory area for avec is
> [VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
yes, you're right. memory area for avec should be 2fe0000000-2ff0000000;
> for pch_msi is
> [VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
>
> For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
> connected to extioi.
>
> So they can coexists together, it only depends on how guest kernel use
> MSI controller.
>
emm, in case avec exists we should pick avec.
thanks.
Song Gao.
> Regards
> Bibo Mao
>> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>> + for (i = 0; i < num; i++) {
>> + /* Connect pch_msi irqs to extioi */
>> + qdev_connect_gpio_out(DEVICE(d), i,
>> + qdev_get_gpio_in(extioi, i + start));
>> + }
>> }
>> virt_devices_init(pch_pic, lvms);
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-17 1:58 ` gaosong
@ 2025-06-17 7:34 ` Bibo Mao
2025-06-18 3:55 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-17 7:34 UTC (permalink / raw)
To: gaosong; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/17 上午9:58, gaosong wrote:
> 在 2025/6/11 下午2:36, Bibo Mao 写道:
>>
>>
>> On 2025/6/9 下午6:48, Song Gao wrote:
>>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>>> ---
>>> hw/loongarch/virt.c | 18 +++++++++++++-----
>>> 1 file changed, 13 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>>> index 718b5b4f92..6b670e7936 100644
>>> --- a/hw/loongarch/virt.c
>>> +++ b/hw/loongarch/virt.c
>>> @@ -503,11 +503,19 @@ static void
>>> virt_irq_init(LoongArchVirtMachineState *lvms, MachineState *ms)
>>> qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
>>> d = SYS_BUS_DEVICE(pch_msi);
>>> sysbus_realize_and_unref(d, &error_fatal);
>>> - sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>>> - for (i = 0; i < num; i++) {
>>> - /* Connect pch_msi irqs to extioi */
>>> - qdev_connect_gpio_out(DEVICE(d), i,
>>> - qdev_get_gpio_in(extioi, i + start));
>>> + if (virt_is_avecintc_enabled(lvms)) {
>>> + for (i = 0; i < num; i++) {
>>> + /* Connect pch_msi irqs to avec */
>>> + qdev_connect_gpio_out(DEVICE(d), i,
>>> + qdev_get_gpio_in(avec, i + start));
>> one parent irqline for avec is enough. Variable num is the number
>> allocated for pch_msi when connecting to extioi. So variable num is
>> meaningless with avec.
>>
> hi,
> here is pch_msi [start-256] gpio_out connect to avec gpio_in [start,
> 256], not the avec connect to cpu.
pch_msi is always connected to eiointc, and it is not connected to avec
gpio_in. There is two MSI controllers coexisting together: pch_msi and
avec, guest OS can choose use one of them or both.
Regards
Bibo Mao
> and I think the 'one parent lrqline for avec' is avec connect cpu
> gpio_in INT_AVEC at patch 6
> 'qdev_connect_gpio_out(avec, cpu, qdev_get_gpio_in(cpudev, INT_AVEC));'
> or all pch_msi gpio_out connect one avec gpio_in ? I'm a little
> confused here.
>
>> Also there is no msi memory map region for avec such as
>> sysbus_mmio_map() in the following.
>>
> emm, the region add at patch 6
> memory_region_add_subregion(get_system_memory(), VIRT_PCH_MSI_ADDR_LOW,
> sysbus_mmio_get_region(SYS_BUS_DEVICE(avec), 0));
>
> I will adjust the patch order and the code order.
>
>>> + }
>>> + } else {In the first, I think irqchip avec and pch_msi can
>>> coexist together.
>> MSI memory area for avec is
>> [VIRT_PCH_MSI_ADDR_LOW - 0x100000, VIRT_PCH_MSI_ADDR_LOW)
> yes, you're right. memory area for avec should be 2fe0000000-2ff0000000;
>> for pch_msi is
>> [VIRT_PCH_MSI_ADDR_LOW, VIRT_PCH_MSI_ADDR_LOW + 0x8)
>>
>> For parent line, AVEC is connected to CPU MSGINT BIT14 and pch_msi is
>> connected to extioi.
>>
>> So they can coexists together, it only depends on how guest kernel use
>> MSI controller.
>>
> emm, in case avec exists we should pick avec.
>
> thanks.
> Song Gao.
>> Regards
>> Bibo Mao
>>> + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
>>> + for (i = 0; i < num; i++) {
>>> + /* Connect pch_msi irqs to extioi */
>>> + qdev_connect_gpio_out(DEVICE(d), i,
>>> + qdev_get_gpio_in(extioi, i + start));
>>> + }
>>> }
>>> virt_devices_init(pch_pic, lvms);
>>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller
2025-06-17 7:34 ` Bibo Mao
@ 2025-06-18 3:55 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-18 3:55 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/17 下午3:34, Bibo Mao 写道:
>>>
>> hi,
>> here is pch_msi [start-256] gpio_out connect to avec gpio_in
>> [start, 256], not the avec connect to cpu.
> pch_msi is always connected to eiointc, and it is not connected to
> avec gpio_in. There is two MSI controllers coexisting together:
> pch_msi and avec, guest OS can choose use one of them or both.
you're right. I got it now.
thanks.
Song Gao
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (6 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 07/10] hw/loongarch: connect pch_msi controller to avec controller Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 6:26 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
index c692fef43c..f609ed9aaa 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,32 @@ 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;
+
+ assert(mc->possible_cpu_arch_ids(machine));
+ id_list = mc->possible_cpu_arch_ids(machine);
+ CPUState *cpu = id_list->cpus[cpu_num].cpu;
+ CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
+ set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
+ qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
+}
+
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_PCH_MSI_ADDR_LOW;
+
+ cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
+ irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
+ avec_set_irq(s, cpu_num, irq_num, 1);
+}
static const MemoryRegionOps loongarch_avec_ops = {
.read = loongarch_avec_mem_read,
@@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
static void avec_irq_handler(void *opaque, int irq, int level)
{
- return;
+ int cpu_num, irq_num = 0;
+ LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
+ cpu_num = irq / 256;
+ irq_num = irq % 256;
+
+ avec_set_irq(s, cpu_num, irq_num, level);
}
static void loongarch_avec_realize(DeviceState *dev, Error **errp)
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
@ 2025-06-11 6:26 ` Bibo Mao
2025-06-17 2:05 ` gaosong
0 siblings, 1 reply; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 6:26 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
> 1 file changed, 34 insertions(+), 3 deletions(-)
>
> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
> index c692fef43c..f609ed9aaa 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,32 @@ 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;
> +
> + assert(mc->possible_cpu_arch_ids(machine));
> + id_list = mc->possible_cpu_arch_ids(machine);
> + CPUState *cpu = id_list->cpus[cpu_num].cpu;
> + CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
The format is strange here. Variable env is declared after normal
sentence, there is such issue in many places.
id_list = mc->possible_cpu_arch_ids(machine);
> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
> + qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
Why is parent_irq array here? I think one parent irq line is enough.
> +}
> +
> 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_PCH_MSI_ADDR_LOW;
> +
> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
>
blank line here.
> + avec_set_irq(s, cpu_num, irq_num, 1);
> +}
>
> static const MemoryRegionOps loongarch_avec_ops = {
> .read = loongarch_avec_mem_read,
> @@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>
> static void avec_irq_handler(void *opaque, int irq, int level)
> {
> - return;
> + int cpu_num, irq_num = 0;
> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
> + cpu_num = irq / 256;
> + irq_num = irq % 256;
> +
> + avec_set_irq(s, cpu_num, irq_num, level);
> }
When is the function avec_irq_handler() called?
Regards
Bibo Mao
>
> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 08/10] hw/loongarch: Implement avec set_irq
2025-06-11 6:26 ` Bibo Mao
@ 2025-06-17 2:05 ` gaosong
0 siblings, 0 replies; 24+ messages in thread
From: gaosong @ 2025-06-17 2:05 UTC (permalink / raw)
To: Bibo Mao; +Cc: qemu-devel, philmd, jiaxun.yang
在 2025/6/11 下午2:26, Bibo Mao 写道:
>
>
> On 2025/6/9 下午6:48, Song Gao wrote:
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>> hw/intc/loongarch_avec.c | 37 ++++++++++++++++++++++++++++++++++---
>> 1 file changed, 34 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/intc/loongarch_avec.c b/hw/intc/loongarch_avec.c
>> index c692fef43c..f609ed9aaa 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,32 @@ 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;
>> +
>> + assert(mc->possible_cpu_arch_ids(machine));
>> + id_list = mc->possible_cpu_arch_ids(machine);
>> + CPUState *cpu = id_list->cpus[cpu_num].cpu;
>> + CPULoongArchState *env = &LOONGARCH_CPU(cpu)->env;
> The format is strange here. Variable env is declared after normal
> sentence, there is such issue in many places.
> id_list = mc->possible_cpu_arch_ids(machine);
>
>> + set_bit(irq_num, &env->CSR_MSGIS[irq_num / 64]);
>> + qemu_set_irq(s->cpu[cpu_num].parent_irq[irq_num], 1);
> Why is parent_irq array here? I think one parent irq line is enough.
>
ok , i'll correct on v3.
>> +}
>> +
>> 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_PCH_MSI_ADDR_LOW;
>> +
>> + cpu_num = FIELD_EX64(msg_addr, MSG_ADDR, IRQ_NUM);
>> + irq_num = FIELD_EX64(msg_addr, MSG_ADDR, CPU_NUM);
> blank line here.
Got it.
>> + avec_set_irq(s, cpu_num, irq_num, 1);
>> +}
>> static const MemoryRegionOps loongarch_avec_ops = {
>> .read = loongarch_avec_mem_read,
>> @@ -38,7 +64,12 @@ static const MemoryRegionOps loongarch_avec_ops = {
>> static void avec_irq_handler(void *opaque, int irq, int level)
>> {
>> - return;
>> + int cpu_num, irq_num = 0;
>> + LoongArchAVECState *s = LOONGARCH_AVEC(opaque);
>> + cpu_num = irq / 256;
>> + irq_num = irq % 256;
>> +
>> + avec_set_irq(s, cpu_num, irq_num, level);
>> }
> When is the function avec_irq_handler() called?
>
when some deviec gpio_out connect to avec gpio_in, since we define the
avec qdev_init_gpio_in at
avec realize and the avec_Irq_handler is the callback function.
Thanks.
Song Gao
> Regards
> Bibo Mao
>> static void loongarch_avec_realize(DeviceState *dev, Error **errp)
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (7 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 08/10] hw/loongarch: Implement avec set_irq Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 4:04 ` Bibo Mao
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 1 +
target/loongarch/cpu.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 0834e91f30..83f6cb081a 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -39,6 +39,7 @@ FIELD(CSR_ECFG, VS, 16, 3)
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
FIELD(CSR_ESTAT, IS, 0, 13)
+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 bde9f917fc..207d11266f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -127,6 +127,23 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
return;
}
+ /* do INTC_AVEC irqs */
+ if (irq == INT_AVEC) {
+ for (int i = 256; i >= 0; i--) {
+ if (test_bit(i, &(env->CSR_MSGIS[i / 64]))) {
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ clear_bit(i, &(env->CSR_MSGIS[i / 64]));
+ }
+ }
+ } else {
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+ env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
+ return;
+ }
+
if (kvm_enabled()) {
kvm_loongarch_set_interrupt(cpu, irq, level);
} else if (tcg_enabled()) {
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
@ 2025-06-11 4:04 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 4:04 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 1 +
> target/loongarch/cpu.c | 17 +++++++++++++++++
> 2 files changed, 18 insertions(+)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 0834e91f30..83f6cb081a 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -39,6 +39,7 @@ FIELD(CSR_ECFG, VS, 16, 3)
>
> #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
> FIELD(CSR_ESTAT, IS, 0, 13)
> +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 bde9f917fc..207d11266f 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -127,6 +127,23 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> return;
> }
>
> + /* do INTC_AVEC irqs */
> + if (irq == INT_AVEC) {
> + for (int i = 256; i >= 0; i--) {
> + if (test_bit(i, &(env->CSR_MSGIS[i / 64]))) {
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
Modification with CSR_MSGIR should be moved to function avec_set_irq(),
or there is extra sub_irq parameter in loongarch_cpu_set_irq()
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> + cpu_interrupt(cs, CPU_INTERRUPT_HARD);
it is unnecessary and there is such code in tcg_enabled() loop sentence.
> + clear_bit(i, &(env->CSR_MSGIS[i / 64]));
CSR_MSGIS is unnecessary, it is pure software state.
> + }
> + }
> + } else {
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> + env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
> + return;
> + }
what is the use about else {} sentences? Does it change interrupt logic
if AVEC is disabled?
Also I think it should be removed to the following (tcg_enabled().
Regards
Bibo Mao
> +
> if (kvm_enabled()) {
> kvm_loongarch_set_interrupt(cpu, irq, level);
> } else if (tcg_enabled()) {
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
2025-06-09 10:48 [PATCH 00/10] hw/loongarch: add the advanced extended interrupt controllers (AVECINTC) support Song Gao
` (8 preceding siblings ...)
2025-06-09 10:48 ` [PATCH 09/10] target/loongarch: loongarch CPU supoort avec irqs Song Gao
@ 2025-06-09 10:48 ` Song Gao
2025-06-11 3:44 ` Bibo Mao
9 siblings, 1 reply; 24+ messages in thread
From: Song Gao @ 2025-06-09 10:48 UTC (permalink / raw)
To: maobibo; +Cc: qemu-devel, philmd, jiaxun.yang
we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
and loongarch_cpu_do_interrupt support msg interrupts.
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu-csr.h | 3 ++-
target/loongarch/cpu.c | 35 ++++++++++++++++++++++++++++++-----
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 83f6cb081a..5a00cf3366 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
#define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, MSGINT, 14, 1) /* used for msg */
FIELD(CSR_ECFG, VS, 16, 3)
#define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
FIELD(CSR_ESTAT, IS, 0, 13)
-FIELD(CSR_ESTAT, MSGINT, 14, 1)
+FIELD(CSR_ESTAT, MSGINT, 14, 1) /* used for msg */
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 207d11266f..b92463101e 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
#ifndef CONFIG_USER_ONLY
#include "hw/loongarch/virt.h"
+static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
+{
+ uint32_t ret = 0;
+ ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+ ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+ return ret;
+}
void loongarch_cpu_set_irq(void *opaque, int irq, int level)
{
LoongArchCPU *cpu = opaque;
@@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
clear_bit(i, &(env->CSR_MSGIS[i / 64]));
}
}
} else {
env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
- env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
- return;
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
}
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);
- if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+ if (loongarch_cpu_has_interrupt(env)) {
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
return ret;
}
+static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
+{
+ bool pending_msg = 0;
+ bool status_msg = 0;
+
+ pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
+ status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
+
+ return (pending_msg & status_msg) != 0;
+}
/* Check if there is pending and not masked out interrupt */
static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
{
uint32_t pending;
uint32_t status;
-
+ if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+ return true;
+ }
pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
@@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
uint32_t vector = 0;
uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+ if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
+ env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
+ env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
+ set_pc(env, env->CSR_EENTRY + \
+ (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
+ return;
+ }
/* Find the highest-priority interrupt. */
vector = 31 - clz32(pending);
--
2.34.1
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt.
2025-06-09 10:48 ` [PATCH 10/10] target/loongarch: cpu do interrupt support msg interrupt Song Gao
@ 2025-06-11 3:44 ` Bibo Mao
0 siblings, 0 replies; 24+ messages in thread
From: Bibo Mao @ 2025-06-11 3:44 UTC (permalink / raw)
To: Song Gao; +Cc: qemu-devel, philmd, jiaxun.yang
On 2025/6/9 下午6:48, Song Gao wrote:
> we use CSR_ESTAT and CSR_ECFG bit 15 for msg interrupt.
> and loongarch_cpu_do_interrupt support msg interrupts.
>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 3 ++-
> target/loongarch/cpu.c | 35 ++++++++++++++++++++++++++++++-----
> 2 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index 83f6cb081a..5a00cf3366 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -35,11 +35,12 @@ FIELD(CSR_MISC, DWPL, 16, 3)
>
> #define LOONGARCH_CSR_ECFG 0x4 /* Exception config */
> FIELD(CSR_ECFG, LIE, 0, 13)
> +FIELD(CSR_ECFG, MSGINT, 14, 1) /* used for msg */
how about only modify LIE such as FIELD(CSR_ECFG, LIE, 0, 15)?
> FIELD(CSR_ECFG, VS, 16, 3)
>
> #define LOONGARCH_CSR_ESTAT 0x5 /* Exception status */
> FIELD(CSR_ESTAT, IS, 0, 13)
> -FIELD(CSR_ESTAT, MSGINT, 14, 1)
> +FIELD(CSR_ESTAT, MSGINT, 14, 1) /* used for msg */
ditto, how about modify IS such as FIELD(CSR_ESTAT, IS, 0, 15)?
Regards
Bibo Mao
> 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 207d11266f..b92463101e 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -117,6 +117,13 @@ static vaddr loongarch_cpu_get_pc(CPUState *cs)
> #ifndef CONFIG_USER_ONLY
> #include "hw/loongarch/virt.h"
>
> +static uint32_t loongarch_cpu_has_interrupt(CPULoongArchState *env)
> +{
> + uint32_t ret = 0;
> + ret = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> + ret |= FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> + return ret;
> +}
> void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> {
> LoongArchCPU *cpu = opaque;
> @@ -134,21 +141,20 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
> env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, INTNUM, i);
> env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 0);
> env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 1);
> - cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 1);
> clear_bit(i, &(env->CSR_MSGIS[i / 64]));
> }
> }
> } else {
> env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> - env->CSR_MSGIR = FIELD_DP64(env->CSR_MSGIR, CSR_MSGIR, ACTIVE, 1);
> - return;
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
> }
>
> 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);
> - if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
> + if (loongarch_cpu_has_interrupt(env)) {
> cpu_interrupt(cs, CPU_INTERRUPT_HARD);
> } else {
> cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
> @@ -166,12 +172,24 @@ static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
> return ret;
> }
>
> +static inline bool cpu_loongarch_hw_interrupt_msg_pending(CPULoongArchState *env)
> +{
> + bool pending_msg = 0;
> + bool status_msg = 0;
> +
> + pending_msg = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, MSGINT);
> + status_msg = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, MSGINT);
> +
> + return (pending_msg & status_msg) != 0;
> +}
> /* Check if there is pending and not masked out interrupt */
> static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
> {
> uint32_t pending;
> uint32_t status;
> -
> + if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> + return true;
> + }
> pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> status = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
>
> @@ -285,6 +303,13 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
> uint32_t vector = 0;
> uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
> pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
> + if (cpu_loongarch_hw_interrupt_msg_pending(env)) {
> + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0);
> + env->CSR_ECFG = FIELD_DP64(env->CSR_ECFG, CSR_ECFG, MSGINT, 0);
> + set_pc(env, env->CSR_EENTRY + \
> + (EXCCODE_EXTERNAL_INT + INT_AVEC) * vec_size);
> + return;
> + }
>
> /* Find the highest-priority interrupt. */
> vector = 31 - clz32(pending);
>
^ permalink raw reply [flat|nested] 24+ messages in thread