loongarch_ipi.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * LoongArch IPI interrupt support
  4. *
  5. * Copyright (C) 2024 Loongson Technology Corporation Limited
  6. */
  7. #include "qemu/osdep.h"
  8. #include "hw/boards.h"
  9. #include "qapi/error.h"
  10. #include "hw/intc/loongarch_ipi.h"
  11. #include "hw/qdev-properties.h"
  12. #include "target/loongarch/cpu.h"
  13. static AddressSpace *get_iocsr_as(CPUState *cpu)
  14. {
  15. return LOONGARCH_CPU(cpu)->env.address_space_iocsr;
  16. }
  17. static int loongarch_ipi_cmp(const void *a, const void *b)
  18. {
  19. IPICore *ipi_a = (IPICore *)a;
  20. IPICore *ipi_b = (IPICore *)b;
  21. return ipi_a->arch_id - ipi_b->arch_id;
  22. }
  23. static int loongarch_cpu_by_arch_id(LoongsonIPICommonState *lics,
  24. int64_t arch_id, int *index, CPUState **pcs)
  25. {
  26. IPICore ipi, *found;
  27. ipi.arch_id = arch_id;
  28. found = bsearch(&ipi, lics->cpu, lics->num_cpu, sizeof(IPICore),
  29. loongarch_ipi_cmp);
  30. if (found && found->cpu) {
  31. if (index) {
  32. *index = found - lics->cpu;
  33. }
  34. if (pcs) {
  35. *pcs = found->cpu;
  36. }
  37. return MEMTX_OK;
  38. }
  39. return MEMTX_ERROR;
  40. }
  41. static void loongarch_ipi_realize(DeviceState *dev, Error **errp)
  42. {
  43. LoongsonIPICommonState *lics = LOONGSON_IPI_COMMON(dev);
  44. LoongarchIPIClass *lic = LOONGARCH_IPI_GET_CLASS(dev);
  45. MachineState *machine = MACHINE(qdev_get_machine());
  46. MachineClass *mc = MACHINE_GET_CLASS(machine);
  47. const CPUArchIdList *id_list;
  48. Error *local_err = NULL;
  49. int i;
  50. lic->parent_realize(dev, &local_err);
  51. if (local_err) {
  52. error_propagate(errp, local_err);
  53. return;
  54. }
  55. assert(mc->possible_cpu_arch_ids);
  56. id_list = mc->possible_cpu_arch_ids(machine);
  57. lics->num_cpu = id_list->len;
  58. lics->cpu = g_new0(IPICore, lics->num_cpu);
  59. for (i = 0; i < lics->num_cpu; i++) {
  60. lics->cpu[i].arch_id = id_list->cpus[i].arch_id;
  61. lics->cpu[i].cpu = CPU(id_list->cpus[i].cpu);
  62. lics->cpu[i].ipi = lics;
  63. qdev_init_gpio_out(dev, &lics->cpu[i].irq, 1);
  64. }
  65. }
  66. static void loongarch_ipi_class_init(ObjectClass *klass, void *data)
  67. {
  68. LoongsonIPICommonClass *licc = LOONGSON_IPI_COMMON_CLASS(klass);
  69. LoongarchIPIClass *lic = LOONGARCH_IPI_CLASS(klass);
  70. DeviceClass *dc = DEVICE_CLASS(klass);
  71. device_class_set_parent_realize(dc, loongarch_ipi_realize,
  72. &lic->parent_realize);
  73. licc->get_iocsr_as = get_iocsr_as;
  74. licc->cpu_by_arch_id = loongarch_cpu_by_arch_id;
  75. }
  76. static const TypeInfo loongarch_ipi_types[] = {
  77. {
  78. .name = TYPE_LOONGARCH_IPI,
  79. .parent = TYPE_LOONGSON_IPI_COMMON,
  80. .instance_size = sizeof(LoongarchIPIState),
  81. .class_size = sizeof(LoongarchIPIClass),
  82. .class_init = loongarch_ipi_class_init,
  83. }
  84. };
  85. DEFINE_TYPES(loongarch_ipi_types)