2 * GICv2m extension for MSI/MSI-x support with a GICv2-based system
4 * Copyright (C) 2015 Linaro, All rights reserved.
6 * Author: Christoffer Dall <christoffer.dall@linaro.org>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 /* This file implements an emulated GICv2m widget as described in the ARM
23 * Server Base System Architecture (SBSA) specification Version 2.2
24 * (ARM-DEN-0029 v2.2) pages 35-39 without any optional implementation defined
25 * identification registers and with a single non-secure MSI register frame.
28 #include "qemu/osdep.h"
29 #include "qapi/error.h"
30 #include "hw/sysbus.h"
32 #include "hw/pci/msi.h"
33 #include "hw/qdev-properties.h"
34 #include "sysemu/kvm.h"
36 #include "qemu/module.h"
37 #include "qom/object.h"
39 #define TYPE_ARM_GICV2M "arm-gicv2m"
40 OBJECT_DECLARE_SIMPLE_TYPE(ARMGICv2mState
, ARM_GICV2M
)
42 #define GICV2M_NUM_SPI_MAX 128
44 #define V2M_MSI_TYPER 0x008
45 #define V2M_MSI_SETSPI_NS 0x040
46 #define V2M_MSI_IIDR 0xFCC
47 #define V2M_IIDR0 0xFD0
48 #define V2M_IIDR11 0xFFC
50 #define PRODUCT_ID_QEMU 0x51 /* ASCII code Q */
52 struct ARMGICv2mState
{
53 SysBusDevice parent_obj
;
56 qemu_irq spi
[GICV2M_NUM_SPI_MAX
];
62 static void gicv2m_set_irq(void *opaque
, int irq
)
64 ARMGICv2mState
*s
= (ARMGICv2mState
*)opaque
;
66 qemu_irq_pulse(s
->spi
[irq
]);
69 static uint64_t gicv2m_read(void *opaque
, hwaddr offset
,
72 ARMGICv2mState
*s
= (ARMGICv2mState
*)opaque
;
76 qemu_log_mask(LOG_GUEST_ERROR
, "gicv2m_read: bad size %u\n", size
);
82 val
= (s
->base_spi
+ 32) << 16;
86 /* We don't have any valid implementor so we leave that field as zero
87 * and we return 0 in the arch revision as per the spec.
89 return (PRODUCT_ID_QEMU
<< 20);
90 case V2M_IIDR0
... V2M_IIDR11
:
91 /* We do not implement any optional identification registers and the
92 * mandatory MSI_PIDR2 register reads as 0x0, so we capture all
93 * implementation defined registers here.
97 qemu_log_mask(LOG_GUEST_ERROR
,
98 "gicv2m_read: Bad offset %x\n", (int)offset
);
103 static void gicv2m_write(void *opaque
, hwaddr offset
,
104 uint64_t value
, unsigned size
)
106 ARMGICv2mState
*s
= (ARMGICv2mState
*)opaque
;
108 if (size
!= 2 && size
!= 4) {
109 qemu_log_mask(LOG_GUEST_ERROR
, "gicv2m_write: bad size %u\n", size
);
114 case V2M_MSI_SETSPI_NS
: {
117 spi
= (value
& 0x3ff) - (s
->base_spi
+ 32);
118 if (spi
>= 0 && spi
< s
->num_spi
) {
119 gicv2m_set_irq(s
, spi
);
124 qemu_log_mask(LOG_GUEST_ERROR
,
125 "gicv2m_write: Bad offset %x\n", (int)offset
);
129 static const MemoryRegionOps gicv2m_ops
= {
131 .write
= gicv2m_write
,
132 .endianness
= DEVICE_LITTLE_ENDIAN
,
135 static void gicv2m_realize(DeviceState
*dev
, Error
**errp
)
137 ARMGICv2mState
*s
= ARM_GICV2M(dev
);
140 if (s
->num_spi
> GICV2M_NUM_SPI_MAX
) {
142 "requested %u SPIs exceeds GICv2m frame maximum %d",
143 s
->num_spi
, GICV2M_NUM_SPI_MAX
);
147 if (s
->base_spi
+ 32 > 1020 - s
->num_spi
) {
149 "requested base SPI %u+%u exceeds max. number 1020",
150 s
->base_spi
+ 32, s
->num_spi
);
154 for (i
= 0; i
< s
->num_spi
; i
++) {
155 sysbus_init_irq(SYS_BUS_DEVICE(dev
), &s
->spi
[i
]);
158 msi_nonbroken
= true;
159 kvm_gsi_direct_mapping
= true;
160 kvm_msi_via_irqfd_allowed
= kvm_irqfds_enabled();
163 static void gicv2m_init(Object
*obj
)
165 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
166 ARMGICv2mState
*s
= ARM_GICV2M(obj
);
168 memory_region_init_io(&s
->iomem
, OBJECT(s
), &gicv2m_ops
, s
,
170 sysbus_init_mmio(sbd
, &s
->iomem
);
173 static Property gicv2m_properties
[] = {
174 DEFINE_PROP_UINT32("base-spi", ARMGICv2mState
, base_spi
, 0),
175 DEFINE_PROP_UINT32("num-spi", ARMGICv2mState
, num_spi
, 64),
176 DEFINE_PROP_END_OF_LIST(),
179 static void gicv2m_class_init(ObjectClass
*klass
, void *data
)
181 DeviceClass
*dc
= DEVICE_CLASS(klass
);
183 device_class_set_props(dc
, gicv2m_properties
);
184 dc
->realize
= gicv2m_realize
;
187 static const TypeInfo gicv2m_info
= {
188 .name
= TYPE_ARM_GICV2M
,
189 .parent
= TYPE_SYS_BUS_DEVICE
,
190 .instance_size
= sizeof(ARMGICv2mState
),
191 .instance_init
= gicv2m_init
,
192 .class_init
= gicv2m_class_init
,
195 static void gicv2m_register_types(void)
197 type_register_static(&gicv2m_info
);
200 type_init(gicv2m_register_types
)