8
9
#include "qemu/osdep.h"
10
#include "hw/intc/arm_gicv5_common.h"
11
+#include "hw/core/qdev-properties.h"
12
+#include "qapi/error.h"
13
+#include "trace.h"
14
15
OBJECT_DEFINE_ABSTRACT_TYPE(GICv5Common, gicv5_common, ARM_GICV5_COMMON, SYS_BUS_DEVICE)
16
17
+/* Any value > 2^24 is out of the valid range for this property */
18
+#define GICV5_SPI_IRS_RANGE_NOT_SET 0xffffffff
19
+
20
static bool bad_frame_accepts(void *opaque, hwaddr addr, unsigned size,
21
bool is_write, MemTxAttrs attrs)
22
{
64
{
65
}
66
67
+static void gicv5_common_realize(DeviceState *dev, Error **errp)
68
+{
69
+ GICv5Common *cs = ARM_GICV5_COMMON(dev);
70
+
71
+ if (cs->num_cpus == 0) {
72
+ error_setg(errp, "The cpus array property must have at least one CPU");
73
+ return;
74
+ }
75
+ if (cs->num_cpus >= (1 << 16)) {
76
+ /* We'll hit other QEMU limits long before this one :-) */
77
+ error_setg(errp, "Number of CPUs exceeds GICv5 architectural maximum");
78
+ return;
79
+ }
80
+ if (cs->num_cpus != cs->num_cpu_iaffids) {
81
+ error_setg(errp, "The cpu-iaffids array property must be the same size "
82
+ "as the cpus array property");
83
+ return;
84
+ }
85
+ if (cs->irsid >= (1 << 16)) {
86
+ error_setg(errp, "irsid (%u) is more than 2^16-1", cs->irsid);
87
+ return;
88
+ }
89
+ if (cs->spi_range > (1 << 24)) {
90
+ /*
91
+ * Note that IRS_IDR5.SPI_RANGE is a 25 bit field but the largest
92
+ * architecturally permitted value is 2^24 (not 2^25-1), hence
93
+ * use of > in the range check.
94
+ */
95
+ error_setg(errp, "spi-range (%u) is more than 2^24", cs->spi_range);
96
+ return;
97
+ }
98
+ if (cs->spi_irs_range == GICV5_SPI_IRS_RANGE_NOT_SET) {
99
+ /* spi-irs-range defaults to same as spi-range */
100
+ cs->spi_irs_range = cs->spi_range;
101
+ }
102
+ if (cs->spi_irs_range > (1 << 24)) {
103
+ /* Similarly IRS_IDR6.SPI_IRS_RANGE */
104
+ error_setg(errp, "spi-irs-range (%u) is more than 2^24",
105
+ cs->spi_irs_range);
106
+ return;
107
+ }
108
+ if (cs->spi_base >= (1 << 24)) {
109
+ /* IRS_IDR7.SPI_BASE is a 24-bit field, so range check is >= */
110
+ error_setg(errp, "spi-base (%u) is more than 2^24-1", cs->spi_base);
111
+ return;
112
+ }
113
+ /* range checks above mean we know this addition won't overflow */
114
+ if (cs->spi_base + cs->spi_irs_range > cs->spi_range) {
115
+ error_setg(errp, "spi-base (%u) + spi-irs-range (%u) is "
116
+ "more than spi-range (%u)",
117
+ cs->spi_base, cs->spi_irs_range, cs->spi_range);
118
+ return;
119
+ }
120
+
121
+ trace_gicv5_common_realize(cs->irsid, cs->num_cpus,
122
+ cs->spi_base, cs->spi_irs_range, cs->spi_range);
123
+}
124
+
125
+static const Property arm_gicv5_common_properties[] = {
126
+ DEFINE_PROP_LINK_ARRAY("cpus", GICv5Common, num_cpus,
127
+ cpus, TYPE_ARM_CPU, ARMCPU *),
128
+ DEFINE_PROP_ARRAY("cpu-iaffids", GICv5Common, num_cpu_iaffids,
129
+ cpu_iaffids, qdev_prop_uint32, uint32_t),
130
+ DEFINE_PROP_UINT32("irsid", GICv5Common, irsid, 0),
131
+ DEFINE_PROP_UINT32("spi-range", GICv5Common, spi_range, 0),
132
+ DEFINE_PROP_UINT32("spi-base", GICv5Common, spi_base, 0),
133
+ DEFINE_PROP_UINT32("spi-irs-range", GICv5Common, spi_irs_range,
134
+ GICV5_SPI_IRS_RANGE_NOT_SET),
135
+};
136
+
137
static void gicv5_common_class_init(ObjectClass *oc, const void *data)
138
{
139
ResettableClass *rc = RESETTABLE_CLASS(oc);
140
+ DeviceClass *dc = DEVICE_CLASS(oc);
141
142
rc->phases.hold = gicv5_common_reset_hold;
143
+
144
+ dc->realize = gicv5_common_realize;
145
+ device_class_set_props(dc, arm_gicv5_common_properties);
146
}