quic/qbox
Loading...
Searching...
No Matches
arm_gicv3.h
1/*
2 * This file is part of libqbox
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * Author: GreenSocs 2020
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9#ifndef _LIBQBOX_COMPONENTS_IRQ_CTRL_ARM_GICV3_H
10#define _LIBQBOX_COMPONENTS_IRQ_CTRL_ARM_GICV3_H
11
12#include <sstream>
13
14#include <systemc>
15#include <cci_configuration>
16
17#include <global_peripheral_initiator.h>
18#include <libqemu-cxx/libqemu-cxx.h>
19
20#include <device.h>
21#include <ports/target.h>
22#include <ports/qemu-initiator-signal-socket.h>
23#include <ports/qemu-target-signal-socket.h>
24#include <qemu-instance.h>
25#include <module_factory_registery.h>
26
27class arm_gicv3 : public QemuDevice
28{
29public:
30 static const uint32_t NUM_PPI = 32;
31
32protected:
33 cci::cci_param<unsigned int> p_num_cpu;
34 cci::cci_param<unsigned int> p_num_spi;
35 cci::cci_param<unsigned int> p_revision;
36 cci::cci_param<std::vector<unsigned int> > p_redist_region;
37 cci::cci_param<bool> p_has_security_extensions;
38
39public:
40 QemuTargetSocket<> dist_iface;
41 sc_core::sc_vector<QemuTargetSocket<> > redist_iface;
42
43 /* Shared peripheral interrupts: sized with the p_num_spi parameter */
44 sc_core::sc_vector<QemuTargetSignalSocket> spi_in;
45
46 /*
47 * Private peripheral interrupts: 32 per CPUs, the outer vector is sized with the
48 * number of CPUs.
49 */
50 sc_core::sc_vector<sc_core::sc_vector<QemuTargetSignalSocket> > ppi_in;
51
52 /* Output interrupt lines. Vector are sized with the number of CPUs */
53 sc_core::sc_vector<QemuInitiatorSignalSocket> irq_out;
54 sc_core::sc_vector<QemuInitiatorSignalSocket> fiq_out;
55 sc_core::sc_vector<QemuInitiatorSignalSocket> virq_out;
56 sc_core::sc_vector<QemuInitiatorSignalSocket> vfiq_out;
57 arm_gicv3(const sc_core::sc_module_name& name, sc_core::sc_object* o)
58 : arm_gicv3(name, *(dynamic_cast<QemuInstance*>(o)))
59 {
60 }
61
62 static const char* get_gicv3_type(QemuInstance& inst)
63 {
64 if (inst.is_kvm_enabled()) {
65 return "kvm-arm-gicv3";
66 } else {
67 return "arm-gicv3";
68 }
69 }
70
71 arm_gicv3(const sc_core::sc_module_name& name, QemuInstance& inst, unsigned num_cpus = 0)
72 : QemuDevice(name, inst, get_gicv3_type(inst))
73 , p_num_cpu("num_cpus", num_cpus, "Number of CPU interfaces")
74 , p_num_spi("num_spi", 0, "Number of shared peripheral interrupts")
75 , p_revision("revision", 3, "Revision of the GIC (3 -> v3, 4 -> v4)")
76 // , p_redist_region("redist_region", std::vector<unsigned int>({}),
77 // "Redistributor regions configuration")
78 , p_redist_region("redist_region",
79 std::vector<unsigned int>(gs::cci_get_vector<unsigned int>(
80 cci::cci_get_broker(), std::string(sc_module::name()) + ".redist_region")),
81 "Redistributor regions configuration")
82 , p_has_security_extensions("has_security_extensions", false, "Enable security extensions")
83 , dist_iface("dist_iface", inst)
84 , redist_iface("redist_iface", p_redist_region.get_value().size(),
85 [&inst](const char* n, int i) { return new QemuTargetSocket<>(n, inst); })
86 , spi_in("spi_in", p_num_spi)
87 , ppi_in("ppi_in_cpu", p_num_cpu,
88 [](const char* n, size_t i) { return new sc_core::sc_vector<QemuTargetSignalSocket>(n, NUM_PPI); })
89 , irq_out("irq_out", p_num_cpu)
90 , fiq_out("fiq_out", p_num_cpu)
91 , virq_out("virq_out", p_num_cpu)
92 , vfiq_out("vfiq_out", p_num_cpu)
93 {
94 }
95
96 void before_end_of_elaboration()
97 {
98 QemuDevice::before_end_of_elaboration();
99 int i;
100
101 m_dev.set_prop_int("num-cpu", p_num_cpu);
102 m_dev.set_prop_int("num-irq", p_num_spi + NUM_PPI);
103 m_dev.set_prop_int("revision", p_revision);
104
105 bool has_security_extensions = m_inst.is_kvm_enabled() ? false : p_has_security_extensions.get_value();
106 m_dev.set_prop_bool("has-security-extensions", has_security_extensions);
107 m_dev.set_prop_uint_array("redist-region-count", p_redist_region.get_value());
108 }
109
110 void end_of_elaboration()
111 {
112 QemuDevice::set_sysbus_as_parent_bus();
113 QemuDevice::end_of_elaboration();
114
115 qemu::SysBusDevice sbd(m_dev);
116 int cpu, i;
117
118 dist_iface.init(sbd, 0);
119
120 for (i = 0; i < p_redist_region.get_value().size(); i++) {
121 redist_iface[i].init(sbd, 1 + i);
122 }
123
124 /* SPIs in */
125 for (i = 0; i < p_num_spi; i++) {
126 spi_in[i].init(m_dev, i);
127 }
128
129 /* PPIs in */
130 for (cpu = 0; cpu < p_num_cpu; cpu++) {
131 for (i = 0; i < NUM_PPI; i++) {
132 int ppi_idx = p_num_spi + cpu * NUM_PPI + i;
133 ppi_in[cpu][i].init(m_dev, ppi_idx);
134 }
135 }
136
137 /* Output lines */
138 for (cpu = 0; cpu < p_num_cpu; cpu++) {
139 irq_out[cpu].init_sbd(sbd, p_num_cpu * 0 + cpu);
140 fiq_out[cpu].init_sbd(sbd, p_num_cpu * 1 + cpu);
141 virq_out[cpu].init_sbd(sbd, p_num_cpu * 2 + cpu);
142 vfiq_out[cpu].init_sbd(sbd, p_num_cpu * 3 + cpu);
143 }
144
145 if (m_inst.is_kvm_enabled()) {
148 sc_core::sc_object* init_obj = gs::find_sc_obj(nullptr, "platform.global_peripheral_initiator_arm_0");
149 auto init = dynamic_cast<global_peripheral_initiator*>(init_obj);
150 assert(init && "Failed to find global peripheral initiator");
151
152 m_inst.get().lock_iothread();
154 addr = gs::cci_get<uint64_t>(cci::cci_get_broker(), std::string(dist_iface.name()) + ".address");
155 init->m_initiator.qemu_io_read(addr, &val, sizeof(val), attrs);
156 for (i = 0; i < p_redist_region.get_value().size(); i++) {
157 addr = gs::cci_get<uint64_t>(cci::cci_get_broker(), std::string(redist_iface[i].name()) + ".address");
158 init->m_initiator.qemu_io_read(addr, &val, sizeof(val), attrs);
159 }
160 m_inst.get().unlock_iothread();
161 }
162 }
163};
164
165extern "C" void module_register();
166#endif
QEMU device abstraction as a SystemC module.
Definition device.h:37
This class encapsulates a libqemu-cxx qemu::LibQemu instance. It handles QEMU parameters and instance...
Definition qemu-instance.h:89
qemu::LibQemu & get()
Returns the underlying qemu::LibQemu instance.
Definition qemu-instance.h:448
Definition target.h:160
Definition arm_gicv3.h:28
Definition global_peripheral_initiator.h:18
Definition libqemu-cxx.h:638
sc_core::sc_object * find_sc_obj(sc_core::sc_object *m, std::string name, bool test=false)
Helper function to find a sc_object by fully qualified name throws SC_ERROR if nothing found.
Definition cciutils.cc:18
Definition libqemu-cxx.h:325