diff options
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/arm_gic.c | 2 | ||||
-rw-r--r-- | hw/intc/arm_gic_common.c | 1 | ||||
-rw-r--r-- | hw/intc/aspeed_intc.c | 424 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi.c | 61 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi_common.c | 41 | ||||
-rw-r--r-- | hw/intc/loongarch_extioi_kvm.c | 140 | ||||
-rw-r--r-- | hw/intc/loongarch_ipi.c | 58 | ||||
-rw-r--r-- | hw/intc/loongarch_ipi_kvm.c | 85 | ||||
-rw-r--r-- | hw/intc/loongarch_pch_msi.c | 10 | ||||
-rw-r--r-- | hw/intc/loongarch_pch_pic.c | 392 | ||||
-rw-r--r-- | hw/intc/loongarch_pic_common.c | 38 | ||||
-rw-r--r-- | hw/intc/loongarch_pic_kvm.c | 89 | ||||
-rw-r--r-- | hw/intc/loongson_ipi_common.c | 33 | ||||
-rw-r--r-- | hw/intc/meson.build | 6 | ||||
-rw-r--r-- | hw/intc/omap_intc.c | 154 | ||||
-rw-r--r-- | hw/intc/trace-events | 8 |
16 files changed, 1204 insertions, 338 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index d18bef4..899f133 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -59,7 +59,7 @@ static const uint8_t gic_id_gicv2[] = { static inline int gic_get_current_cpu(GICState *s) { if (!qtest_enabled() && s->num_cpu > 1) { - return current_cpu->cpu_index; + return current_cpu->cpu_index - s->first_cpu_index; } return 0; } diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index 0f0c48d..ed5be05 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -350,6 +350,7 @@ static void arm_gic_common_linux_init(ARMLinuxBootIf *obj, static const Property arm_gic_common_properties[] = { DEFINE_PROP_UINT32("num-cpu", GICState, num_cpu, 1), + DEFINE_PROP_UINT32("first-cpu-index", GICState, first_cpu_index, 0), DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32), /* Revision can be 1 or 2 for GIC architecture specification * versions 1 or 2, or 0 to indicate the legacy 11MPCore GIC. diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c index be7f516..5cd786d 100644 --- a/hw/intc/aspeed_intc.c +++ b/hw/intc/aspeed_intc.c @@ -62,6 +62,95 @@ REG32(GICINT196_STATUS, 0x44) REG32(GICINT197_EN, 0x50) REG32(GICINT197_STATUS, 0x54) +/* + * SSP INTC Registers + */ +REG32(SSPINT128_EN, 0x2000) +REG32(SSPINT128_STATUS, 0x2004) +REG32(SSPINT129_EN, 0x2100) +REG32(SSPINT129_STATUS, 0x2104) +REG32(SSPINT130_EN, 0x2200) +REG32(SSPINT130_STATUS, 0x2204) +REG32(SSPINT131_EN, 0x2300) +REG32(SSPINT131_STATUS, 0x2304) +REG32(SSPINT132_EN, 0x2400) +REG32(SSPINT132_STATUS, 0x2404) +REG32(SSPINT133_EN, 0x2500) +REG32(SSPINT133_STATUS, 0x2504) +REG32(SSPINT134_EN, 0x2600) +REG32(SSPINT134_STATUS, 0x2604) +REG32(SSPINT135_EN, 0x2700) +REG32(SSPINT135_STATUS, 0x2704) +REG32(SSPINT136_EN, 0x2800) +REG32(SSPINT136_STATUS, 0x2804) +REG32(SSPINT137_EN, 0x2900) +REG32(SSPINT137_STATUS, 0x2904) +REG32(SSPINT138_EN, 0x2A00) +REG32(SSPINT138_STATUS, 0x2A04) +REG32(SSPINT160_169_EN, 0x2B00) +REG32(SSPINT160_169_STATUS, 0x2B04) + +/* + * SSP INTCIO Registers + */ +REG32(SSPINT160_EN, 0x180) +REG32(SSPINT160_STATUS, 0x184) +REG32(SSPINT161_EN, 0x190) +REG32(SSPINT161_STATUS, 0x194) +REG32(SSPINT162_EN, 0x1A0) +REG32(SSPINT162_STATUS, 0x1A4) +REG32(SSPINT163_EN, 0x1B0) +REG32(SSPINT163_STATUS, 0x1B4) +REG32(SSPINT164_EN, 0x1C0) +REG32(SSPINT164_STATUS, 0x1C4) +REG32(SSPINT165_EN, 0x1D0) +REG32(SSPINT165_STATUS, 0x1D4) + +/* + * TSP INTC Registers + */ +REG32(TSPINT128_EN, 0x3000) +REG32(TSPINT128_STATUS, 0x3004) +REG32(TSPINT129_EN, 0x3100) +REG32(TSPINT129_STATUS, 0x3104) +REG32(TSPINT130_EN, 0x3200) +REG32(TSPINT130_STATUS, 0x3204) +REG32(TSPINT131_EN, 0x3300) +REG32(TSPINT131_STATUS, 0x3304) +REG32(TSPINT132_EN, 0x3400) +REG32(TSPINT132_STATUS, 0x3404) +REG32(TSPINT133_EN, 0x3500) +REG32(TSPINT133_STATUS, 0x3504) +REG32(TSPINT134_EN, 0x3600) +REG32(TSPINT134_STATUS, 0x3604) +REG32(TSPINT135_EN, 0x3700) +REG32(TSPINT135_STATUS, 0x3704) +REG32(TSPINT136_EN, 0x3800) +REG32(TSPINT136_STATUS, 0x3804) +REG32(TSPINT137_EN, 0x3900) +REG32(TSPINT137_STATUS, 0x3904) +REG32(TSPINT138_EN, 0x3A00) +REG32(TSPINT138_STATUS, 0x3A04) +REG32(TSPINT160_169_EN, 0x3B00) +REG32(TSPINT160_169_STATUS, 0x3B04) + +/* + * TSP INTCIO Registers + */ + +REG32(TSPINT160_EN, 0x200) +REG32(TSPINT160_STATUS, 0x204) +REG32(TSPINT161_EN, 0x210) +REG32(TSPINT161_STATUS, 0x214) +REG32(TSPINT162_EN, 0x220) +REG32(TSPINT162_STATUS, 0x224) +REG32(TSPINT163_EN, 0x230) +REG32(TSPINT163_STATUS, 0x234) +REG32(TSPINT164_EN, 0x240) +REG32(TSPINT164_STATUS, 0x244) +REG32(TSPINT165_EN, 0x250) +REG32(TSPINT165_STATUS, 0x254) + static const AspeedINTCIRQ *aspeed_intc_get_irq(AspeedINTCClass *aic, uint32_t reg) { @@ -450,6 +539,90 @@ static void aspeed_intc_write(void *opaque, hwaddr offset, uint64_t data, } } +static void aspeed_ssp_intc_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedINTCState *s = ASPEED_INTC(opaque); + const char *name = object_get_typename(OBJECT(s)); + uint32_t reg = offset >> 2; + + trace_aspeed_intc_write(name, offset, size, data); + + switch (reg) { + case R_SSPINT128_EN: + case R_SSPINT129_EN: + case R_SSPINT130_EN: + case R_SSPINT131_EN: + case R_SSPINT132_EN: + case R_SSPINT133_EN: + case R_SSPINT134_EN: + case R_SSPINT135_EN: + case R_SSPINT136_EN: + case R_SSPINT160_169_EN: + aspeed_intc_enable_handler(s, offset, data); + break; + case R_SSPINT128_STATUS: + case R_SSPINT129_STATUS: + case R_SSPINT130_STATUS: + case R_SSPINT131_STATUS: + case R_SSPINT132_STATUS: + case R_SSPINT133_STATUS: + case R_SSPINT134_STATUS: + case R_SSPINT135_STATUS: + case R_SSPINT136_STATUS: + aspeed_intc_status_handler(s, offset, data); + break; + case R_SSPINT160_169_STATUS: + aspeed_intc_status_handler_multi_outpins(s, offset, data); + break; + default: + s->regs[reg] = data; + break; + } +} + +static void aspeed_tsp_intc_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedINTCState *s = ASPEED_INTC(opaque); + const char *name = object_get_typename(OBJECT(s)); + uint32_t reg = offset >> 2; + + trace_aspeed_intc_write(name, offset, size, data); + + switch (reg) { + case R_TSPINT128_EN: + case R_TSPINT129_EN: + case R_TSPINT130_EN: + case R_TSPINT131_EN: + case R_TSPINT132_EN: + case R_TSPINT133_EN: + case R_TSPINT134_EN: + case R_TSPINT135_EN: + case R_TSPINT136_EN: + case R_TSPINT160_169_EN: + aspeed_intc_enable_handler(s, offset, data); + break; + case R_TSPINT128_STATUS: + case R_TSPINT129_STATUS: + case R_TSPINT130_STATUS: + case R_TSPINT131_STATUS: + case R_TSPINT132_STATUS: + case R_TSPINT133_STATUS: + case R_TSPINT134_STATUS: + case R_TSPINT135_STATUS: + case R_TSPINT136_STATUS: + aspeed_intc_status_handler(s, offset, data); + break; + case R_TSPINT160_169_STATUS: + aspeed_intc_status_handler_multi_outpins(s, offset, data); + break; + default: + s->regs[reg] = data; + break; + } +} + static uint64_t aspeed_intcio_read(void *opaque, hwaddr offset, unsigned int size) { @@ -496,11 +669,75 @@ static void aspeed_intcio_write(void *opaque, hwaddr offset, uint64_t data, } } +static void aspeed_ssp_intcio_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedINTCState *s = ASPEED_INTC(opaque); + const char *name = object_get_typename(OBJECT(s)); + uint32_t reg = offset >> 2; + + trace_aspeed_intc_write(name, offset, size, data); + + switch (reg) { + case R_SSPINT160_EN: + case R_SSPINT161_EN: + case R_SSPINT162_EN: + case R_SSPINT163_EN: + case R_SSPINT164_EN: + case R_SSPINT165_EN: + aspeed_intc_enable_handler(s, offset, data); + break; + case R_SSPINT160_STATUS: + case R_SSPINT161_STATUS: + case R_SSPINT162_STATUS: + case R_SSPINT163_STATUS: + case R_SSPINT164_STATUS: + case R_SSPINT165_STATUS: + aspeed_intc_status_handler(s, offset, data); + break; + default: + s->regs[reg] = data; + break; + } +} + +static void aspeed_tsp_intcio_write(void *opaque, hwaddr offset, uint64_t data, + unsigned size) +{ + AspeedINTCState *s = ASPEED_INTC(opaque); + const char *name = object_get_typename(OBJECT(s)); + uint32_t reg = offset >> 2; + + trace_aspeed_intc_write(name, offset, size, data); + + switch (reg) { + case R_TSPINT160_EN: + case R_TSPINT161_EN: + case R_TSPINT162_EN: + case R_TSPINT163_EN: + case R_TSPINT164_EN: + case R_TSPINT165_EN: + aspeed_intc_enable_handler(s, offset, data); + break; + case R_TSPINT160_STATUS: + case R_TSPINT161_STATUS: + case R_TSPINT162_STATUS: + case R_TSPINT163_STATUS: + case R_TSPINT164_STATUS: + case R_TSPINT165_STATUS: + aspeed_intc_status_handler(s, offset, data); + break; + default: + s->regs[reg] = data; + break; + } +} static const MemoryRegionOps aspeed_intc_ops = { .read = aspeed_intc_read, .write = aspeed_intc_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -511,6 +748,51 @@ static const MemoryRegionOps aspeed_intcio_ops = { .read = aspeed_intcio_read, .write = aspeed_intcio_write, .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static const MemoryRegionOps aspeed_ssp_intc_ops = { + .read = aspeed_intc_read, + .write = aspeed_ssp_intc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static const MemoryRegionOps aspeed_ssp_intcio_ops = { + .read = aspeed_intcio_read, + .write = aspeed_ssp_intcio_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static const MemoryRegionOps aspeed_tsp_intc_ops = { + .read = aspeed_intc_read, + .write = aspeed_tsp_intc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + +static const MemoryRegionOps aspeed_tsp_intcio_ops = { + .read = aspeed_intcio_read, + .write = aspeed_tsp_intcio_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl.min_access_size = 4, .valid = { .min_access_size = 4, .max_access_size = 4, @@ -674,11 +956,153 @@ static const TypeInfo aspeed_2700_intcio_info = { .class_init = aspeed_2700_intcio_class_init, }; +static AspeedINTCIRQ aspeed_2700ssp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 0, 10, R_SSPINT160_169_EN, R_SSPINT160_169_STATUS}, + {1, 10, 1, R_SSPINT128_EN, R_SSPINT128_STATUS}, + {2, 11, 1, R_SSPINT129_EN, R_SSPINT129_STATUS}, + {3, 12, 1, R_SSPINT130_EN, R_SSPINT130_STATUS}, + {4, 13, 1, R_SSPINT131_EN, R_SSPINT131_STATUS}, + {5, 14, 1, R_SSPINT132_EN, R_SSPINT132_STATUS}, + {6, 15, 1, R_SSPINT133_EN, R_SSPINT133_STATUS}, + {7, 16, 1, R_SSPINT134_EN, R_SSPINT134_STATUS}, + {8, 17, 1, R_SSPINT135_EN, R_SSPINT135_STATUS}, + {9, 18, 1, R_SSPINT136_EN, R_SSPINT136_STATUS}, +}; + +static void aspeed_2700ssp_intc_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 SSP INTC Controller"; + aic->num_lines = 32; + aic->num_inpins = 10; + aic->num_outpins = 19; + aic->mem_size = 0x4000; + aic->nr_regs = 0x2B08 >> 2; + aic->reg_offset = 0x0; + aic->reg_ops = &aspeed_ssp_intc_ops; + aic->irq_table = aspeed_2700ssp_intc_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intc_irqs); +} + +static const TypeInfo aspeed_2700ssp_intc_info = { + .name = TYPE_ASPEED_2700SSP_INTC, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700ssp_intc_class_init, +}; + +static AspeedINTCIRQ aspeed_2700ssp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 0, 1, R_SSPINT160_EN, R_SSPINT160_STATUS}, + {1, 1, 1, R_SSPINT161_EN, R_SSPINT161_STATUS}, + {2, 2, 1, R_SSPINT162_EN, R_SSPINT162_STATUS}, + {3, 3, 1, R_SSPINT163_EN, R_SSPINT163_STATUS}, + {4, 4, 1, R_SSPINT164_EN, R_SSPINT164_STATUS}, + {5, 5, 1, R_SSPINT165_EN, R_SSPINT165_STATUS}, +}; + +static void aspeed_2700ssp_intcio_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 SSP INTC IO Controller"; + aic->num_lines = 32; + aic->num_inpins = 6; + aic->num_outpins = 6; + aic->mem_size = 0x400; + aic->nr_regs = 0x1d8 >> 2; + aic->reg_offset = 0; + aic->reg_ops = &aspeed_ssp_intcio_ops; + aic->irq_table = aspeed_2700ssp_intcio_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700ssp_intcio_irqs); +} + +static const TypeInfo aspeed_2700ssp_intcio_info = { + .name = TYPE_ASPEED_2700SSP_INTCIO, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700ssp_intcio_class_init, +}; + +static AspeedINTCIRQ aspeed_2700tsp_intc_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 0, 10, R_TSPINT160_169_EN, R_TSPINT160_169_STATUS}, + {1, 10, 1, R_TSPINT128_EN, R_TSPINT128_STATUS}, + {2, 11, 1, R_TSPINT129_EN, R_TSPINT129_STATUS}, + {3, 12, 1, R_TSPINT130_EN, R_TSPINT130_STATUS}, + {4, 13, 1, R_TSPINT131_EN, R_TSPINT131_STATUS}, + {5, 14, 1, R_TSPINT132_EN, R_TSPINT132_STATUS}, + {6, 15, 1, R_TSPINT133_EN, R_TSPINT133_STATUS}, + {7, 16, 1, R_TSPINT134_EN, R_TSPINT134_STATUS}, + {8, 17, 1, R_TSPINT135_EN, R_TSPINT135_STATUS}, + {9, 18, 1, R_TSPINT136_EN, R_TSPINT136_STATUS}, +}; + +static void aspeed_2700tsp_intc_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 TSP INTC Controller"; + aic->num_lines = 32; + aic->num_inpins = 10; + aic->num_outpins = 19; + aic->mem_size = 0x4000; + aic->nr_regs = 0x3B08 >> 2; + aic->reg_offset = 0; + aic->reg_ops = &aspeed_tsp_intc_ops; + aic->irq_table = aspeed_2700tsp_intc_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intc_irqs); +} + +static const TypeInfo aspeed_2700tsp_intc_info = { + .name = TYPE_ASPEED_2700TSP_INTC, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700tsp_intc_class_init, +}; + +static AspeedINTCIRQ aspeed_2700tsp_intcio_irqs[ASPEED_INTC_MAX_INPINS] = { + {0, 0, 1, R_TSPINT160_EN, R_TSPINT160_STATUS}, + {1, 1, 1, R_TSPINT161_EN, R_TSPINT161_STATUS}, + {2, 2, 1, R_TSPINT162_EN, R_TSPINT162_STATUS}, + {3, 3, 1, R_TSPINT163_EN, R_TSPINT163_STATUS}, + {4, 4, 1, R_TSPINT164_EN, R_TSPINT164_STATUS}, + {5, 5, 1, R_TSPINT165_EN, R_TSPINT165_STATUS}, +}; + +static void aspeed_2700tsp_intcio_class_init(ObjectClass *klass, + const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass); + + dc->desc = "ASPEED 2700 TSP INTC IO Controller"; + aic->num_lines = 32; + aic->num_inpins = 6; + aic->num_outpins = 6; + aic->mem_size = 0x400; + aic->nr_regs = 0x258 >> 2; + aic->reg_offset = 0x0; + aic->reg_ops = &aspeed_tsp_intcio_ops; + aic->irq_table = aspeed_2700tsp_intcio_irqs; + aic->irq_table_count = ARRAY_SIZE(aspeed_2700tsp_intcio_irqs); +} + +static const TypeInfo aspeed_2700tsp_intcio_info = { + .name = TYPE_ASPEED_2700TSP_INTCIO, + .parent = TYPE_ASPEED_INTC, + .class_init = aspeed_2700tsp_intcio_class_init, +}; + static void aspeed_intc_register_types(void) { type_register_static(&aspeed_intc_info); type_register_static(&aspeed_2700_intc_info); type_register_static(&aspeed_2700_intcio_info); + type_register_static(&aspeed_2700ssp_intc_info); + type_register_static(&aspeed_2700ssp_intcio_info); + type_register_static(&aspeed_2700tsp_intc_info); + type_register_static(&aspeed_2700tsp_intcio_info); } type_init(aspeed_intc_register_types); diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c index f4fe961..8b8ac6b 100644 --- a/hw/intc/loongarch_extioi.c +++ b/hw/intc/loongarch_extioi.c @@ -12,6 +12,7 @@ #include "hw/irq.h" #include "hw/loongarch/virt.h" #include "system/address-spaces.h" +#include "system/kvm.h" #include "hw/intc/loongarch_extioi.h" #include "trace.h" @@ -351,23 +352,29 @@ static void loongarch_extioi_realize(DeviceState *dev, Error **errp) return; } - for (i = 0; i < EXTIOI_IRQS; i++) { - sysbus_init_irq(sbd, &s->irq[i]); - } - - qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS); - memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops, - s, "extioi_system_mem", 0x900); - sysbus_init_mmio(sbd, &s->extioi_system_mem); - if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) { - memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops, - s, "extioi_virt", EXTIOI_VIRT_SIZE); - sysbus_init_mmio(sbd, &s->virt_extend); s->features |= EXTIOI_VIRT_HAS_FEATURES; } else { s->status |= BIT(EXTIOI_ENABLE); } + + if (kvm_irqchip_in_kernel()) { + kvm_extioi_realize(dev, errp); + } else { + for (i = 0; i < EXTIOI_IRQS; i++) { + sysbus_init_irq(sbd, &s->irq[i]); + } + + qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS); + memory_region_init_io(&s->extioi_system_mem, OBJECT(s), &extioi_ops, + s, "extioi_system_mem", 0x900); + sysbus_init_mmio(sbd, &s->extioi_system_mem); + if (s->features & BIT(EXTIOI_HAS_VIRT_EXTENSION)) { + memory_region_init_io(&s->virt_extend, OBJECT(s), &extioi_virt_ops, + s, "extioi_virt", EXTIOI_VIRT_SIZE); + sysbus_init_mmio(sbd, &s->virt_extend); + } + } } static void loongarch_extioi_unrealize(DeviceState *dev) @@ -377,11 +384,26 @@ static void loongarch_extioi_unrealize(DeviceState *dev) g_free(s->cpu); } -static void loongarch_extioi_reset(DeviceState *d) +static void loongarch_extioi_reset_hold(Object *obj, ResetType type) +{ + LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_GET_CLASS(obj); + + if (lec->parent_phases.hold) { + lec->parent_phases.hold(obj, type); + } + + if (kvm_irqchip_in_kernel()) { + kvm_extioi_put(obj, 0); + } +} + +static int vmstate_extioi_pre_save(void *opaque) { - LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(d); + if (kvm_irqchip_in_kernel()) { + return kvm_extioi_get(opaque); + } - s->status = 0; + return 0; } static int vmstate_extioi_post_load(void *opaque, int version_id) @@ -389,6 +411,10 @@ static int vmstate_extioi_post_load(void *opaque, int version_id) LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(opaque); int i, start_irq; + if (kvm_irqchip_in_kernel()) { + return kvm_extioi_put(opaque, version_id); + } + for (i = 0; i < (EXTIOI_IRQS / 4); i++) { start_irq = i * 4; extioi_update_sw_coremap(s, start_irq, s->coremap[i], false); @@ -406,12 +432,15 @@ static void loongarch_extioi_class_init(ObjectClass *klass, const void *data) DeviceClass *dc = DEVICE_CLASS(klass); LoongArchExtIOIClass *lec = LOONGARCH_EXTIOI_CLASS(klass); LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_parent_realize(dc, loongarch_extioi_realize, &lec->parent_realize); device_class_set_parent_unrealize(dc, loongarch_extioi_unrealize, &lec->parent_unrealize); - device_class_set_legacy_reset(dc, loongarch_extioi_reset); + resettable_class_set_parent_phases(rc, NULL, loongarch_extioi_reset_hold, + NULL, &lec->parent_phases); + lecc->pre_save = vmstate_extioi_pre_save; lecc->post_load = vmstate_extioi_post_load; } diff --git a/hw/intc/loongarch_extioi_common.c b/hw/intc/loongarch_extioi_common.c index 9e15890..4a904b3 100644 --- a/hw/intc/loongarch_extioi_common.c +++ b/hw/intc/loongarch_extioi_common.c @@ -108,6 +108,43 @@ static void loongarch_extioi_common_realize(DeviceState *dev, Error **errp) } } +static void loongarch_extioi_common_reset_hold(Object *obj, ResetType type) +{ + LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_GET_CLASS(obj); + LoongArchExtIOICommonState *s = LOONGARCH_EXTIOI_COMMON(obj); + ExtIOICore *core; + int i; + + if (lecc->parent_phases.hold) { + lecc->parent_phases.hold(obj, type); + } + + /* Clear HW registers for the board */ + memset(s->nodetype, 0, sizeof(s->nodetype)); + memset(s->bounce, 0, sizeof(s->bounce)); + memset(s->isr, 0, sizeof(s->isr)); + memset(s->enable, 0, sizeof(s->enable)); + memset(s->ipmap, 0, sizeof(s->ipmap)); + memset(s->coremap, 0, sizeof(s->coremap)); + memset(s->sw_pending, 0, sizeof(s->sw_pending)); + memset(s->sw_ipmap, 0, sizeof(s->sw_ipmap)); + memset(s->sw_coremap, 0, sizeof(s->sw_coremap)); + + for (i = 0; i < s->num_cpu; i++) { + core = s->cpu + i; + /* EXTIOI with targeted CPU available however not present */ + if (!core->cpu) { + continue; + } + + /* Clear HW registers for CPUs */ + memset(core->coreisr, 0, sizeof(core->coreisr)); + memset(core->sw_isr, 0, sizeof(core->sw_isr)); + } + + s->status = 0; +} + static int loongarch_extioi_common_pre_save(void *opaque) { LoongArchExtIOICommonState *s = (LoongArchExtIOICommonState *)opaque; @@ -180,9 +217,13 @@ static void loongarch_extioi_common_class_init(ObjectClass *klass, DeviceClass *dc = DEVICE_CLASS(klass); LoongArchExtIOICommonClass *lecc = LOONGARCH_EXTIOI_COMMON_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_parent_realize(dc, loongarch_extioi_common_realize, &lecc->parent_realize); + resettable_class_set_parent_phases(rc, NULL, + loongarch_extioi_common_reset_hold, + NULL, &lecc->parent_phases); device_class_set_props(dc, extioi_properties); dc->vmsd = &vmstate_loongarch_extioi; hc->plug = loongarch_extioi_cpu_plug; diff --git a/hw/intc/loongarch_extioi_kvm.c b/hw/intc/loongarch_extioi_kvm.c new file mode 100644 index 0000000..0133540 --- /dev/null +++ b/hw/intc/loongarch_extioi_kvm.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch EXTIOI interrupt kvm support + * + * Copyright (C) 2025 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "qemu/typedefs.h" +#include "hw/intc/loongarch_extioi.h" +#include "linux/kvm.h" +#include "qapi/error.h" +#include "system/kvm.h" + +static void kvm_extioi_access_reg(int fd, uint64_t addr, void *val, bool write) +{ + kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS, + addr, val, write, &error_abort); +} + +static void kvm_extioi_access_sw_state(int fd, uint64_t addr, + void *val, bool write) +{ + kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS, + addr, val, write, &error_abort); +} + +static void kvm_extioi_access_sw_status(void *opaque, bool write) +{ + LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(opaque); + LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque); + int addr; + + addr = KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE; + kvm_extioi_access_sw_state(les->dev_fd, addr, &lecs->status, write); +} + +static void kvm_extioi_access_regs(void *opaque, bool write) +{ + LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(opaque); + LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque); + int fd = les->dev_fd; + int addr, offset, cpu; + + for (addr = EXTIOI_NODETYPE_START; addr < EXTIOI_NODETYPE_END; addr += 4) { + offset = (addr - EXTIOI_NODETYPE_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->nodetype[offset], write); + } + + for (addr = EXTIOI_IPMAP_START; addr < EXTIOI_IPMAP_END; addr += 4) { + offset = (addr - EXTIOI_IPMAP_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->ipmap[offset], write); + } + + for (addr = EXTIOI_ENABLE_START; addr < EXTIOI_ENABLE_END; addr += 4) { + offset = (addr - EXTIOI_ENABLE_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->enable[offset], write); + } + + for (addr = EXTIOI_BOUNCE_START; addr < EXTIOI_BOUNCE_END; addr += 4) { + offset = (addr - EXTIOI_BOUNCE_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->bounce[offset], write); + } + + for (addr = EXTIOI_ISR_START; addr < EXTIOI_ISR_END; addr += 4) { + offset = (addr - EXTIOI_ISR_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->isr[offset], write); + } + + for (addr = EXTIOI_COREMAP_START; addr < EXTIOI_COREMAP_END; addr += 4) { + offset = (addr - EXTIOI_COREMAP_START) / 4; + kvm_extioi_access_reg(fd, addr, &lecs->coremap[offset], write); + } + + for (cpu = 0; cpu < lecs->num_cpu; cpu++) { + for (addr = EXTIOI_COREISR_START; + addr < EXTIOI_COREISR_END; addr += 4) { + offset = (addr - EXTIOI_COREISR_START) / 4; + kvm_extioi_access_reg(fd, (cpu << 16) | addr, + &lecs->cpu[cpu].coreisr[offset], write); + } + } +} + +int kvm_extioi_get(void *opaque) +{ + kvm_extioi_access_regs(opaque, false); + kvm_extioi_access_sw_status(opaque, false); + return 0; +} + +int kvm_extioi_put(void *opaque, int version_id) +{ + LoongArchExtIOIState *les = LOONGARCH_EXTIOI(opaque); + int fd = les->dev_fd; + + if (fd == 0) { + return 0; + } + + kvm_extioi_access_regs(opaque, true); + kvm_extioi_access_sw_status(opaque, true); + kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL, + KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED, + NULL, true, &error_abort); + return 0; +} + +void kvm_extioi_realize(DeviceState *dev, Error **errp) +{ + LoongArchExtIOICommonState *lecs = LOONGARCH_EXTIOI_COMMON(dev); + LoongArchExtIOIState *les = LOONGARCH_EXTIOI(dev); + int ret; + + ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_EIOINTC, false); + if (ret < 0) { + fprintf(stderr, "create KVM_LOONGARCH_EIOINTC failed: %s\n", + strerror(-ret)); + abort(); + } + + les->dev_fd = ret; + ret = kvm_device_access(les->dev_fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL, + KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU, + &lecs->num_cpu, true, NULL); + if (ret < 0) { + fprintf(stderr, "KVM_LOONGARCH_EXTIOI_INIT_NUM_CPU failed: %s\n", + strerror(-ret)); + abort(); + } + + ret = kvm_device_access(les->dev_fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL, + KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE, + &lecs->features, true, NULL); + if (ret < 0) { + fprintf(stderr, "KVM_LOONGARCH_EXTIOI_INIT_FEATURE failed: %s\n", + strerror(-ret)); + abort(); + } +} diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c index 2f8bb57..fc8005c 100644 --- a/hw/intc/loongarch_ipi.c +++ b/hw/intc/loongarch_ipi.c @@ -11,6 +11,7 @@ #include "qapi/error.h" #include "hw/intc/loongarch_ipi.h" #include "hw/qdev-properties.h" +#include "system/kvm.h" #include "target/loongarch/cpu.h" static AddressSpace *get_iocsr_as(CPUState *cpu) @@ -91,6 +92,40 @@ static void loongarch_ipi_realize(DeviceState *dev, Error **errp) lics->cpu[i].ipi = lics; qdev_init_gpio_out(dev, &lics->cpu[i].irq, 1); } + + if (kvm_irqchip_in_kernel()) { + kvm_ipi_realize(dev, errp); + } +} + +static void loongarch_ipi_reset_hold(Object *obj, ResetType type) +{ + int i; + LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(obj); + LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(obj); + IPICore *core; + + if (lic->parent_phases.hold) { + lic->parent_phases.hold(obj, type); + } + + for (i = 0; i < lics->num_cpu; i++) { + core = lics->cpu + i; + /* IPI with targeted CPU available however not present */ + if (!core->cpu) { + continue; + } + + core->status = 0; + core->en = 0; + core->set = 0; + core->clear = 0; + memset(core->buf, 0, sizeof(core->buf)); + } + + if (kvm_irqchip_in_kernel()) { + kvm_ipi_put(obj, 0); + } } static void loongarch_ipi_cpu_plug(HotplugHandler *hotplug_dev, @@ -140,19 +175,42 @@ static void loongarch_ipi_cpu_unplug(HotplugHandler *hotplug_dev, core->cpu = NULL; } +static int loongarch_ipi_pre_save(void *opaque) +{ + if (kvm_irqchip_in_kernel()) { + return kvm_ipi_get(opaque); + } + + return 0; +} + +static int loongarch_ipi_post_load(void *opaque, int version_id) +{ + if (kvm_irqchip_in_kernel()) { + return kvm_ipi_put(opaque, version_id); + } + + return 0; +} + static void loongarch_ipi_class_init(ObjectClass *klass, const void *data) { LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); device_class_set_parent_realize(dc, loongarch_ipi_realize, &lic->parent_realize); + resettable_class_set_parent_phases(rc, NULL, loongarch_ipi_reset_hold, + NULL, &lic->parent_phases); licc->get_iocsr_as = get_iocsr_as; licc->cpu_by_arch_id = loongarch_cpu_by_arch_id; hc->plug = loongarch_ipi_cpu_plug; hc->unplug = loongarch_ipi_cpu_unplug; + licc->pre_save = loongarch_ipi_pre_save; + licc->post_load = loongarch_ipi_post_load; } static const TypeInfo loongarch_ipi_types[] = { diff --git a/hw/intc/loongarch_ipi_kvm.c b/hw/intc/loongarch_ipi_kvm.c new file mode 100644 index 0000000..4cb3acc --- /dev/null +++ b/hw/intc/loongarch_ipi_kvm.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch IPI interrupt KVM support + * + * Copyright (C) 2025 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/intc/loongarch_ipi.h" +#include "system/kvm.h" +#include "target/loongarch/cpu.h" + +static void kvm_ipi_access_reg(int fd, uint64_t addr, uint32_t *val, bool write) +{ + kvm_device_access(fd, KVM_DEV_LOONGARCH_IPI_GRP_REGS, + addr, val, write, &error_abort); +} + +static void kvm_ipi_access_regs(void *opaque, bool write) +{ + LoongsonIPICommonState *ipi = (LoongsonIPICommonState *)opaque; + LoongarchIPIState *lis = LOONGARCH_IPI(opaque); + IPICore *core; + uint64_t attr; + int cpu, fd = lis->dev_fd; + + if (fd == 0) { + return; + } + + for (cpu = 0; cpu < ipi->num_cpu; cpu++) { + core = &ipi->cpu[cpu]; + attr = (cpu << 16) | CORE_STATUS_OFF; + kvm_ipi_access_reg(fd, attr, &core->status, write); + + attr = (cpu << 16) | CORE_EN_OFF; + kvm_ipi_access_reg(fd, attr, &core->en, write); + + attr = (cpu << 16) | CORE_SET_OFF; + kvm_ipi_access_reg(fd, attr, &core->set, write); + + attr = (cpu << 16) | CORE_CLEAR_OFF; + kvm_ipi_access_reg(fd, attr, &core->clear, write); + + attr = (cpu << 16) | CORE_BUF_20; + kvm_ipi_access_reg(fd, attr, &core->buf[0], write); + + attr = (cpu << 16) | CORE_BUF_28; + kvm_ipi_access_reg(fd, attr, &core->buf[2], write); + + attr = (cpu << 16) | CORE_BUF_30; + kvm_ipi_access_reg(fd, attr, &core->buf[4], write); + + attr = (cpu << 16) | CORE_BUF_38; + kvm_ipi_access_reg(fd, attr, &core->buf[6], write); + } +} + +int kvm_ipi_get(void *opaque) +{ + kvm_ipi_access_regs(opaque, false); + return 0; +} + +int kvm_ipi_put(void *opaque, int version_id) +{ + kvm_ipi_access_regs(opaque, true); + return 0; +} + +void kvm_ipi_realize(DeviceState *dev, Error **errp) +{ + LoongarchIPIState *lis = LOONGARCH_IPI(dev); + int ret; + + ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_IPI, false); + if (ret < 0) { + fprintf(stderr, "IPI KVM_CREATE_DEVICE failed: %s\n", + strerror(-ret)); + abort(); + } + + lis->dev_fd = ret; +} diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c index 06eb944..f6d1631 100644 --- a/hw/intc/loongarch_pch_msi.c +++ b/hw/intc/loongarch_pch_msi.c @@ -13,6 +13,7 @@ #include "hw/pci/msi.h" #include "hw/misc/unimp.h" #include "migration/vmstate.h" +#include "system/kvm.h" #include "trace.h" static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size) @@ -26,6 +27,15 @@ static void loongarch_msi_mem_write(void *opaque, hwaddr addr, LoongArchPCHMSI *s = (LoongArchPCHMSI *)opaque; int irq_num; + if (kvm_irqchip_in_kernel()) { + MSIMessage msg; + + msg.address = addr; + msg.data = val; + kvm_irqchip_send_msi(kvm_state, msg); + return; + } + /* * vector number is irq number from upper extioi intc * need subtract irq base to get msi vector offset diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c index 6c2b6de..c4b242d 100644 --- a/hw/intc/loongarch_pch_pic.c +++ b/hw/intc/loongarch_pch_pic.c @@ -7,8 +7,10 @@ #include "qemu/osdep.h" #include "qemu/bitops.h" +#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" @@ -47,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) { @@ -71,308 +78,196 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level) pch_pic_update_irq(s, mask, level); } -static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr, - unsigned size) +static uint64_t pch_pic_read(void *opaque, hwaddr addr, uint64_t field_mask) { LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t val = 0; - uint32_t offset = addr & 0xfff; + uint32_t offset; - switch (offset) { - case PCH_PIC_INT_ID_LO: - val = PCH_PIC_INT_ID_VAL; + offset = addr & 7; + addr -= offset; + switch (addr) { + case PCH_PIC_INT_ID: + val = cpu_to_le64(s->id.data); break; - case PCH_PIC_INT_ID_HI: - /* - * With 7A1000 manual - * bit 0-15 pch irqchip version - * bit 16-31 irq number supported with pch irqchip - */ - val = deposit32(PCH_PIC_INT_ID_VER, 16, 16, s->irq_num - 1); + case PCH_PIC_INT_MASK: + val = s->int_mask; break; - case PCH_PIC_INT_MASK_LO: - val = (uint32_t)s->int_mask; + case PCH_PIC_INT_EDGE: + val = s->intedge; break; - case PCH_PIC_INT_MASK_HI: - val = s->int_mask >> 32; + case PCH_PIC_HTMSI_EN: + val = s->htmsi_en; break; - case PCH_PIC_INT_EDGE_LO: - val = (uint32_t)s->intedge; + case PCH_PIC_AUTO_CTRL0: + case PCH_PIC_AUTO_CTRL1: + /* PCH PIC connect to EXTIOI always, discard auto_ctrl access */ break; - case PCH_PIC_INT_EDGE_HI: - val = s->intedge >> 32; + case PCH_PIC_INT_STATUS: + val = s->intisr & (~s->int_mask); break; - case PCH_PIC_HTMSI_EN_LO: - val = (uint32_t)s->htmsi_en; + case PCH_PIC_INT_POL: + val = s->int_polarity; break; - case PCH_PIC_HTMSI_EN_HI: - val = s->htmsi_en >> 32; + case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END: + val = *(uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC); break; - case PCH_PIC_AUTO_CTRL0_LO: - case PCH_PIC_AUTO_CTRL0_HI: - case PCH_PIC_AUTO_CTRL1_LO: - case PCH_PIC_AUTO_CTRL1_HI: + case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END: + val = *(uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY); break; default: + qemu_log_mask(LOG_GUEST_ERROR, + "pch_pic_read: Bad address 0x%"PRIx64"\n", addr); break; } - trace_loongarch_pch_pic_low_readw(size, addr, val); - return val; + return (val >> (offset * 8)) & field_mask; } -static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi) -{ - uint64_t mask = 0xffffffff00000000; - uint64_t data = target; - - return hi ? (value & ~mask) | (data << 32) : (value & mask) | data; -} - -static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr, - uint64_t value, unsigned size) +static void pch_pic_write(void *opaque, hwaddr addr, uint64_t value, + uint64_t field_mask) { LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); - uint32_t offset, old_valid, data = (uint32_t)value; - uint64_t old, int_mask; - offset = addr & 0xfff; - - trace_loongarch_pch_pic_low_writew(size, addr, data); - - switch (offset) { - case PCH_PIC_INT_MASK_LO: - old = s->int_mask; - s->int_mask = get_writew_val(old, data, 0); - old_valid = (uint32_t)old; - if (old_valid & ~data) { - pch_pic_update_irq(s, (old_valid & ~data), 1); - } - if (~old_valid & data) { - pch_pic_update_irq(s, (~old_valid & data), 0); - } - break; - case PCH_PIC_INT_MASK_HI: + uint32_t offset; + uint64_t old, mask, data, *ptemp; + + offset = addr & 7; + addr -= offset; + mask = field_mask << (offset * 8); + data = (value & field_mask) << (offset * 8); + switch (addr) { + case PCH_PIC_INT_MASK: old = s->int_mask; - s->int_mask = get_writew_val(old, data, 1); - old_valid = (uint32_t)(old >> 32); - int_mask = old_valid & ~data; - if (int_mask) { - pch_pic_update_irq(s, int_mask << 32, 1); + s->int_mask = (old & ~mask) | data; + if (old & ~data) { + pch_pic_update_irq(s, old & ~data, 1); } - int_mask = ~old_valid & data; - if (int_mask) { - pch_pic_update_irq(s, int_mask << 32, 0); + + if (~old & data) { + pch_pic_update_irq(s, ~old & data, 0); } break; - case PCH_PIC_INT_EDGE_LO: - s->intedge = get_writew_val(s->intedge, data, 0); - break; - case PCH_PIC_INT_EDGE_HI: - s->intedge = get_writew_val(s->intedge, data, 1); + case PCH_PIC_INT_EDGE: + s->intedge = (s->intedge & ~mask) | data; break; - case PCH_PIC_INT_CLEAR_LO: + case PCH_PIC_INT_CLEAR: if (s->intedge & data) { - s->intirr &= (~data); + s->intirr &= ~data; pch_pic_update_irq(s, data, 0); - s->intisr &= (~data); + s->intisr &= ~data; } break; - case PCH_PIC_INT_CLEAR_HI: - value <<= 32; - if (s->intedge & value) { - s->intirr &= (~value); - pch_pic_update_irq(s, value, 0); - s->intisr &= (~value); - } + case PCH_PIC_HTMSI_EN: + s->htmsi_en = (s->htmsi_en & ~mask) | data; break; - case PCH_PIC_HTMSI_EN_LO: - s->htmsi_en = get_writew_val(s->htmsi_en, data, 0); + case PCH_PIC_AUTO_CTRL0: + case PCH_PIC_AUTO_CTRL1: + /* Discard auto_ctrl access */ break; - case PCH_PIC_HTMSI_EN_HI: - s->htmsi_en = get_writew_val(s->htmsi_en, data, 1); + case PCH_PIC_INT_POL: + s->int_polarity = (s->int_polarity & ~mask) | data; break; - case PCH_PIC_AUTO_CTRL0_LO: - case PCH_PIC_AUTO_CTRL0_HI: - case PCH_PIC_AUTO_CTRL1_LO: - case PCH_PIC_AUTO_CTRL1_HI: + case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END: + ptemp = (uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC); + *ptemp = (*ptemp & ~mask) | data; + break; + case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END: + ptemp = (uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY); + *ptemp = (*ptemp & ~mask) | data; break; default: + qemu_log_mask(LOG_GUEST_ERROR, + "pch_pic_write: Bad address 0x%"PRIx64"\n", addr); break; } } -static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr, - unsigned size) +static uint64_t loongarch_pch_pic_read(void *opaque, hwaddr addr, + unsigned size) { - LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); uint64_t val = 0; - uint32_t offset = addr & 0xfff; - switch (offset) { - case STATUS_LO_START: - val = (uint32_t)(s->intisr & (~s->int_mask)); + switch (size) { + case 1: + val = pch_pic_read(opaque, addr, UCHAR_MAX); break; - case STATUS_HI_START: - val = (s->intisr & (~s->int_mask)) >> 32; + case 2: + val = pch_pic_read(opaque, addr, USHRT_MAX); break; - case POL_LO_START: - val = (uint32_t)s->int_polarity; + case 4: + val = pch_pic_read(opaque, addr, UINT_MAX); break; - case POL_HI_START: - val = s->int_polarity >> 32; + case 8: + val = pch_pic_read(opaque, addr, UINT64_MAX); break; default: + qemu_log_mask(LOG_GUEST_ERROR, + "loongarch_pch_pic_read: Bad size %d\n", size); break; } - trace_loongarch_pch_pic_high_readw(size, addr, val); + trace_loongarch_pch_pic_read(size, addr, val); return val; } -static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr, - uint64_t value, unsigned size) +static void loongarch_pch_pic_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) { - LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); - uint32_t offset, data = (uint32_t)value; - offset = addr & 0xfff; - - trace_loongarch_pch_pic_high_writew(size, addr, data); + trace_loongarch_pch_pic_write(size, addr, value); - switch (offset) { - case STATUS_LO_START: - s->intisr = get_writew_val(s->intisr, data, 0); - break; - case STATUS_HI_START: - s->intisr = get_writew_val(s->intisr, data, 1); + switch (size) { + case 1: + pch_pic_write(opaque, addr, value, UCHAR_MAX); break; - case POL_LO_START: - s->int_polarity = get_writew_val(s->int_polarity, data, 0); + case 2: + pch_pic_write(opaque, addr, value, USHRT_MAX); break; - case POL_HI_START: - s->int_polarity = get_writew_val(s->int_polarity, data, 1); break; - default: - break; - } -} - -static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr, - unsigned size) -{ - LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); - uint64_t val = 0; - uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; - int64_t offset_tmp; - - switch (offset) { - case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END: - offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET; - if (offset_tmp >= 0 && offset_tmp < 64) { - val = s->htmsi_vector[offset_tmp]; - } - break; - case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END: - offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET; - if (offset_tmp >= 0 && offset_tmp < 64) { - val = s->route_entry[offset_tmp]; - } - break; - default: - break; - } - - trace_loongarch_pch_pic_readb(size, addr, val); - return val; -} - -static void loongarch_pch_pic_writeb(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque); - int32_t offset_tmp; - uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET; - - trace_loongarch_pch_pic_writeb(size, addr, data); - - switch (offset) { - case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END: - offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET; - if (offset_tmp >= 0 && offset_tmp < 64) { - s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff); - } + case 4: + pch_pic_write(opaque, addr, value, UINT_MAX); break; - case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END: - offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET; - if (offset_tmp >= 0 && offset_tmp < 64) { - s->route_entry[offset_tmp] = (uint8_t)(data & 0xff); - } + case 8: + pch_pic_write(opaque, addr, value, UINT64_MAX); break; default: + qemu_log_mask(LOG_GUEST_ERROR, + "loongarch_pch_pic_write: Bad size %d\n", size); break; } } -static const MemoryRegionOps loongarch_pch_pic_reg32_low_ops = { - .read = loongarch_pch_pic_low_readw, - .write = loongarch_pch_pic_low_writew, - .valid = { - .min_access_size = 4, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static const MemoryRegionOps loongarch_pch_pic_reg32_high_ops = { - .read = loongarch_pch_pic_high_readw, - .write = loongarch_pch_pic_high_writew, - .valid = { - .min_access_size = 4, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static const MemoryRegionOps loongarch_pch_pic_reg8_ops = { - .read = loongarch_pch_pic_readb, - .write = loongarch_pch_pic_writeb, +static const MemoryRegionOps loongarch_pch_pic_ops = { + .read = loongarch_pch_pic_read, + .write = loongarch_pch_pic_write, .valid = { .min_access_size = 1, - .max_access_size = 1, + .max_access_size = 8, + /* + * PCH PIC device would not work correctly if the guest was doing + * unaligned access. This might not be a limitation on the real + * device but in practice there is no reason for a guest to access + * this device unaligned. + */ + .unaligned = false, }, .impl = { .min_access_size = 1, - .max_access_size = 1, + .max_access_size = 8, }, .endianness = DEVICE_LITTLE_ENDIAN, }; -static void loongarch_pch_pic_reset(DeviceState *d) +static void loongarch_pic_reset_hold(Object *obj, ResetType type) { - LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(d); - int i; - - s->int_mask = -1; - s->htmsi_en = 0x0; - s->intedge = 0x0; - s->intclr = 0x0; - s->auto_crtl0 = 0x0; - s->auto_crtl1 = 0x0; - for (i = 0; i < 64; i++) { - s->route_entry[i] = 0x1; - s->htmsi_vector[i] = 0x0; + LoongarchPICClass *lpc = LOONGARCH_PIC_GET_CLASS(obj); + + if (lpc->parent_phases.hold) { + lpc->parent_phases.hold(obj, type); + } + + if (kvm_irqchip_in_kernel()) { + kvm_pic_put(obj, 0); } - s->intirr = 0x0; - s->intisr = 0x0; - s->last_intirr = 0x0; - s->int_polarity = 0x0; } static void loongarch_pic_realize(DeviceState *dev, Error **errp) @@ -390,28 +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->iomem32_low, OBJECT(dev), - &loongarch_pch_pic_reg32_low_ops, - s, PCH_PIC_NAME(.reg32_part1), 0x100); - memory_region_init_io(&s->iomem8, OBJECT(dev), &loongarch_pch_pic_reg8_ops, - s, PCH_PIC_NAME(.reg8), 0x2a0); - memory_region_init_io(&s->iomem32_high, OBJECT(dev), - &loongarch_pch_pic_reg32_high_ops, - s, PCH_PIC_NAME(.reg32_part2), 0xc60); - sysbus_init_mmio(sbd, &s->iomem32_low); - sysbus_init_mmio(sbd, &s->iomem8); - sysbus_init_mmio(sbd, &s->iomem32_high); + 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); - device_class_set_legacy_reset(dc, loongarch_pch_pic_reset); + 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[] = { diff --git a/hw/intc/loongarch_pic_common.c b/hw/intc/loongarch_pic_common.c index fdb250c..de17050 100644 --- a/hw/intc/loongarch_pic_common.c +++ b/hw/intc/loongarch_pic_common.c @@ -44,6 +44,40 @@ static void loongarch_pic_common_realize(DeviceState *dev, Error **errp) } } +static void loongarch_pic_common_reset_hold(Object *obj, ResetType type) +{ + LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(obj); + int i; + + /* + * With Loongson 7A1000 user manual + * Chapter 5.2 "Description of Interrupt-related Registers" + * + * Interrupt controller identification register 1 + * Bit 24-31 Interrupt Controller ID + * Interrupt controller identification register 2 + * Bit 0-7 Interrupt Controller version number + * Bit 16-23 The number of interrupt sources supported + */ + s->id.desc.id = PCH_PIC_INT_ID_VAL; + s->id.desc.version = PCH_PIC_INT_ID_VER; + s->id.desc.irq_num = s->irq_num - 1; + s->int_mask = UINT64_MAX; + s->htmsi_en = 0x0; + s->intedge = 0x0; + s->intclr = 0x0; + s->auto_crtl0 = 0x0; + s->auto_crtl1 = 0x0; + for (i = 0; i < 64; i++) { + s->route_entry[i] = 0x1; + s->htmsi_vector[i] = 0x0; + } + s->intirr = 0x0; + s->intisr = 0x0; + s->last_intirr = 0x0; + s->int_polarity = 0x0; +} + static const Property loongarch_pic_common_properties[] = { DEFINE_PROP_UINT32("pch_pic_irq_num", LoongArchPICCommonState, irq_num, 0), }; @@ -76,9 +110,13 @@ static void loongarch_pic_common_class_init(ObjectClass *klass, { DeviceClass *dc = DEVICE_CLASS(klass); LoongArchPICCommonClass *lpcc = LOONGARCH_PIC_COMMON_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_parent_realize(dc, loongarch_pic_common_realize, &lpcc->parent_realize); + resettable_class_set_parent_phases(rc, NULL, + loongarch_pic_common_reset_hold, + NULL, &lpcc->parent_phases); device_class_set_props(dc, loongarch_pic_common_properties); dc->vmsd = &vmstate_loongarch_pic_common; } diff --git a/hw/intc/loongarch_pic_kvm.c b/hw/intc/loongarch_pic_kvm.c new file mode 100644 index 0000000..dd504ec --- /dev/null +++ b/hw/intc/loongarch_pic_kvm.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * LoongArch kvm pch pic interrupt support + * + * Copyright (C) 2025 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/boards.h" +#include "hw/intc/loongarch_pch_pic.h" +#include "hw/loongarch/virt.h" +#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; + + if (fd == 0) { + return; + } + + 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); + uint64_t pch_pic_base = VIRT_PCH_REG_BASE; + int ret; + + ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_LOONGARCH_PCHPIC, false); + if (ret < 0) { + fprintf(stderr, "Create KVM_LOONGARCH_PCHPIC failed: %s\n", + strerror(-ret)); + abort(); + } + + lps->dev_fd = ret; + ret = kvm_device_access(lps->dev_fd, KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL, + KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT, + &pch_pic_base, true, NULL); + if (ret < 0) { + fprintf(stderr, "KVM_LOONGARCH_PCH_PIC_INIT failed: %s\n", + strerror(-ret)); + abort(); + } +} diff --git a/hw/intc/loongson_ipi_common.c b/hw/intc/loongson_ipi_common.c index f32661c..8cd78d4 100644 --- a/hw/intc/loongson_ipi_common.c +++ b/hw/intc/loongson_ipi_common.c @@ -11,6 +11,7 @@ #include "hw/irq.h" #include "qemu/log.h" #include "migration/vmstate.h" +#include "system/kvm.h" #include "trace.h" MemTxResult loongson_ipi_core_readl(void *opaque, hwaddr addr, uint64_t *data, @@ -255,6 +256,10 @@ static void loongson_ipi_common_realize(DeviceState *dev, Error **errp) LoongsonIPICommonState *s = LOONGSON_IPI_COMMON(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + if (kvm_irqchip_in_kernel()) { + return; + } + memory_region_init_io(&s->ipi_iocsr_mem, OBJECT(dev), &loongson_ipi_iocsr_ops, s, "loongson_ipi_iocsr", 0x48); @@ -277,10 +282,38 @@ static void loongson_ipi_common_unrealize(DeviceState *dev) g_free(s->cpu); } +static int loongson_ipi_common_pre_save(void *opaque) +{ + IPICore *ipicore = (IPICore *)opaque; + LoongsonIPICommonState *s = ipicore->ipi; + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(s); + + if (licc->pre_save) { + return licc->pre_save(s); + } + + return 0; +} + +static int loongson_ipi_common_post_load(void *opaque, int version_id) +{ + IPICore *ipicore = (IPICore *)opaque; + LoongsonIPICommonState *s = ipicore->ipi; + LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_GET_CLASS(s); + + if (licc->post_load) { + return licc->post_load(s, version_id); + } + + return 0; +} + static const VMStateDescription vmstate_ipi_core = { .name = "ipi-single", .version_id = 2, .minimum_version_id = 2, + .pre_save = loongson_ipi_common_pre_save, + .post_load = loongson_ipi_common_post_load, .fields = (const VMStateField[]) { VMSTATE_UINT32(status, IPICore), VMSTATE_UINT32(en, IPICore), diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 602da30..3137521 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -71,6 +71,12 @@ specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c')) specific_ss.add(when: 'CONFIG_LOONGSON_IPI_COMMON', if_true: files('loongson_ipi_common.c')) specific_ss.add(when: 'CONFIG_LOONGSON_IPI', if_true: files('loongson_ipi.c')) specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c')) +specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_LOONGARCH_IPI'], + if_true: files('loongarch_ipi_kvm.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_KVM', 'CONFIG_LOONGARCH_PCH_PIC'], + if_true: files('loongarch_pic_kvm.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_KVM', 'CONFIG_LOONGARCH_EXTIOI'], + if_true: files('loongarch_extioi_kvm.c')) diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 9e8737b..c61158b 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -102,8 +102,8 @@ static inline void omap_inth_update(OMAPIntcState *s, int is_fiq) } } -#define INT_FALLING_EDGE 0 -#define INT_LOW_LEVEL 1 +#define INT_FALLING_EDGE 0 +#define INT_LOW_LEVEL 1 static void omap_set_intr(void *opaque, int irq, int req) { @@ -142,13 +142,13 @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr, offset &= 0xff; switch (offset) { - case 0x00: /* ITR */ + case 0x00: /* ITR */ return bank->irqs; - case 0x04: /* MIR */ + case 0x04: /* MIR */ return bank->mask; - case 0x10: /* SIR_IRQ_CODE */ + case 0x10: /* SIR_IRQ_CODE */ case 0x14: /* SIR_FIQ_CODE */ if (bank_no != 0) break; @@ -159,49 +159,49 @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr, bank->irqs &= ~(1 << i); return line_no; - case 0x18: /* CONTROL_REG */ + case 0x18: /* CONTROL_REG */ if (bank_no != 0) break; return 0; - case 0x1c: /* ILR0 */ - case 0x20: /* ILR1 */ - case 0x24: /* ILR2 */ - case 0x28: /* ILR3 */ - case 0x2c: /* ILR4 */ - case 0x30: /* ILR5 */ - case 0x34: /* ILR6 */ - case 0x38: /* ILR7 */ - case 0x3c: /* ILR8 */ - case 0x40: /* ILR9 */ - case 0x44: /* ILR10 */ - case 0x48: /* ILR11 */ - case 0x4c: /* ILR12 */ - case 0x50: /* ILR13 */ - case 0x54: /* ILR14 */ - case 0x58: /* ILR15 */ - case 0x5c: /* ILR16 */ - case 0x60: /* ILR17 */ - case 0x64: /* ILR18 */ - case 0x68: /* ILR19 */ - case 0x6c: /* ILR20 */ - case 0x70: /* ILR21 */ - case 0x74: /* ILR22 */ - case 0x78: /* ILR23 */ - case 0x7c: /* ILR24 */ - case 0x80: /* ILR25 */ - case 0x84: /* ILR26 */ - case 0x88: /* ILR27 */ - case 0x8c: /* ILR28 */ - case 0x90: /* ILR29 */ - case 0x94: /* ILR30 */ - case 0x98: /* ILR31 */ + case 0x1c: /* ILR0 */ + case 0x20: /* ILR1 */ + case 0x24: /* ILR2 */ + case 0x28: /* ILR3 */ + case 0x2c: /* ILR4 */ + case 0x30: /* ILR5 */ + case 0x34: /* ILR6 */ + case 0x38: /* ILR7 */ + case 0x3c: /* ILR8 */ + case 0x40: /* ILR9 */ + case 0x44: /* ILR10 */ + case 0x48: /* ILR11 */ + case 0x4c: /* ILR12 */ + case 0x50: /* ILR13 */ + case 0x54: /* ILR14 */ + case 0x58: /* ILR15 */ + case 0x5c: /* ILR16 */ + case 0x60: /* ILR17 */ + case 0x64: /* ILR18 */ + case 0x68: /* ILR19 */ + case 0x6c: /* ILR20 */ + case 0x70: /* ILR21 */ + case 0x74: /* ILR22 */ + case 0x78: /* ILR23 */ + case 0x7c: /* ILR24 */ + case 0x80: /* ILR25 */ + case 0x84: /* ILR26 */ + case 0x88: /* ILR27 */ + case 0x8c: /* ILR28 */ + case 0x90: /* ILR29 */ + case 0x94: /* ILR30 */ + case 0x98: /* ILR31 */ i = (offset - 0x1c) >> 2; return (bank->priority[i] << 2) | (((bank->sens_edge >> i) & 1) << 1) | ((bank->fiq >> i) & 1); - case 0x9c: /* ISR */ + case 0x9c: /* ISR */ return 0x00000000; } @@ -219,24 +219,24 @@ static void omap_inth_write(void *opaque, hwaddr addr, offset &= 0xff; switch (offset) { - case 0x00: /* ITR */ + case 0x00: /* ITR */ /* Important: ignore the clearing if the IRQ is level-triggered and the input bit is 1 */ bank->irqs &= value | (bank->inputs & bank->sens_edge); return; - case 0x04: /* MIR */ + case 0x04: /* MIR */ bank->mask = value; omap_inth_update(s, 0); omap_inth_update(s, 1); return; - case 0x10: /* SIR_IRQ_CODE */ - case 0x14: /* SIR_FIQ_CODE */ + case 0x10: /* SIR_IRQ_CODE */ + case 0x14: /* SIR_FIQ_CODE */ OMAP_RO_REG(addr); break; - case 0x18: /* CONTROL_REG */ + case 0x18: /* CONTROL_REG */ if (bank_no != 0) break; if (value & 2) { @@ -251,38 +251,38 @@ static void omap_inth_write(void *opaque, hwaddr addr, } return; - case 0x1c: /* ILR0 */ - case 0x20: /* ILR1 */ - case 0x24: /* ILR2 */ - case 0x28: /* ILR3 */ - case 0x2c: /* ILR4 */ - case 0x30: /* ILR5 */ - case 0x34: /* ILR6 */ - case 0x38: /* ILR7 */ - case 0x3c: /* ILR8 */ - case 0x40: /* ILR9 */ - case 0x44: /* ILR10 */ - case 0x48: /* ILR11 */ - case 0x4c: /* ILR12 */ - case 0x50: /* ILR13 */ - case 0x54: /* ILR14 */ - case 0x58: /* ILR15 */ - case 0x5c: /* ILR16 */ - case 0x60: /* ILR17 */ - case 0x64: /* ILR18 */ - case 0x68: /* ILR19 */ - case 0x6c: /* ILR20 */ - case 0x70: /* ILR21 */ - case 0x74: /* ILR22 */ - case 0x78: /* ILR23 */ - case 0x7c: /* ILR24 */ - case 0x80: /* ILR25 */ - case 0x84: /* ILR26 */ - case 0x88: /* ILR27 */ - case 0x8c: /* ILR28 */ - case 0x90: /* ILR29 */ - case 0x94: /* ILR30 */ - case 0x98: /* ILR31 */ + case 0x1c: /* ILR0 */ + case 0x20: /* ILR1 */ + case 0x24: /* ILR2 */ + case 0x28: /* ILR3 */ + case 0x2c: /* ILR4 */ + case 0x30: /* ILR5 */ + case 0x34: /* ILR6 */ + case 0x38: /* ILR7 */ + case 0x3c: /* ILR8 */ + case 0x40: /* ILR9 */ + case 0x44: /* ILR10 */ + case 0x48: /* ILR11 */ + case 0x4c: /* ILR12 */ + case 0x50: /* ILR13 */ + case 0x54: /* ILR14 */ + case 0x58: /* ILR15 */ + case 0x5c: /* ILR16 */ + case 0x60: /* ILR17 */ + case 0x64: /* ILR18 */ + case 0x68: /* ILR19 */ + case 0x6c: /* ILR20 */ + case 0x70: /* ILR21 */ + case 0x74: /* ILR22 */ + case 0x78: /* ILR23 */ + case 0x7c: /* ILR24 */ + case 0x80: /* ILR25 */ + case 0x84: /* ILR26 */ + case 0x88: /* ILR27 */ + case 0x8c: /* ILR28 */ + case 0x90: /* ILR29 */ + case 0x94: /* ILR30 */ + case 0x98: /* ILR31 */ i = (offset - 0x1c) >> 2; bank->priority[i] = (value >> 2) & 0x1f; bank->sens_edge &= ~(1 << i); @@ -291,7 +291,7 @@ static void omap_inth_write(void *opaque, hwaddr addr, bank->fiq |= (value & 1) << i; return; - case 0x9c: /* ISR */ + case 0x9c: /* ISR */ for (i = 0; i < 32; i ++) if (value & (1 << i)) { omap_set_intr(s, 32 * bank_no + i, 1); diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 0ba9a02..334aa6a 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -314,12 +314,8 @@ loongson_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x loongson_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64 # loongarch_pch_pic.c loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d" -loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -loongarch_pch_pic_low_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -loongarch_pch_pic_high_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -loongarch_pch_pic_high_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -loongarch_pch_pic_readb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 -loongarch_pch_pic_writeb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 +loongarch_pch_pic_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64 # loongarch_pch_msi.c loongarch_msi_set_irq(int irq_num) "set msi irq %d" |