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 cci::cci_param<bool> p_has_lpi; // Locality specific Peripheral Interrupts
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 , p_has_lpi("has_lpi", false, "Enable LPI")
84 , dist_iface("dist_iface", inst)
85 , redist_iface("redist_iface", p_redist_region.get_value().size(),
86 [&inst](const char* n, int i) { return new QemuTargetSocket<>(n, inst); })
87 , spi_in("spi_in", p_num_spi)
88 , ppi_in("ppi_in_cpu", p_num_cpu,
89 [](const char* n, size_t i) { return new sc_core::sc_vector<QemuTargetSignalSocket>(n, NUM_PPI); })
90 , irq_out("irq_out", p_num_cpu)
91 , fiq_out("fiq_out", p_num_cpu)
92 , virq_out("virq_out", p_num_cpu)
93 , vfiq_out("vfiq_out", p_num_cpu)
94 {
95 }
96
97 void before_end_of_elaboration()
98 {
99 QemuDevice::before_end_of_elaboration();
100 int i;
101
102 m_dev.set_prop_int("num-cpu", p_num_cpu);
103 m_dev.set_prop_int("num-irq", p_num_spi + NUM_PPI);
104 m_dev.set_prop_int("revision", p_revision);
105
106 bool has_security_extensions = m_inst.is_kvm_enabled() ? false : p_has_security_extensions.get_value();
107 bool has_lpi = m_inst.is_kvm_enabled() ? false : p_has_lpi.get_value();
108 m_dev.set_prop_bool("has-security-extensions", has_security_extensions);
109 m_dev.set_prop_bool("has-lpi", has_lpi);
110 if (has_lpi) {
111 m_dev.set_prop_link("sysmem", *(this->get_qemu_inst().get().get_system_memory()));
112 }
113 m_dev.set_prop_uint_array("redist-region-count", p_redist_region.get_value());
114 }
115
116 void end_of_elaboration()
117 {
118 QemuDevice::set_sysbus_as_parent_bus();
119 QemuDevice::end_of_elaboration();
120
121 qemu::SysBusDevice sbd(m_dev);
122 int cpu, i;
123
124 dist_iface.init(sbd, 0);
125
126 for (i = 0; i < p_redist_region.get_value().size(); i++) {
127 redist_iface[i].init(sbd, 1 + i);
128 }
129
130 /* SPIs in */
131 for (i = 0; i < p_num_spi; i++) {
132 spi_in[i].init(m_dev, i);
133 }
134
135 /* PPIs in */
136 for (cpu = 0; cpu < p_num_cpu; cpu++) {
137 for (i = 0; i < NUM_PPI; i++) {
138 int ppi_idx = p_num_spi + cpu * NUM_PPI + i;
139 ppi_in[cpu][i].init(m_dev, ppi_idx);
140 }
141 }
142
143 /* Output lines */
144 for (cpu = 0; cpu < p_num_cpu; cpu++) {
145 irq_out[cpu].init_sbd(sbd, p_num_cpu * 0 + cpu);
146 fiq_out[cpu].init_sbd(sbd, p_num_cpu * 1 + cpu);
147 virq_out[cpu].init_sbd(sbd, p_num_cpu * 2 + cpu);
148 vfiq_out[cpu].init_sbd(sbd, p_num_cpu * 3 + cpu);
149 }
150
151 if (m_inst.is_kvm_enabled()) {
154 sc_core::sc_object* init_obj = gs::find_sc_obj(nullptr, "platform.global_peripheral_initiator_arm_0");
155 auto init = dynamic_cast<global_peripheral_initiator*>(init_obj);
156 assert(init && "Failed to find global peripheral initiator");
157
158 m_inst.get().lock_iothread();
160 addr = gs::cci_get<uint64_t>(cci::cci_get_broker(), std::string(dist_iface.name()) + ".address");
161 init->m_initiator.qemu_io_read(addr, &val, sizeof(val), attrs);
162 for (i = 0; i < p_redist_region.get_value().size(); i++) {
163 addr = gs::cci_get<uint64_t>(cci::cci_get_broker(), std::string(redist_iface[i].name()) + ".address");
164 init->m_initiator.qemu_io_read(addr, &val, sizeof(val), attrs);
165 }
166 m_inst.get().unlock_iothread();
167 }
168 }
169};
170
171extern "C" void module_register();
172#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:463
Definition target.h:160
Definition arm_gicv3.h:28
Definition global_peripheral_initiator.h:18
Definition libqemu-cxx.h:627
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:318