Message ID | 20220128034412.1262452-17-yangxiaojuan@loongson.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add LoongArch softmmu support | expand |
On 28/01/2022 03:43, Xiaojuan Yang wrote: > Loongson-3A5000 support 14 interrupts from 64 - 77(Timer->75 IPI->76) > Loongson-3A5000 and ls7a form a legacy model and extended model irq > hierarchy.Tcg mode emulate a simplified extended model which > has no Legacy I/O Interrupt Controller(LIOINTC) and LPC. > e.g: > > | +-----+ +---------+ +-------+ | > | | IPI |--> | CPUINTC | <-- | Timer | | > | +-----+ +---------+ +-------+ | > | ^ | > | | | > | +---------+ > | | EIOINTC | > | +---------+ > | ^ ^ | > | | | | > | +---------+ +---------+ | > | | PCH-PIC | | PCH-MSI | | > | +---------+ +---------+ | > | ^ ^ ^ | > | | | | | > | +---------+ +---------+ +---------+ | > | | UARTs | | Devices | | Devices | | > | +---------+ +---------+ +---------+ | > | ^ | > > The following series patch will realize the interrupt > controller in this model. > > More detailed info can be found at the kernel doc or manual > 1.https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/ > linux-loongson.git/tree/Documentation/loongarch?h=loongarch-next > 2.https://github.com/loongson/LoongArch-Documentation > > Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> > Signed-off-by: Song Gao <gaosong@loongson.cn> > --- > hw/loongarch/loongson3.c | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c > index 83c464899b..e79d86928d 100644 > --- a/hw/loongarch/loongson3.c > +++ b/hw/loongarch/loongson3.c > @@ -64,6 +64,29 @@ static const MemoryRegionOps loongarch_qemu_ops = { > }, > }; > > +static void loongarch_cpu_set_irq(void *opaque, int irq, int level) > +{ > + LoongArchCPU *cpu = opaque; > + CPULoongArchState *env = &cpu->env; > + CPUState *cs = CPU(cpu); > + > + if (irq < 0 || irq > N_IRQS) { > + return; > + } > + > + if (level) { > + env->CSR_ESTAT |= 1 << irq; > + } else { > + env->CSR_ESTAT &= ~(1 << irq); > + } > + > + if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) { > + cpu_interrupt(cs, CPU_INTERRUPT_HARD); > + } else { > + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); > + } > +} > + > static void loongarch_init(MachineState *machine) > { > const char *cpu_model = machine->cpu_type; > @@ -88,6 +111,9 @@ static void loongarch_init(MachineState *machine) > /* Init CPUs */ > for (i = 0; i < machine->smp.cpus; i++) { > la_cpu = LOONGARCH_CPU(cpu_create(machine->cpu_type)); > + timer_init_ns(&la_cpu->timer, QEMU_CLOCK_VIRTUAL, > + &loongarch_constant_timer_cb, la_cpu); > + qdev_init_gpio_in(DEVICE(la_cpu), loongarch_cpu_set_irq, N_IRQS); > > timer_init_ns(&la_cpu->timer, QEMU_CLOCK_VIRTUAL, > &loongarch_constant_timer_cb, la_cpu); This should also get moved into the new loongarch_cpu_init() function previously discussed. ATB, Mark.
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c index 83c464899b..e79d86928d 100644 --- a/hw/loongarch/loongson3.c +++ b/hw/loongarch/loongson3.c @@ -64,6 +64,29 @@ static const MemoryRegionOps loongarch_qemu_ops = { }, }; +static void loongarch_cpu_set_irq(void *opaque, int irq, int level) +{ + LoongArchCPU *cpu = opaque; + CPULoongArchState *env = &cpu->env; + CPUState *cs = CPU(cpu); + + if (irq < 0 || irq > N_IRQS) { + return; + } + + if (level) { + env->CSR_ESTAT |= 1 << irq; + } else { + env->CSR_ESTAT &= ~(1 << irq); + } + + if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + static void loongarch_init(MachineState *machine) { const char *cpu_model = machine->cpu_type; @@ -88,6 +111,9 @@ static void loongarch_init(MachineState *machine) /* Init CPUs */ for (i = 0; i < machine->smp.cpus; i++) { la_cpu = LOONGARCH_CPU(cpu_create(machine->cpu_type)); + timer_init_ns(&la_cpu->timer, QEMU_CLOCK_VIRTUAL, + &loongarch_constant_timer_cb, la_cpu); + qdev_init_gpio_in(DEVICE(la_cpu), loongarch_cpu_set_irq, N_IRQS); timer_init_ns(&la_cpu->timer, QEMU_CLOCK_VIRTUAL, &loongarch_constant_timer_cb, la_cpu);