2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 * Authors: Sanjay Lal <sanjayl@kymasys.com>
9 * Copyright (C) 2016 Imagination Technologies
12 #include "qemu/osdep.h"
14 #include "qemu/module.h"
15 #include "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "exec/memory.h"
18 #include "sysemu/sysemu.h"
19 #include "sysemu/kvm.h"
20 #include "sysemu/reset.h"
22 #include "hw/intc/mips_gic.h"
24 #include "hw/qdev-properties.h"
26 static void mips_gic_set_vp_irq(MIPSGICState
*gic
, int vp
, int pin
)
31 /* ORing pending registers sharing same pin */
32 for (i
= 0; i
< gic
->num_irq
; i
++) {
33 if ((gic
->irq_state
[i
].map_pin
& GIC_MAP_MSK
) == pin
&&
34 gic
->irq_state
[i
].map_vp
== vp
&&
35 gic
->irq_state
[i
].enabled
) {
36 ored_level
|= gic
->irq_state
[i
].pending
;
39 /* no need to iterate all interrupts */
43 if (((gic
->vps
[vp
].compare_map
& GIC_MAP_MSK
) == pin
) &&
44 (gic
->vps
[vp
].mask
& GIC_VP_MASK_CMP_MSK
)) {
45 /* ORing with local pending register (count/compare) */
46 ored_level
|= (gic
->vps
[vp
].pend
& GIC_VP_MASK_CMP_MSK
) >>
50 kvm_mips_set_ipi_interrupt(env_archcpu(gic
->vps
[vp
].env
),
51 pin
+ GIC_CPU_PIN_OFFSET
,
54 qemu_set_irq(gic
->vps
[vp
].env
->irq
[pin
+ GIC_CPU_PIN_OFFSET
],
59 static void gic_update_pin_for_irq(MIPSGICState
*gic
, int n_IRQ
)
61 int vp
= gic
->irq_state
[n_IRQ
].map_vp
;
62 int pin
= gic
->irq_state
[n_IRQ
].map_pin
& GIC_MAP_MSK
;
64 if (vp
< 0 || vp
>= gic
->num_vps
) {
67 mips_gic_set_vp_irq(gic
, vp
, pin
);
70 static void gic_set_irq(void *opaque
, int n_IRQ
, int level
)
72 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
74 gic
->irq_state
[n_IRQ
].pending
= (uint8_t) level
;
75 if (!gic
->irq_state
[n_IRQ
].enabled
) {
76 /* GIC interrupt source disabled */
79 gic_update_pin_for_irq(gic
, n_IRQ
);
82 #define OFFSET_CHECK(c) \
89 /* GIC Read VP Local/Other Registers */
90 static uint64_t gic_read_vp(MIPSGICState
*gic
, uint32_t vp_index
, hwaddr addr
,
95 return gic
->vps
[vp_index
].ctl
;
97 mips_gictimer_get_sh_count(gic
->gic_timer
);
98 return gic
->vps
[vp_index
].pend
;
100 return gic
->vps
[vp_index
].mask
;
101 case GIC_VP_COMPARE_MAP_OFS
:
102 return gic
->vps
[vp_index
].compare_map
;
103 case GIC_VP_OTHER_ADDR_OFS
:
104 return gic
->vps
[vp_index
].other_addr
;
105 case GIC_VP_IDENT_OFS
:
107 case GIC_VP_COMPARE_LO_OFS
:
108 return mips_gictimer_get_vp_compare(gic
->gic_timer
, vp_index
);
109 case GIC_VP_COMPARE_HI_OFS
:
112 qemu_log_mask(LOG_UNIMP
, "Read %d bytes at GIC offset LOCAL/OTHER 0x%"
113 PRIx64
"\n", size
, addr
);
119 static uint64_t gic_read(void *opaque
, hwaddr addr
, unsigned size
)
121 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
122 uint32_t vp_index
= current_cpu
->cpu_index
;
124 int i
, base
, irq_src
;
125 uint32_t other_index
;
128 case GIC_SH_CONFIG_OFS
:
129 ret
= gic
->sh_config
| (mips_gictimer_get_countstop(gic
->gic_timer
) <<
130 GIC_SH_CONFIG_COUNTSTOP_SHF
);
132 case GIC_SH_COUNTERLO_OFS
:
133 ret
= mips_gictimer_get_sh_count(gic
->gic_timer
);
135 case GIC_SH_COUNTERHI_OFS
:
138 case GIC_SH_PEND_OFS
... GIC_SH_PEND_LAST_OFS
:
139 /* each bit represents pending status for an interrupt pin */
140 base
= (addr
- GIC_SH_PEND_OFS
) * 8;
141 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
142 for (i
= 0; i
< size
* 8; i
++) {
143 ret
|= (uint64_t) (gic
->irq_state
[base
+ i
].pending
) << i
;
146 case GIC_SH_MASK_OFS
... GIC_SH_MASK_LAST_OFS
:
147 /* each bit represents status for an interrupt pin */
148 base
= (addr
- GIC_SH_MASK_OFS
) * 8;
149 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
150 for (i
= 0; i
< size
* 8; i
++) {
151 ret
|= (uint64_t) (gic
->irq_state
[base
+ i
].enabled
) << i
;
154 case GIC_SH_MAP0_PIN_OFS
... GIC_SH_MAP255_PIN_OFS
:
155 /* 32 bits per a pin */
156 irq_src
= (addr
- GIC_SH_MAP0_PIN_OFS
) / 4;
157 OFFSET_CHECK(irq_src
< gic
->num_irq
);
158 ret
= gic
->irq_state
[irq_src
].map_pin
;
160 case GIC_SH_MAP0_VP_OFS
... GIC_SH_MAP255_VP_LAST_OFS
:
161 /* up to 32 bytes per a pin */
162 irq_src
= (addr
- GIC_SH_MAP0_VP_OFS
) / 32;
163 OFFSET_CHECK(irq_src
< gic
->num_irq
);
164 if ((gic
->irq_state
[irq_src
].map_vp
) >= 0) {
165 ret
= (uint64_t) 1 << (gic
->irq_state
[irq_src
].map_vp
);
170 /* VP-Local Register */
171 case VP_LOCAL_SECTION_OFS
... (VP_LOCAL_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
172 ret
= gic_read_vp(gic
, vp_index
, addr
- VP_LOCAL_SECTION_OFS
, size
);
174 /* VP-Other Register */
175 case VP_OTHER_SECTION_OFS
... (VP_OTHER_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
176 other_index
= gic
->vps
[vp_index
].other_addr
;
177 ret
= gic_read_vp(gic
, other_index
, addr
- VP_OTHER_SECTION_OFS
, size
);
179 /* User-Mode Visible section */
180 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERLO
:
181 ret
= mips_gictimer_get_sh_count(gic
->gic_timer
);
183 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERHI
:
187 qemu_log_mask(LOG_UNIMP
, "Read %d bytes at GIC offset 0x%" PRIx64
"\n",
193 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
197 static void gic_timer_expire_cb(void *opaque
, uint32_t vp_index
)
199 MIPSGICState
*gic
= opaque
;
201 gic
->vps
[vp_index
].pend
|= (1 << GIC_LOCAL_INT_COMPARE
);
202 if (gic
->vps
[vp_index
].pend
&
203 (gic
->vps
[vp_index
].mask
& GIC_VP_MASK_CMP_MSK
)) {
204 if (gic
->vps
[vp_index
].compare_map
& GIC_MAP_TO_PIN_MSK
) {
205 /* it is safe to set the irq high regardless of other GIC IRQs */
206 uint32_t pin
= (gic
->vps
[vp_index
].compare_map
& GIC_MAP_MSK
);
207 qemu_irq_raise(gic
->vps
[vp_index
].env
->irq
208 [pin
+ GIC_CPU_PIN_OFFSET
]);
213 static void gic_timer_store_vp_compare(MIPSGICState
*gic
, uint32_t vp_index
,
216 gic
->vps
[vp_index
].pend
&= ~(1 << GIC_LOCAL_INT_COMPARE
);
217 if (gic
->vps
[vp_index
].compare_map
& GIC_MAP_TO_PIN_MSK
) {
218 uint32_t pin
= (gic
->vps
[vp_index
].compare_map
& GIC_MAP_MSK
);
219 mips_gic_set_vp_irq(gic
, vp_index
, pin
);
221 mips_gictimer_store_vp_compare(gic
->gic_timer
, vp_index
, compare
);
224 /* GIC Write VP Local/Other Registers */
225 static void gic_write_vp(MIPSGICState
*gic
, uint32_t vp_index
, hwaddr addr
,
226 uint64_t data
, unsigned size
)
230 /* EIC isn't supported */
232 case GIC_VP_RMASK_OFS
:
233 gic
->vps
[vp_index
].mask
&= ~(data
& GIC_VP_SET_RESET_MSK
) &
234 GIC_VP_SET_RESET_MSK
;
236 case GIC_VP_SMASK_OFS
:
237 gic
->vps
[vp_index
].mask
|= data
& GIC_VP_SET_RESET_MSK
;
239 case GIC_VP_COMPARE_MAP_OFS
:
240 /* EIC isn't supported */
241 OFFSET_CHECK((data
& GIC_MAP_MSK
) <= GIC_CPU_INT_MAX
);
242 gic
->vps
[vp_index
].compare_map
= data
& GIC_MAP_TO_PIN_REG_MSK
;
244 case GIC_VP_OTHER_ADDR_OFS
:
245 OFFSET_CHECK(data
< gic
->num_vps
);
246 gic
->vps
[vp_index
].other_addr
= data
;
248 case GIC_VP_COMPARE_LO_OFS
:
249 gic_timer_store_vp_compare(gic
, vp_index
, data
);
252 qemu_log_mask(LOG_UNIMP
, "Write %d bytes at GIC offset LOCAL/OTHER "
253 "0x%" PRIx64
" 0x%08" PRIx64
"\n", size
, addr
, data
);
258 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
262 static void gic_write(void *opaque
, hwaddr addr
, uint64_t data
, unsigned size
)
265 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
266 uint32_t vp_index
= current_cpu
->cpu_index
;
267 int i
, base
, irq_src
;
268 uint32_t other_index
;
271 case GIC_SH_CONFIG_OFS
:
273 uint32_t pre_cntstop
= mips_gictimer_get_countstop(gic
->gic_timer
);
274 uint32_t new_cntstop
= (data
& GIC_SH_CONFIG_COUNTSTOP_MSK
) >>
275 GIC_SH_CONFIG_COUNTSTOP_SHF
;
276 if (pre_cntstop
!= new_cntstop
) {
277 if (new_cntstop
== 1) {
278 mips_gictimer_stop_count(gic
->gic_timer
);
280 mips_gictimer_start_count(gic
->gic_timer
);
285 case GIC_SH_COUNTERLO_OFS
:
286 if (mips_gictimer_get_countstop(gic
->gic_timer
)) {
287 mips_gictimer_store_sh_count(gic
->gic_timer
, data
);
290 case GIC_SH_RMASK_OFS
... GIC_SH_RMASK_LAST_OFS
:
291 /* up to 64 bits per a pin */
292 base
= (addr
- GIC_SH_RMASK_OFS
) * 8;
293 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
294 for (i
= 0; i
< size
* 8; i
++) {
295 gic
->irq_state
[base
+ i
].enabled
&= !((data
>> i
) & 1);
296 gic_update_pin_for_irq(gic
, base
+ i
);
299 case GIC_SH_WEDGE_OFS
:
300 /* Figure out which VP/HW Interrupt this maps to */
301 intr
= data
& ~GIC_SH_WEDGE_RW_MSK
;
302 /* Mask/Enabled Checks */
303 OFFSET_CHECK(intr
< gic
->num_irq
);
304 if (data
& GIC_SH_WEDGE_RW_MSK
) {
305 gic_set_irq(gic
, intr
, 1);
307 gic_set_irq(gic
, intr
, 0);
310 case GIC_SH_SMASK_OFS
... GIC_SH_SMASK_LAST_OFS
:
311 /* up to 64 bits per a pin */
312 base
= (addr
- GIC_SH_SMASK_OFS
) * 8;
313 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
314 for (i
= 0; i
< size
* 8; i
++) {
315 gic
->irq_state
[base
+ i
].enabled
|= (data
>> i
) & 1;
316 gic_update_pin_for_irq(gic
, base
+ i
);
319 case GIC_SH_MAP0_PIN_OFS
... GIC_SH_MAP255_PIN_OFS
:
320 /* 32 bits per a pin */
321 irq_src
= (addr
- GIC_SH_MAP0_PIN_OFS
) / 4;
322 OFFSET_CHECK(irq_src
< gic
->num_irq
);
323 /* EIC isn't supported */
324 OFFSET_CHECK((data
& GIC_MAP_MSK
) <= GIC_CPU_INT_MAX
);
325 gic
->irq_state
[irq_src
].map_pin
= data
& GIC_MAP_TO_PIN_REG_MSK
;
327 case GIC_SH_MAP0_VP_OFS
... GIC_SH_MAP255_VP_LAST_OFS
:
328 /* up to 32 bytes per a pin */
329 irq_src
= (addr
- GIC_SH_MAP0_VP_OFS
) / 32;
330 OFFSET_CHECK(irq_src
< gic
->num_irq
);
331 data
= data
? ctz64(data
) : -1;
332 OFFSET_CHECK(data
< gic
->num_vps
);
333 gic
->irq_state
[irq_src
].map_vp
= data
;
335 case VP_LOCAL_SECTION_OFS
... (VP_LOCAL_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
336 gic_write_vp(gic
, vp_index
, addr
- VP_LOCAL_SECTION_OFS
, data
, size
);
338 case VP_OTHER_SECTION_OFS
... (VP_OTHER_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
339 other_index
= gic
->vps
[vp_index
].other_addr
;
340 gic_write_vp(gic
, other_index
, addr
- VP_OTHER_SECTION_OFS
, data
, size
);
342 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERLO
:
343 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERHI
:
344 /* do nothing. Read-only section */
347 qemu_log_mask(LOG_UNIMP
, "Write %d bytes at GIC offset 0x%" PRIx64
348 " 0x%08" PRIx64
"\n", size
, addr
, data
);
353 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
356 static void gic_reset(void *opaque
)
359 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
360 int numintrs
= (gic
->num_irq
/ 8) - 1;
362 gic
->sh_config
= /* COUNTSTOP = 0 it is accessible via MIPSGICTimer*/
363 /* CounterHi not implemented */
364 (0 << GIC_SH_CONFIG_COUNTBITS_SHF
) |
365 (numintrs
<< GIC_SH_CONFIG_NUMINTRS_SHF
) |
366 (gic
->num_vps
<< GIC_SH_CONFIG_PVPS_SHF
);
367 for (i
= 0; i
< gic
->num_vps
; i
++) {
368 gic
->vps
[i
].ctl
= 0x0;
369 gic
->vps
[i
].pend
= 0x0;
370 /* PERFCNT, TIMER and WD not implemented */
371 gic
->vps
[i
].mask
= 0x32;
372 gic
->vps
[i
].compare_map
= GIC_MAP_TO_PIN_MSK
;
373 mips_gictimer_store_vp_compare(gic
->gic_timer
, i
, 0xffffffff);
374 gic
->vps
[i
].other_addr
= 0x0;
376 for (i
= 0; i
< gic
->num_irq
; i
++) {
377 gic
->irq_state
[i
].enabled
= 0;
378 gic
->irq_state
[i
].pending
= 0;
379 gic
->irq_state
[i
].map_pin
= GIC_MAP_TO_PIN_MSK
;
380 gic
->irq_state
[i
].map_vp
= -1;
382 mips_gictimer_store_sh_count(gic
->gic_timer
, 0);
384 mips_gictimer_start_count(gic
->gic_timer
);
387 static const MemoryRegionOps gic_ops
= {
390 .endianness
= DEVICE_NATIVE_ENDIAN
,
392 .max_access_size
= 8,
396 static void mips_gic_init(Object
*obj
)
398 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
399 MIPSGICState
*s
= MIPS_GIC(obj
);
401 memory_region_init_io(&s
->mr
, OBJECT(s
), &gic_ops
, s
,
402 "mips-gic", GIC_ADDRSPACE_SZ
);
403 sysbus_init_mmio(sbd
, &s
->mr
);
404 qemu_register_reset(gic_reset
, s
);
407 static void mips_gic_realize(DeviceState
*dev
, Error
**errp
)
409 MIPSGICState
*s
= MIPS_GIC(dev
);
410 CPUState
*cs
= first_cpu
;
413 if (s
->num_vps
> GIC_MAX_VPS
) {
414 error_setg(errp
, "Exceeded maximum CPUs %d", s
->num_vps
);
417 if ((s
->num_irq
> GIC_MAX_INTRS
) || (s
->num_irq
% 8) || (s
->num_irq
<= 0)) {
418 error_setg(errp
, "GIC supports up to %d external interrupts in "
419 "multiples of 8 : %d", GIC_MAX_INTRS
, s
->num_irq
);
422 s
->vps
= g_new(MIPSGICVPState
, s
->num_vps
);
423 s
->irq_state
= g_new(MIPSGICIRQState
, s
->num_irq
);
424 /* Register the env for all VPs with the GIC */
425 for (i
= 0; i
< s
->num_vps
; i
++) {
427 s
->vps
[i
].env
= cs
->env_ptr
;
431 "Unable to initialize GIC, CPUState for CPU#%d not valid.", i
);
435 s
->gic_timer
= mips_gictimer_init(s
, s
->num_vps
, gic_timer_expire_cb
);
436 qdev_init_gpio_in(dev
, gic_set_irq
, s
->num_irq
);
437 for (i
= 0; i
< s
->num_irq
; i
++) {
438 s
->irq_state
[i
].irq
= qdev_get_gpio_in(dev
, i
);
442 static Property mips_gic_properties
[] = {
443 DEFINE_PROP_INT32("num-vp", MIPSGICState
, num_vps
, 1),
444 DEFINE_PROP_INT32("num-irq", MIPSGICState
, num_irq
, 256),
445 DEFINE_PROP_END_OF_LIST(),
448 static void mips_gic_class_init(ObjectClass
*klass
, void *data
)
450 DeviceClass
*dc
= DEVICE_CLASS(klass
);
452 dc
->props
= mips_gic_properties
;
453 dc
->realize
= mips_gic_realize
;
456 static const TypeInfo mips_gic_info
= {
457 .name
= TYPE_MIPS_GIC
,
458 .parent
= TYPE_SYS_BUS_DEVICE
,
459 .instance_size
= sizeof(MIPSGICState
),
460 .instance_init
= mips_gic_init
,
461 .class_init
= mips_gic_class_init
,
464 static void mips_gic_register_types(void)
466 type_register_static(&mips_gic_info
);
469 type_init(mips_gic_register_types
)