riscv: AIA: Add in-kernel irqchips save and restore function support
v5 cover riscv: AIA: Add in-kernel irqchips save and restore function support
This series adds support for in-kernel AIA irqchip save and restore on RISC-V.
Changes in v5:
- Fix typos in the patch descriptions.
- Split the non-RISC-V-specific changes into a separate patch (patch 03).
- Drop the TCG vmstate debug fix from this series.
- Link to v4: https://lore.kernel.org/qemu-devel/[email protected]/
Changes in v4:
- Fix build issues in the TCG-only configuration.
- Rename several functions to make them more readable.
- Fix the missing section footer problem.
- Add patch 04, which fixes an assertion failure during save on --disable-tcg builds.
- Link to v3: https://lore.kernel.org/qemu-devel/[email protected]/
Changes in v3:
- Removed unnecessary changes in bitops.h
- Link to v2: https://lore.kernel.org/qemu-devel/[email protected]/
Changes in v2:
- Added the BITS_TO_U64S macro
- Added the nr_eix field and dynamically allocated the eie/eip arrays
- Replaced the CONFIG_32BIT macro with is_32bit boolean flag
- Link to v1: https://lore.kernel.org/qemu-devel/[email protected]/
Wang Yechao (1):
include/qemu/bitops: Move BITS_TO_U64S to bitops.h
Xuemei Liu (3):
target/riscv/kvm: create kvm_riscv_aia_access_reg hw/intc/riscv_aplic: Add in-kernel aplic save and restore function hw/intc/imsic: Add in-kernel imsic save and restore function
hw/intc/riscv_aplic.c | 201 +++++++++++++++++++++++++++++----- hw/intc/riscv_imsic.c | 180 +++++++++++++++++++++++++++--- include/hw/intc/riscv_aplic.h | 4 + include/hw/intc/riscv_imsic.h | 3 + include/qemu/bitops.h | 1 + migration/vmstate-types.c | 3 +- target/riscv/kvm/kvm-cpu.c | 7 +- target/riscv/kvm/kvm_riscv.h | 1 + 8 files changed, 357 insertions(+), 43 deletions(-)
Signature · 1 line
2.47.3
PATCH v5 1/4 target/riscv/kvm: create kvm_riscv_aia_access_reg
From: Xuemei Liu <[email protected]>
Create common function kvm_riscv_aia_access_reg to access APLIC and IMSIC regs
--- target/riscv/kvm/kvm-cpu.c | 7 ++++++- target/riscv/kvm/kvm_riscv.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-)
target/riscv/kvm/kvm-cpu.c +6 -1
@@ -58,6 +58,7 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level)static bool cap_has_mp_state;static bool mp_state_reset; +static int aia_fd =-1 ;#define KVM_RISCV_REG_ID_U32 (type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U32 | \ type | idx)
@@ -1924,13 +1925,17 @@ void kvm_arch_accel_class_init(ObjectClass *oc) "auto"); } +void kvm_riscv_aia_access_reg (int group,uint64_t addr,void *val,bool write) +{ +kvm_device_access (aia_fd, group, addr, val, write, &error_abort); +} +void kvm_riscv_aia_create (MachineState *machine,uint64_t group_shift,uint64_t aia_irq_num,uint64_t aia_msi_num,uint64_t aplic_base,uint64_t imsic_base,uint64_t guest_num) {int ret, i; -int aia_fd =-1 ;uint64_t default_aia_mode;uint64_t socket_count =riscv_socket_count (machine);uint64_t max_hart_per_socket =0 ;
target/riscv/kvm/kvm_riscv.h +1 -0
@@ -29,6 +29,7 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu);* @level: %0 to clear the interrupt, non-zero to set it. */ void kvm_riscv_set_irq (RISCVCPU *cpu,int irq,int level); +void kvm_riscv_aia_access_reg (int group,uint64_t addr,void *val,bool write); void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, uint64_t aia_irq_num, uint64_t aia_msi_num, uint64_t aplic_base, uint64_t imsic_base,
Signature · 1 line
2.27.0
Re: [PATCH v5 1/4] target/riscv/kvm: create kvm_riscv_aia_access_reg
Quoted 26 lines · Wang Yechao
From: Xuemei Liu <[email protected]>
Create common function
kvm_riscv_aia_access_regto access APLIC and IMSIC regsSigned-off-by Xuemei Liu <[email protected]>Signed-off-by Wang Yechao <[email protected]>Reviewed-by Daniel Henrique Barboza <[email protected]>--- target/riscv/kvm/kvm-cpu.c | 7 ++++++- target/riscv/kvm/kvm_riscv.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-)target/riscv/kvm/kvm-cpu.c +1
-0@@ -58,6 +58,7 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level)static bool cap_has_mp_state;static bool mp_state_reset; +static int aia_fd =-1 ;#define KVM_RISCV_REG_ID_U32 (type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U32 | \ type | idx)
target/riscv/kvm/kvm-cpu.c void kvm_arch_accel_class_init(ObjectClass *oc) · line 1929
Quoted 5 lines
target/riscv/kvm/kvm-cpu.c +2
-0@@ -1924,13 +1925,17 @@ void kvm_arch_accel_class_init(ObjectClass *oc) "auto"); } +void kvm_riscv_aia_access_reg (int group,uint64_t addr,void *val,bool write) +{
This function is only valid after kvm_riscv_aia_create() has completed successfully. Would it be better to add the following ?
+ g_assert(aia_fd >=0);
Otherwise,
Thanks,
Nutty
Quoted 25 lines
target/riscv/kvm/kvm-cpu.c +3
-1+kvm_device_access (aia_fd, group, addr, val, write, &error_abort); +} +void kvm_riscv_aia_create (MachineState *machine,uint64_t group_shift,uint64_t aia_irq_num,uint64_t aia_msi_num,uint64_t aplic_base,uint64_t imsic_base,uint64_t guest_num) {int ret, i; -int aia_fd =-1 ;uint64_t default_aia_mode;uint64_t socket_count =riscv_socket_count (machine);uint64_t max_hart_per_socket =0 ;target/riscv/kvm/kvm_riscv.h +1
-0@@ -29,6 +29,7 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu);* @level: %0 to clear the interrupt, non-zero to set it. */ void kvm_riscv_set_irq (RISCVCPU *cpu,int irq,int level); +void kvm_riscv_aia_access_reg (int group,uint64_t addr,void *val,bool write); void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, uint64_t aia_irq_num, uint64_t aia_msi_num, uint64_t aplic_base, uint64_t imsic_base,
PATCH v5 2/4 hw/intc/riscv_aplic: Add in-kernel aplic save and restore function
In reply to Wang YechaoFrom: Xuemei Liu <[email protected]>
Add save and restore function if riscv_use_emulated_aplic return false, it is to get and set APLIC irqchip state from KVM kernel.
--- hw/intc/riscv_aplic.c | 201 +++++++++++++++++++++++++++++----- include/hw/intc/riscv_aplic.h | 4 + 2 files changed, 179 insertions(+), 26 deletions(-)
hw/intc/riscv_aplic.c +175 -26
@@ -979,9 +979,7 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) } aplic->bitfield_words = (aplic->num_irqs +31 ) >>5 ; - aplic->sourcecfg =g_new0 (uint32_t, aplic->num_irqs); aplic->state =g_new0 (uint32_t, aplic->num_irqs); - aplic->target =g_new0 (uint32_t, aplic->num_irqs); aplic->idelivery =g_new0 (uint32_t, aplic->num_harts); aplic->iforce =g_new0 (uint32_t, aplic->num_harts); aplic->ithreshold =g_new0 (uint32_t, aplic->num_harts);
@@ -993,8 +991,16 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)if (kvm_enabled ()) { aplic->kvm_splitmode = true; } + }else { + aplic->nr_words =BITS_TO_U32S (aplic->num_irqs); + aplic->setip =g_new0 (uint32_t, aplic->nr_words); + aplic->clrip =g_new0 (uint32_t, aplic->nr_words); + aplic->setie =g_new0 (uint32_t, aplic->nr_words); } + aplic->sourcecfg =g_new0 (uint32_t, aplic->num_irqs); + aplic->target =g_new0 (uint32_t, aplic->num_irqs); +/* * Only root APLICs have hardware IRQ lines. All non-root APLICs * have IRQ lines delegated by their parent APLIC.
@@ -1020,47 +1026,190 @@ static const Property riscv_aplic_properties[] = { DEFINE_PROP_BOOL("mmode", RISCVAPLICState, mmode, 0), }; -static bool riscv_aplic_state_needed (void *opaque) +static bool riscv_emulated_aplic_state_needed (void *opaque) {RISCVAPLICState *aplic = opaque;return riscv_use_emulated_aplic (aplic->msimode); } +static const VMStateDescription vmstate_emulated_aplic_state = { + .name ="riscv_aplic/emulated_aplic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = riscv_emulated_aplic_state_needed, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (state, RISCVAPLICState, + num_irqs,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_UINT32 (mmsicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (mmsicfgaddrH, RISCVAPLICState), +VMSTATE_UINT32 (smsicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (smsicfgaddrH, RISCVAPLICState), +VMSTATE_UINT32 (kvm_msicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (kvm_msicfgaddrH, RISCVAPLICState), +VMSTATE_VARRAY_UINT32 (idelivery, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (iforce, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (ithreshold, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + } +}; + +#ifdef CONFIG_KVM +static bool kvm_riscv_aplic_state_needed (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +return !riscv_use_emulated_aplic (aplic->msimode); +} + +static int kvm_riscv_aplic_state_pre_save (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +for (uint32_t i =0 ; i < aplic->nr_words; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIP_BASE + i *4 , + aplic->setip + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_CLRIP_BASE + i *4 , + aplic->clrip + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIE_BASE + i *4 , + aplic->setie + i, false); + } + +return 0 ; +} + +static int kvm_riscv_aplic_state_post_load (void *opaque,int version_id) +{ +RISCVAPLICState *aplic = opaque; + +for (uint32_t i =0 ; i < aplic->nr_words; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIP_BASE + i *4 , + aplic->setip + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_CLRIP_BASE + i *4 , + aplic->clrip + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIE_BASE + i *4 , + aplic->setie + i, true); + } + +return 0 ; +} + +static const VMStateDescription vmstate_kvm_aplic_state = { + .name ="riscv_aplic/kvm_aplic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = kvm_riscv_aplic_state_needed, + .pre_save = kvm_riscv_aplic_state_pre_save, + .post_load = kvm_riscv_aplic_state_post_load, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (setip, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (clrip, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (setie, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + } +}; + +static int riscv_aplic_pre_save (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +if (!riscv_use_emulated_aplic (aplic->msimode)) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_DOMAINCFG , + &aplic->domaincfg, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_GENMSI , + &aplic->genmsi, false); + +for (uint32_t i =1 ; i < aplic->num_irqs; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SOURCECFG_BASE + (i -1 ) *4 , + aplic->sourcecfg + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_TARGET_BASE + (i -1 ) *4 , + aplic->target + i, false); + } + } + +return 0 ; +} + +static int riscv_aplic_post_load (void *opaque,int version_id) +{ +RISCVAPLICState *aplic = opaque; + +if (!riscv_use_emulated_aplic (aplic->msimode)) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_DOMAINCFG , + &aplic->domaincfg, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_GENMSI , + &aplic->genmsi, true); + +for (uint32_t i =1 ; i < aplic->num_irqs; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SOURCECFG_BASE + (i -1 ) *4 , + aplic->sourcecfg + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_TARGET_BASE + (i -1 ) *4 , + aplic->target + i, true); + } + } + +return 0 ; +} + +#else +static int riscv_aplic_pre_save (void *opaque) +{ +return 0 ; +} + +static int riscv_aplic_post_load (void *opaque,int version_id) +{ +return 0 ; +} +#endif +static const VMStateDescription vmstate_riscv_aplic = { .name ="riscv_aplic" , - .version_id =3 , - .minimum_version_id =3 , - .needed = riscv_aplic_state_needed, + .version_id =4 , + .minimum_version_id =4 , + .pre_save = riscv_aplic_pre_save, + .post_load = riscv_aplic_post_load, .fields = (const VMStateField []) {VMSTATE_UINT32 (domaincfg, RISCVAPLICState), -VMSTATE_UINT32 (mmsicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (mmsicfgaddrH, RISCVAPLICState), -VMSTATE_UINT32 (smsicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (smsicfgaddrH, RISCVAPLICState),VMSTATE_UINT32 (genmsi, RISCVAPLICState), -VMSTATE_UINT32 (kvm_msicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (kvm_msicfgaddrH, RISCVAPLICState), -VMSTATE_VARRAY_UINT32 (sourcecfg, RISCVAPLICState, - num_irqs,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (state, RISCVAPLICState, +VMSTATE_VARRAY_UINT32 (sourcecfg , RISCVAPLICState, num_irqs,0 , vmstate_info_uint32, uint32_t),VMSTATE_VARRAY_UINT32 (target, RISCVAPLICState, num_irqs,0 , vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (idelivery, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (iforce, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (ithreshold, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t),VMSTATE_END_OF_LIST () - } + }, + .subsections = (const VMStateDescription *const []) { + &vmstate_emulated_aplic_state, +#ifdef CONFIG_KVM + &vmstate_kvm_aplic_state, +#endif +NULL + } };static void riscv_aplic_class_init (ObjectClass *klass,const void *data)
include/hw/intc/riscv_aplic.h +4 -0
@@ -53,6 +53,9 @@ struct RISCVAPLICState {uint32_t *idelivery;uint32_t *iforce;uint32_t *ithreshold; +uint32_t *setip; +uint32_t *clrip; +uint32_t *setie;/* topology */ #define QEMU_APLIC_MAX_CHILDREN 16
@@ -66,6 +69,7 @@ struct RISCVAPLICState {uint32_t num_harts;uint32_t iprio_mask;uint32_t num_irqs; +uint32_t nr_words;bool msimode;bool mmode;
Signature · 1 line
2.27.0
Re: [PATCH v5 2/4] hw/intc/riscv_aplic: Add in-kernel aplic save and restore function
Quoted 8 lines · Wang Yechao
From: Xuemei Liu <[email protected]>
Add save and restore function if
riscv_use_emulated_aplicreturn false, it is to get and set APLIC irqchip state from KVM kernel.Signed-off-by Xuemei Liu <[email protected]>Signed-off-by Wang Yechao <[email protected]>Reviewed-by Daniel Henrique Barboza <[email protected]>
Thanks,
Nutty
Quoted 273 lines
--- hw/intc/riscv_aplic.c | 201 +++++++++++++++++++++++++++++----- include/hw/intc/riscv_aplic.h | 4 + 2 files changed, 179 insertions(+), 26 deletions(-)hw/intc/riscv_aplic.c +175
-26@@ -979,9 +979,7 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) } aplic->bitfield_words = (aplic->num_irqs +31 ) >>5 ; - aplic->sourcecfg =g_new0 (uint32_t, aplic->num_irqs); aplic->state =g_new0 (uint32_t, aplic->num_irqs); - aplic->target =g_new0 (uint32_t, aplic->num_irqs); aplic->idelivery =g_new0 (uint32_t, aplic->num_harts); aplic->iforce =g_new0 (uint32_t, aplic->num_harts); aplic->ithreshold =g_new0 (uint32_t, aplic->num_harts);@@ -993,8 +991,16 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp)if (kvm_enabled ()) { aplic->kvm_splitmode = true; } + }else { + aplic->nr_words =BITS_TO_U32S (aplic->num_irqs); + aplic->setip =g_new0 (uint32_t, aplic->nr_words); + aplic->clrip =g_new0 (uint32_t, aplic->nr_words); + aplic->setie =g_new0 (uint32_t, aplic->nr_words); } + aplic->sourcecfg =g_new0 (uint32_t, aplic->num_irqs); + aplic->target =g_new0 (uint32_t, aplic->num_irqs); +/* * Only root APLICs have hardware IRQ lines. All non-root APLICs * have IRQ lines delegated by their parent APLIC. @@ -1020,47 +1026,190 @@ static const Property riscv_aplic_properties[] = { DEFINE_PROP_BOOL("mmode", RISCVAPLICState, mmode, 0), }; -static bool riscv_aplic_state_needed (void *opaque) +static bool riscv_emulated_aplic_state_needed (void *opaque) {RISCVAPLICState *aplic = opaque;return riscv_use_emulated_aplic (aplic->msimode); } +static const VMStateDescription vmstate_emulated_aplic_state = { + .name ="riscv_aplic/emulated_aplic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = riscv_emulated_aplic_state_needed, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (state, RISCVAPLICState, + num_irqs,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_UINT32 (mmsicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (mmsicfgaddrH, RISCVAPLICState), +VMSTATE_UINT32 (smsicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (smsicfgaddrH, RISCVAPLICState), +VMSTATE_UINT32 (kvm_msicfgaddr, RISCVAPLICState), +VMSTATE_UINT32 (kvm_msicfgaddrH, RISCVAPLICState), +VMSTATE_VARRAY_UINT32 (idelivery, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (iforce, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (ithreshold, RISCVAPLICState, + num_harts,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + } +}; + +#ifdef CONFIG_KVM +static bool kvm_riscv_aplic_state_needed (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +return !riscv_use_emulated_aplic (aplic->msimode); +} + +static int kvm_riscv_aplic_state_pre_save (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +for (uint32_t i =0 ; i < aplic->nr_words; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIP_BASE + i *4 , + aplic->setip + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_CLRIP_BASE + i *4 , + aplic->clrip + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIE_BASE + i *4 , + aplic->setie + i, false); + } + +return 0 ; +} + +static int kvm_riscv_aplic_state_post_load (void *opaque,int version_id) +{ +RISCVAPLICState *aplic = opaque; + +for (uint32_t i =0 ; i < aplic->nr_words; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIP_BASE + i *4 , + aplic->setip + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_CLRIP_BASE + i *4 , + aplic->clrip + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SETIE_BASE + i *4 , + aplic->setie + i, true); + } + +return 0 ; +} + +static const VMStateDescription vmstate_kvm_aplic_state = { + .name ="riscv_aplic/kvm_aplic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = kvm_riscv_aplic_state_needed, + .pre_save = kvm_riscv_aplic_state_pre_save, + .post_load = kvm_riscv_aplic_state_post_load, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (setip, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (clrip, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (setie, RISCVAPLICState, + nr_words,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + } +}; + +static int riscv_aplic_pre_save (void *opaque) +{ +RISCVAPLICState *aplic = opaque; + +if (!riscv_use_emulated_aplic (aplic->msimode)) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_DOMAINCFG , + &aplic->domaincfg, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_GENMSI , + &aplic->genmsi, false); + +for (uint32_t i =1 ; i < aplic->num_irqs; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SOURCECFG_BASE + (i -1 ) *4 , + aplic->sourcecfg + i, false); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_TARGET_BASE + (i -1 ) *4 , + aplic->target + i, false); + } + } + +return 0 ; +} + +static int riscv_aplic_post_load (void *opaque,int version_id) +{ +RISCVAPLICState *aplic = opaque; + +if (!riscv_use_emulated_aplic (aplic->msimode)) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_DOMAINCFG , + &aplic->domaincfg, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC ,APLIC_GENMSI , + &aplic->genmsi, true); + +for (uint32_t i =1 ; i < aplic->num_irqs; i++) { +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_SOURCECFG_BASE + (i -1 ) *4 , + aplic->sourcecfg + i, true); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_APLIC , +APLIC_TARGET_BASE + (i -1 ) *4 , + aplic->target + i, true); + } + } + +return 0 ; +} + +#else +static int riscv_aplic_pre_save (void *opaque) +{ +return 0 ; +} + +static int riscv_aplic_post_load (void *opaque,int version_id) +{ +return 0 ; +} +#endif +static const VMStateDescription vmstate_riscv_aplic = { .name ="riscv_aplic" , - .version_id =3 , - .minimum_version_id =3 , - .needed = riscv_aplic_state_needed, + .version_id =4 , + .minimum_version_id =4 , + .pre_save = riscv_aplic_pre_save, + .post_load = riscv_aplic_post_load, .fields = (const VMStateField []) {VMSTATE_UINT32 (domaincfg, RISCVAPLICState), -VMSTATE_UINT32 (mmsicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (mmsicfgaddrH, RISCVAPLICState), -VMSTATE_UINT32 (smsicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (smsicfgaddrH, RISCVAPLICState),VMSTATE_UINT32 (genmsi, RISCVAPLICState), -VMSTATE_UINT32 (kvm_msicfgaddr, RISCVAPLICState), -VMSTATE_UINT32 (kvm_msicfgaddrH, RISCVAPLICState), -VMSTATE_VARRAY_UINT32 (sourcecfg, RISCVAPLICState, - num_irqs,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (state, RISCVAPLICState, +VMSTATE_VARRAY_UINT32 (sourcecfg , RISCVAPLICState, num_irqs,0 , vmstate_info_uint32, uint32_t),VMSTATE_VARRAY_UINT32 (target, RISCVAPLICState, num_irqs,0 , vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (idelivery, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (iforce, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (ithreshold, RISCVAPLICState, - num_harts,0 , - vmstate_info_uint32, uint32_t),VMSTATE_END_OF_LIST () - } + }, + .subsections = (const VMStateDescription *const []) { + &vmstate_emulated_aplic_state, +#ifdef CONFIG_KVM + &vmstate_kvm_aplic_state, +#endif +NULL + } };static void riscv_aplic_class_init (ObjectClass *klass,const void *data)include/hw/intc/riscv_aplic.h +4
-0@@ -53,6 +53,9 @@ struct RISCVAPLICState {uint32_t *idelivery;uint32_t *iforce;uint32_t *ithreshold; +uint32_t *setip; +uint32_t *clrip; +uint32_t *setie;/* topology */ #define QEMU_APLIC_MAX_CHILDREN 16@@ -66,6 +69,7 @@ struct RISCVAPLICState {uint32_t num_harts;uint32_t iprio_mask;uint32_t num_irqs; +uint32_t nr_words;bool msimode;bool mmode;
PATCH v5 3/4 include/qemu/bitops: Move BITS_TO_U64S to bitops.h
In reply to Wang YechaoBITS_TO_U64S was a private macro in migration/vmstate-types.c, defining the number of 64-bit words used on the wire for bitmaps. Move it to include/qemu/bitops.h alongside the existing BITS_TO_U32S so it can be shared with other code.
While moving it, express the divisor with sizeof(uint64_t) instead of the hardcoded 64, keeping it consistent with BITS_TO_U32S. This is semantically equivalent.
--- include/qemu/bitops.h | 1 + migration/vmstate-types.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-)
include/qemu/bitops.h +1 -0
@@ -20,6 +20,7 @@#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)#define BITS_TO_LONGS (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))#define BITS_TO_U32S (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t)) +#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint64_t))#define BIT (nr) (1UL << (nr))#define BIT_ULL (nr) (1ULL << (nr))
migration/vmstate-types.c +1 -2
@@ -16,6 +16,7 @@#include "migration.h" #include "migration/vmstate.h" #include "migration/client-options.h" +#include "qemu/bitops.h" #include "qemu/error-report.h" #include "qemu/queue.h" #include "trace.h"
@@ -596,8 +597,6 @@ const VMStateInfo vmstate_info_tmp = {* bit words with the bits in big endian order. The in-memory format * is an array of 'unsigned long', which may be either 32 or 64 bits. */ -/* This is the number of 64 bit words sent over the wire */ -#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, 64)static bool load_bitmap (QEMUFile *f,void *pv,size_t size,const VMStateField *field,Error **errp) {
Signature · 1 line
2.27.0
Re: [PATCH v5 3/4] include/qemu/bitops: Move BITS_TO_U64S to bitops.h
Quoted 5 lines · Wang Yechao
BITS_TO_U64Swas a private macro inmigration/vmstate-types.c, defining the number of 64-bit words used on the wire for bitmaps. Move it toinclude/qemu/bitops.halongside the existingBITS_TO_U32Sso it can be shared with other code.
Quoted 7 lines
While moving it, express the divisor with
sizeof(uint64_t)instead of the hardcoded 64, keeping it consistent withBITS_TO_U32S. This is semantically equivalent.Signed-off-by Wang Yechao <[email protected]>Signed-off-by Xuemei Liu <[email protected]>Reviewed-by Daniel Henrique Barboza <[email protected]>
Thanks,
Nutty
Quoted 38 lines
--- include/qemu/bitops.h | 1 + migration/vmstate-types.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-)include/qemu/bitops.h +1
-0@@ -20,6 +20,7 @@#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)#define BITS_TO_LONGS (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))#define BITS_TO_U32S (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t)) +#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint64_t))#define BIT (nr) (1UL << (nr))#define BIT_ULL (nr) (1ULL << (nr))migration/vmstate-types.c +1
-2@@ -16,6 +16,7 @@#include "migration.h" #include "migration/vmstate.h" #include "migration/client-options.h" +#include "qemu/bitops.h" #include "qemu/error-report.h" #include "qemu/queue.h" #include "trace.h" @@ -596,8 +597,6 @@ const VMStateInfo vmstate_info_tmp = {* bit words with the bits in big endian order. The in-memory format * is an array of 'unsigned long', which may be either 32 or 64 bits. */ -/* This is the number of 64 bit words sent over the wire */ -#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, 64)static bool load_bitmap (QEMUFile *f,void *pv,size_t size,const VMStateField *field,Error **errp) {
Re: [PATCH v5 3/4] include/qemu/bitops: Move BITS_TO_U64S to bitops.h
In reply to Wang YechaoQuoted 5 lines · Wang Yechao
BITS_TO_U64Swas a private macro inmigration/vmstate-types.c, defining the number of 64-bit words used on the wire for bitmaps. Move it toinclude/qemu/bitops.halongside the existingBITS_TO_U32Sso it can be shared with other code.
Quoted 8 lines
While moving it, express the divisor with
sizeof(uint64_t)instead of the hardcoded 64, keeping it consistent withBITS_TO_U32S. This is semantically equivalent.Signed-off-by Wang Yechao <[email protected]>Signed-off-by Xuemei Liu <[email protected]>Reviewed-by Daniel Henrique Barboza
Alistair
Quoted 43 lines
---
include/qemu/bitops.h | 1 +
migration/vmstate-types.c | 3 +--2 files changed, 2 insertions(+), 2 deletions(-)include/qemu/bitops.h +1
-0@@ -20,6 +20,7 @@ #define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define BITS_TO_U32S(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(uint32_t)) +#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, BITS_PER_BYTE *
sizeof(uint64_t))
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))migration/vmstate-types.c +1
-0@@ -16,6 +16,7 @@ #include "migration.h" #include "migration/vmstate.h" #include "migration/client-options.h" +#include "qemu/bitops.h" #include "qemu/error-report.h" #include "qemu/queue.h" #include "trace.h"@@ -596,8 +597,6 @@ const VMStateInfo vmstate_info_tmp = { * bit words with the bits in big endian order. The in-memory format * is an array of 'unsigned long', which may be either 32 or 64bits.
*/migration/vmstate-types.c +0
-2-/* This is the number of 64 bit words sent over the wire */ -#define BITS_TO_U64S (nr) DIV_ROUND_UP(nr, 64)static bool
load_bitmap(QEMUFile *f, void *pv, size_t size, const VMStateField *field, Error **errp){
PATCH v5 4/4 hw/intc/imsic: Add in-kernel imsic save and restore function
In reply to Wang YechaoFrom: Xuemei Liu <[email protected]>
Add save and restore function if kvm_irqchip_in_kernel() return true, it is to get and set IMSIC irqchip state from KVM kernel.
--- hw/intc/riscv_imsic.c | 180 +++++++++++++++++++++++++++++++--- include/hw/intc/riscv_imsic.h | 3 + 2 files changed, 169 insertions(+), 14 deletions(-)
hw/intc/riscv_imsic.c +166 -14
@@ -34,6 +34,7 @@#include "system/system.h" #include "system/kvm.h" #include "migration/vmstate.h" +#include "kvm/kvm_riscv.h" #define IMSIC_MMIO_PAGE_LE 0x00#define IMSIC_MMIO_PAGE_BE 0x04
@@ -408,11 +409,16 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp)qdev_init_gpio_out (dev, imsic->external_irqs, imsic->num_pages); imsic->num_eistate = imsic->num_pages * imsic->num_irqs; - imsic->eidelivery =g_new0 (uint32_t, imsic->num_pages); - imsic->eithreshold =g_new0 (uint32_t, imsic->num_pages); imsic->eistate =g_new0 (uint32_t, imsic->num_eistate); + }else { + imsic->nr_eix =2 *BITS_TO_U64S (imsic->num_irqs); + imsic->eie =g_new0 (uint32_t, imsic->nr_eix); + imsic->eip =g_new0 (uint32_t, imsic->nr_eix); } + imsic->eidelivery =g_new0 (uint32_t, imsic->num_pages); + imsic->eithreshold =g_new0 (uint32_t, imsic->num_pages); +memory_region_init_io (&imsic->mmio,OBJECT (dev), &riscv_imsic_ops, imsic,TYPE_RISCV_IMSIC ,IMSIC_MMIO_SIZE (imsic->num_pages));
@@ -443,23 +449,17 @@ static const Property riscv_imsic_properties[] = { DEFINE_PROP_UINT32("num-irqs", RISCVIMSICState, num_irqs, 0), }; -static bool riscv_imsic_state_needed (void *opaque) +static bool riscv_emulated_imsic_state_needed (void *opaque) {return !kvm_irqchip_in_kernel (); } -static const VMStateDescription vmstate_riscv_imsic = { - .name ="riscv_imsic" , - .version_id =2 , - .minimum_version_id =2 , - .needed = riscv_imsic_state_needed, +static const VMStateDescription vmstate_emulated_imsic_state = { + .name ="riscv_imsic/emulated_imsic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = riscv_emulated_imsic_state_needed, .fields = (const VMStateField []) { -VMSTATE_VARRAY_UINT32 (eidelivery, RISCVIMSICState, - num_pages,0 , - vmstate_info_uint32, uint32_t), -VMSTATE_VARRAY_UINT32 (eithreshold, RISCVIMSICState, - num_pages,0 , - vmstate_info_uint32, uint32_t),VMSTATE_VARRAY_UINT32 (eistate, RISCVIMSICState, num_eistate,0 , vmstate_info_uint32, uint32_t),
@@ -467,6 +467,158 @@ static const VMStateDescription vmstate_riscv_imsic = { } }; +#ifdef CONFIG_KVM +static bool kvm_riscv_imsic_state_needed (void *opaque) +{ +return kvm_irqchip_in_kernel (); +} + +static int kvm_riscv_imsic_state_pre_save (void *opaque) +{ +RISCVIMSICState *imsic = opaque; +RISCVCPU *rcpu =RISCV_CPU (cpu_by_arch_id (imsic->hartid)); +bool is_32bit =riscv_cpu_is_32bit (rcpu); +uint32_t inc =2 ; +uint64_t attr; + +if (is_32bit) { + inc =1 ; + } + +for (uint32_t i =0 ; i < imsic->nr_eix; i += inc) { + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIE0 + i); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eie + i, false); + + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIP0 + i); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eip + i, false); + } + +return 0 ; +} + +static int kvm_riscv_imsic_state_post_load (void *opaque,int version_id) +{ +RISCVIMSICState *imsic = opaque; +RISCVCPU *rcpu =RISCV_CPU (cpu_by_arch_id (imsic->hartid)); +bool is_32bit =riscv_cpu_is_32bit (rcpu); +uint32_t inc =2 ; +uint64_t attr; + +if (is_32bit) { + inc =1 ; + } + +for (uint32_t i =0 ; i < imsic->nr_eix; i += inc) { + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIE0 + i); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eie + i, true); + + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIP0 + i); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eip + i, true); + } + +return 0 ; +} + +static const VMStateDescription vmstate_kvm_imsic_state = { + .name ="riscv_imsic/kvm_imsic_state" , + .version_id =1 , + .minimum_version_id =1 , + .needed = kvm_riscv_imsic_state_needed, + .pre_save = kvm_riscv_imsic_state_pre_save, + .post_load = kvm_riscv_imsic_state_post_load, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (eie, RISCVIMSICState, + nr_eix,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (eip, RISCVIMSICState, + nr_eix,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + } +}; + +static int riscv_imsic_pre_save (void *opaque) +{ +RISCVIMSICState *imsic = opaque; +uint64_t attr; + +if (kvm_irqchip_in_kernel ()) { + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIDELIVERY ); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eidelivery, false); + + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EITHRESHOLD ); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eithreshold, false); + } + +return 0 ; +} + +static int riscv_imsic_post_load (void *opaque,int version_id) +{ +RISCVIMSICState *imsic = opaque; +uint64_t attr; + +if (kvm_irqchip_in_kernel ()) { + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EIDELIVERY ); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eidelivery, true); + + attr =KVM_DEV_RISCV_AIA_IMSIC_MKATTR (imsic->hartid, +ISELECT_IMSIC_EITHRESHOLD ); +kvm_riscv_aia_access_reg (KVM_DEV_RISCV_AIA_GRP_IMSIC , attr, + imsic->eithreshold, true); + } + +return 0 ; +} +#else +static int riscv_imsic_pre_save (void *opaque) +{ +return 0 ; +} +static int riscv_imsic_post_load (void *opaque,int version_id) +{ +return 0 ; +} +#endif + +static const VMStateDescription vmstate_riscv_imsic = { + .name ="riscv_imsic" , + .version_id =3 , + .minimum_version_id =3 , + .pre_save = riscv_imsic_pre_save, + .post_load = riscv_imsic_post_load, + .fields = (const VMStateField []) { +VMSTATE_VARRAY_UINT32 (eidelivery, RISCVIMSICState, + num_pages,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_VARRAY_UINT32 (eithreshold, RISCVIMSICState, + num_pages,0 , + vmstate_info_uint32, uint32_t), +VMSTATE_END_OF_LIST () + }, + .subsections = (const VMStateDescription *const []) { + &vmstate_emulated_imsic_state, +#ifdef CONFIG_KVM + &vmstate_kvm_imsic_state, +#endif +NULL + } +}; +static void riscv_imsic_class_init (ObjectClass *klass,const void *data) {DeviceClass *dc =DEVICE_CLASS (klass);
include/hw/intc/riscv_imsic.h +3 -0
@@ -53,12 +53,15 @@ struct RISCVIMSICState {uint32_t *eidelivery;uint32_t *eithreshold;uint32_t *eistate; +uint32_t *eip; +uint32_t *eie;/* config */ bool mmode;uint32_t hartid;uint32_t num_pages;uint32_t num_irqs; +uint32_t nr_eix; }; DeviceState *riscv_imsic_create(MemoryRegion *container, hwaddr addr,
Signature · 1 line
2.27.0
Alistair Francis
AppliedQuoted 34 lines · Wang Yechao
This series adds support for in-kernel AIA irqchip save and restore on RISC-V.
Changes in v5:
- Fix typos in the patch descriptions.
- Split the non-RISC-V-specific changes into a separate patch (patch 03).
- Drop the TCG vmstate debug fix from this series.
- Link to v4:
https://lore.kernel.org/qemu-devel/[email protected]/Changes in v4:
- Fix build issues in the TCG-only configuration.
- Rename several functions to make them more readable.
- Fix the missing section footer problem.
- Add patch 04, which fixes an assertion failure during save on --disable-tcg builds.- Link to v3:
https://lore.kernel.org/qemu-devel/[email protected]/
Changes in v3:
- Removed unnecessary changes inbitops.h
- Link to v2:
https://lore.kernel.org/qemu-devel/[email protected]/Changes in v2:
- Added theBITS_TO_U64Smacro
- Added thenr_eixfield and dynamically allocated the eie/eip arrays
- Replaced theCONFIG_32BITmacro withis_32bitboolean flag
- Link to v1:
https://lore.kernel.org/qemu-devel/[email protected]/
Quoted 7 lines
Wang Yechao (1):
include/qemu/bitops: MoveBITS_TO_U64Stobitops.hXuemei Liu (3):
target/riscv/kvm: createkvm_riscv_aia_access_reghw/intc/riscv_aplic: Add in-kernel aplic save and restore function hw/intc/imsic: Add in-kernel imsic save and restore function
Thanks!
Applied to riscv-to-apply.next
Alistair
Quoted 11 lines
hw/intc/riscv_aplic.c | 201 +++++++++++++++++++++++++++++--- --
hw/intc/riscv_imsic.c | 180 +++++++++++++++++++++++++++---include/hw/intc/riscv_aplic.h| 4 +include/hw/intc/riscv_imsic.h| 3 + include/qemu/bitops.h | 1 + migration/vmstate-types.c | 3 +- target/riscv/kvm/kvm-cpu.c | 7 +- target/riscv/kvm/kvm_riscv.h | 1 +8 files changed, 357 insertions(+), 43 deletions(-)