hw/intc/loongarch_pch: Add kernel irqchip save and restore function

Add save and store funtction if kvm_irqchip_in_kernel() return true,
it is to get and set PCH PCI irqchip state from KVM kernel.

Reviewed-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
Message-ID: <20250606063033.2557365-9-maobibo@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
This commit is contained in:
Bibo Mao 2025-06-06 14:30:28 +08:00 committed by Song Gao
parent b758e28974
commit 11a04c9f40
4 changed files with 72 additions and 0 deletions

View file

@ -287,16 +287,38 @@ static void loongarch_pic_realize(DeviceState *dev, Error **errp)
}
}
static int loongarch_pic_pre_save(LoongArchPICCommonState *opaque)
{
if (kvm_irqchip_in_kernel()) {
return kvm_pic_get(opaque);
}
return 0;
}
static int loongarch_pic_post_load(LoongArchPICCommonState *opaque,
int version_id)
{
if (kvm_irqchip_in_kernel()) {
return kvm_pic_put(opaque, version_id);
}
return 0;
}
static void loongarch_pic_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
LoongarchPICClass *lpc = LOONGARCH_PIC_CLASS(klass);
LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
resettable_class_set_parent_phases(rc, NULL, loongarch_pic_reset_hold,
NULL, &lpc->parent_phases);
device_class_set_parent_realize(dc, loongarch_pic_realize,
&lpc->parent_realize);
lpcc->pre_save = loongarch_pic_pre_save;
lpcc->post_load = loongarch_pic_post_load;
}
static const TypeInfo loongarch_pic_types[] = {

View file

@ -13,6 +13,53 @@
#include "hw/pci-host/ls7a.h"
#include "system/kvm.h"
static void kvm_pch_pic_access_reg(int fd, uint64_t addr, void *val, bool write)
{
kvm_device_access(fd, KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS,
addr, val, write, &error_abort);
}
static void kvm_pch_pic_access(void *opaque, bool write)
{
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
LoongarchPICState *lps = LOONGARCH_PIC(opaque);
int fd = lps->dev_fd;
int addr, offset;
kvm_pch_pic_access_reg(fd, PCH_PIC_INT_MASK, &s->int_mask, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_HTMSI_EN, &s->htmsi_en, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_INT_EDGE, &s->intedge, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_AUTO_CTRL0, &s->auto_crtl0, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_AUTO_CTRL1, &s->auto_crtl1, write);
for (addr = PCH_PIC_ROUTE_ENTRY;
addr < PCH_PIC_ROUTE_ENTRY_END; addr++) {
offset = addr - PCH_PIC_ROUTE_ENTRY;
kvm_pch_pic_access_reg(fd, addr, &s->route_entry[offset], write);
}
for (addr = PCH_PIC_HTMSI_VEC; addr < PCH_PIC_HTMSI_VEC_END; addr++) {
offset = addr - PCH_PIC_HTMSI_VEC;
kvm_pch_pic_access_reg(fd, addr, &s->htmsi_vector[offset], write);
}
kvm_pch_pic_access_reg(fd, PCH_PIC_INT_REQUEST, &s->intirr, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_INT_STATUS, &s->intisr, write);
kvm_pch_pic_access_reg(fd, PCH_PIC_INT_POL, &s->int_polarity, write);
}
int kvm_pic_get(void *opaque)
{
kvm_pch_pic_access(opaque, false);
return 0;
}
int kvm_pic_put(void *opaque, int version_id)
{
kvm_pch_pic_access(opaque, true);
return 0;
}
void kvm_pic_realize(DeviceState *dev, Error **errp)
{
LoongarchPICState *lps = LOONGARCH_PIC(dev);

View file

@ -27,5 +27,7 @@ struct LoongarchPICClass {
};
void kvm_pic_realize(DeviceState *dev, Error **errp);
int kvm_pic_get(void *opaque);
int kvm_pic_put(void *opaque, int version_id);
#endif /* HW_LOONGARCH_PCH_PIC_H */

View file

@ -23,6 +23,7 @@
#define PCH_PIC_ROUTE_ENTRY_END 0x13f
#define PCH_PIC_HTMSI_VEC 0x200
#define PCH_PIC_HTMSI_VEC_END 0x23f
#define PCH_PIC_INT_REQUEST 0x380
#define PCH_PIC_INT_STATUS 0x3a0
#define PCH_PIC_INT_POL 0x3e0