Message ID | 1636594528-8175-18-git-send-email-yangxiaojuan@loongson.cn (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add Loongarch softmmu support. | expand |
On 11/11/2021 01:35, 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/loongarch_int.c | 59 ++++++++++++++++++++++++++++++++ > hw/loongarch/ls3a5000_virt.c | 2 ++ > hw/loongarch/meson.build | 1 + > include/hw/loongarch/loongarch.h | 2 ++ > 4 files changed, 64 insertions(+) > create mode 100644 hw/loongarch/loongarch_int.c > > diff --git a/hw/loongarch/loongarch_int.c b/hw/loongarch/loongarch_int.c > new file mode 100644 > index 0000000000..2502d056ac > --- /dev/null > +++ b/hw/loongarch/loongarch_int.c > @@ -0,0 +1,59 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * QEMU LOONGARCH interrupt support > + * > + * Copyright (C) 2021 Loongson Technology Corporation Limited > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/main-loop.h" > +#include "hw/irq.h" > +#include "hw/loongarch/loongarch.h" > +#include "cpu.h" > + > +static void cpu_loongarch_irq_request(void *opaque, int irq, int level) > +{ > + LoongArchCPU *cpu = opaque; > + CPULoongArchState *env = &cpu->env; > + CPUState *cs = CPU(cpu); > + bool locked = false; > + > + if (irq < 0 || irq > N_IRQS) { > + return; > + } > + > + /* Make sure locking works even if BQL is already held by the caller */ > + if (!qemu_mutex_iothread_locked()) { > + locked = true; > + qemu_mutex_lock_iothread(); > + } > + > + 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); > + } > + > + if (locked) { > + qemu_mutex_unlock_iothread(); > + } > +} > + > +void cpu_loongarch_init_irq(LoongArchCPU *cpu) > +{ > + CPULoongArchState *env = &cpu->env; > + qemu_irq *qi; > + int i; > + > + qi = qemu_allocate_irqs(cpu_loongarch_irq_request, cpu, N_IRQS); > + for (i = 0; i < N_IRQS; i++) { > + env->irq[i] = qi[i]; > + } > + g_free(qi); > +} TYPE_CPU is a child of TYPE_DEVICE so rather than use qemu_allocate_irqs() here you should declare these as qdev gpios in the LoongArchCPU device and wire them up using qdev_connect_gpio_out(). I suspect once you've done this then cpu_loongarch_init_irq() will no longer be required. > diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c > index 7c88d64795..37d6b1ec88 100644 > --- a/hw/loongarch/ls3a5000_virt.c > +++ b/hw/loongarch/ls3a5000_virt.c > @@ -150,6 +150,8 @@ static void ls3a5000_virt_init(MachineState *machine) > env = &cpu->env; > cpu_states[i] = env; > > + /* Init CPU internal devices */ > + cpu_loongarch_init_irq(cpu); > cpu_loongarch_clock_init(cpu); > qemu_register_reset(main_cpu_reset, cpu); > } > diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build > index 1e743cadb8..a972210680 100644 > --- a/hw/loongarch/meson.build > +++ b/hw/loongarch/meson.build > @@ -1,4 +1,5 @@ > loongarch_ss = ss.source_set() > +loongarch_ss.add(files('loongarch_int.c')) > loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c')) > > hw_arch += {'loongarch': loongarch_ss} > diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h > index edab069f76..8538697e5f 100644 > --- a/include/hw/loongarch/loongarch.h > +++ b/include/hw/loongarch/loongarch.h > @@ -43,4 +43,6 @@ typedef struct LoongArchMachineState { > #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") > DECLARE_INSTANCE_CHECKER(LoongArchMachineState, LOONGARCH_MACHINE, > TYPE_LOONGARCH_MACHINE) > + > +void cpu_loongarch_init_irq(LoongArchCPU *cpu); > #endif ATB, Mark.
diff --git a/hw/loongarch/loongarch_int.c b/hw/loongarch/loongarch_int.c new file mode 100644 index 0000000000..2502d056ac --- /dev/null +++ b/hw/loongarch/loongarch_int.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QEMU LOONGARCH interrupt support + * + * Copyright (C) 2021 Loongson Technology Corporation Limited + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "hw/irq.h" +#include "hw/loongarch/loongarch.h" +#include "cpu.h" + +static void cpu_loongarch_irq_request(void *opaque, int irq, int level) +{ + LoongArchCPU *cpu = opaque; + CPULoongArchState *env = &cpu->env; + CPUState *cs = CPU(cpu); + bool locked = false; + + if (irq < 0 || irq > N_IRQS) { + return; + } + + /* Make sure locking works even if BQL is already held by the caller */ + if (!qemu_mutex_iothread_locked()) { + locked = true; + qemu_mutex_lock_iothread(); + } + + 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); + } + + if (locked) { + qemu_mutex_unlock_iothread(); + } +} + +void cpu_loongarch_init_irq(LoongArchCPU *cpu) +{ + CPULoongArchState *env = &cpu->env; + qemu_irq *qi; + int i; + + qi = qemu_allocate_irqs(cpu_loongarch_irq_request, cpu, N_IRQS); + for (i = 0; i < N_IRQS; i++) { + env->irq[i] = qi[i]; + } + g_free(qi); +} diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c index 7c88d64795..37d6b1ec88 100644 --- a/hw/loongarch/ls3a5000_virt.c +++ b/hw/loongarch/ls3a5000_virt.c @@ -150,6 +150,8 @@ static void ls3a5000_virt_init(MachineState *machine) env = &cpu->env; cpu_states[i] = env; + /* Init CPU internal devices */ + cpu_loongarch_init_irq(cpu); cpu_loongarch_clock_init(cpu); qemu_register_reset(main_cpu_reset, cpu); } diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build index 1e743cadb8..a972210680 100644 --- a/hw/loongarch/meson.build +++ b/hw/loongarch/meson.build @@ -1,4 +1,5 @@ loongarch_ss = ss.source_set() +loongarch_ss.add(files('loongarch_int.c')) loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c')) hw_arch += {'loongarch': loongarch_ss} diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h index edab069f76..8538697e5f 100644 --- a/include/hw/loongarch/loongarch.h +++ b/include/hw/loongarch/loongarch.h @@ -43,4 +43,6 @@ typedef struct LoongArchMachineState { #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("loongson7a") DECLARE_INSTANCE_CHECKER(LoongArchMachineState, LOONGARCH_MACHINE, TYPE_LOONGARCH_MACHINE) + +void cpu_loongarch_init_irq(LoongArchCPU *cpu); #endif