aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/loongarch_pch_pic.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc/loongarch_pch_pic.c')
-rw-r--r--hw/intc/loongarch_pch_pic.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
index cbba2fc..c4b242d 100644
--- a/hw/intc/loongarch_pch_pic.c
+++ b/hw/intc/loongarch_pch_pic.c
@@ -10,6 +10,7 @@
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/intc/loongarch_pch_pic.h"
+#include "system/kvm.h"
#include "trace.h"
#include "qapi/error.h"
@@ -48,6 +49,11 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level)
assert(irq < s->irq_num);
trace_loongarch_pch_pic_irq_handler(irq, level);
+ if (kvm_irqchip_in_kernel()) {
+ kvm_set_irq(kvm_state, irq, !!level);
+ return;
+ }
+
if (s->intedge & mask) {
/* Edge triggered */
if (level) {
@@ -82,7 +88,7 @@ static uint64_t pch_pic_read(void *opaque, hwaddr addr, uint64_t field_mask)
addr -= offset;
switch (addr) {
case PCH_PIC_INT_ID:
- val = s->id.data;
+ val = cpu_to_le64(s->id.data);
break;
case PCH_PIC_INT_MASK:
val = s->int_mask;
@@ -258,6 +264,10 @@ static void loongarch_pic_reset_hold(Object *obj, ResetType type)
if (lpc->parent_phases.hold) {
lpc->parent_phases.hold(obj, type);
}
+
+ if (kvm_irqchip_in_kernel()) {
+ kvm_pic_put(obj, 0);
+ }
}
static void loongarch_pic_realize(DeviceState *dev, Error **errp)
@@ -275,22 +285,49 @@ static void loongarch_pic_realize(DeviceState *dev, Error **errp)
qdev_init_gpio_out(dev, s->parent_irq, s->irq_num);
qdev_init_gpio_in(dev, pch_pic_irq_handler, s->irq_num);
- memory_region_init_io(&s->iomem, OBJECT(dev),
- &loongarch_pch_pic_ops,
- s, TYPE_LOONGARCH_PIC, VIRT_PCH_REG_SIZE);
- sysbus_init_mmio(sbd, &s->iomem);
+
+ if (kvm_irqchip_in_kernel()) {
+ kvm_pic_realize(dev, errp);
+ } else {
+ memory_region_init_io(&s->iomem, OBJECT(dev),
+ &loongarch_pch_pic_ops,
+ s, TYPE_LOONGARCH_PIC, VIRT_PCH_REG_SIZE);
+ sysbus_init_mmio(sbd, &s->iomem);
+ }
+}
+
+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[] = {