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 "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "exec/memory.h"
18 #include "sysemu/sysemu.h"
19 #include "sysemu/kvm.h"
21 #include "hw/intc/mips_gic.h"
23 static void mips_gic_set_vp_irq(MIPSGICState
*gic
, int vp
, int pin
, int level
)
25 int ored_level
= level
;
28 /* ORing pending registers sharing same pin */
30 for (i
= 0; i
< gic
->num_irq
; i
++) {
31 if ((gic
->irq_state
[i
].map_pin
& GIC_MAP_MSK
) == pin
&&
32 gic
->irq_state
[i
].map_vp
== vp
&&
33 gic
->irq_state
[i
].enabled
) {
34 ored_level
|= gic
->irq_state
[i
].pending
;
37 /* no need to iterate all interrupts */
41 if (((gic
->vps
[vp
].compare_map
& GIC_MAP_MSK
) == pin
) &&
42 (gic
->vps
[vp
].mask
& GIC_VP_MASK_CMP_MSK
)) {
43 /* ORing with local pending register (count/compare) */
44 ored_level
|= (gic
->vps
[vp
].pend
& GIC_VP_MASK_CMP_MSK
) >>
49 kvm_mips_set_ipi_interrupt(mips_env_get_cpu(gic
->vps
[vp
].env
),
50 pin
+ GIC_CPU_PIN_OFFSET
,
53 qemu_set_irq(gic
->vps
[vp
].env
->irq
[pin
+ GIC_CPU_PIN_OFFSET
],
58 static void gic_set_irq(void *opaque
, int n_IRQ
, int level
)
60 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
61 int vp
= gic
->irq_state
[n_IRQ
].map_vp
;
62 int pin
= gic
->irq_state
[n_IRQ
].map_pin
& GIC_MAP_MSK
;
64 gic
->irq_state
[n_IRQ
].pending
= (uint8_t) level
;
65 if (!gic
->irq_state
[n_IRQ
].enabled
) {
66 /* GIC interrupt source disabled */
69 if (vp
< 0 || vp
>= gic
->num_vps
) {
72 mips_gic_set_vp_irq(gic
, vp
, pin
, level
);
75 #define OFFSET_CHECK(c) \
82 /* GIC Read VP Local/Other Registers */
83 static uint64_t gic_read_vp(MIPSGICState
*gic
, uint32_t vp_index
, hwaddr addr
,
88 return gic
->vps
[vp_index
].ctl
;
90 mips_gictimer_get_sh_count(gic
->gic_timer
);
91 return gic
->vps
[vp_index
].pend
;
93 return gic
->vps
[vp_index
].mask
;
94 case GIC_VP_COMPARE_MAP_OFS
:
95 return gic
->vps
[vp_index
].compare_map
;
96 case GIC_VP_OTHER_ADDR_OFS
:
97 return gic
->vps
[vp_index
].other_addr
;
98 case GIC_VP_IDENT_OFS
:
100 case GIC_VP_COMPARE_LO_OFS
:
101 return mips_gictimer_get_vp_compare(gic
->gic_timer
, vp_index
);
102 case GIC_VP_COMPARE_HI_OFS
:
105 qemu_log_mask(LOG_UNIMP
, "Read %d bytes at GIC offset LOCAL/OTHER 0x%"
106 PRIx64
"\n", size
, addr
);
112 static uint64_t gic_read(void *opaque
, hwaddr addr
, unsigned size
)
114 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
115 uint32_t vp_index
= current_cpu
->cpu_index
;
117 int i
, base
, irq_src
;
118 uint32_t other_index
;
121 case GIC_SH_CONFIG_OFS
:
122 ret
= gic
->sh_config
| (mips_gictimer_get_countstop(gic
->gic_timer
) <<
123 GIC_SH_CONFIG_COUNTSTOP_SHF
);
125 case GIC_SH_COUNTERLO_OFS
:
126 ret
= mips_gictimer_get_sh_count(gic
->gic_timer
);
128 case GIC_SH_COUNTERHI_OFS
:
131 case GIC_SH_PEND_OFS
... GIC_SH_PEND_LAST_OFS
:
132 /* each bit represents pending status for an interrupt pin */
133 base
= (addr
- GIC_SH_PEND_OFS
) * 8;
134 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
135 for (i
= 0; i
< size
* 8; i
++) {
136 ret
|= (uint64_t) (gic
->irq_state
[base
+ i
].pending
) << i
;
139 case GIC_SH_MASK_OFS
... GIC_SH_MASK_LAST_OFS
:
140 /* each bit represents status for an interrupt pin */
141 base
= (addr
- GIC_SH_MASK_OFS
) * 8;
142 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
143 for (i
= 0; i
< size
* 8; i
++) {
144 ret
|= (uint64_t) (gic
->irq_state
[base
+ i
].enabled
) << i
;
147 case GIC_SH_MAP0_PIN_OFS
... GIC_SH_MAP255_PIN_OFS
:
148 /* 32 bits per a pin */
149 irq_src
= (addr
- GIC_SH_MAP0_PIN_OFS
) / 4;
150 OFFSET_CHECK(irq_src
< gic
->num_irq
);
151 ret
= gic
->irq_state
[irq_src
].map_pin
;
153 case GIC_SH_MAP0_VP_OFS
... GIC_SH_MAP255_VP_LAST_OFS
:
154 /* up to 32 bytes per a pin */
155 irq_src
= (addr
- GIC_SH_MAP0_VP_OFS
) / 32;
156 OFFSET_CHECK(irq_src
< gic
->num_irq
);
157 if ((gic
->irq_state
[irq_src
].map_vp
) >= 0) {
158 ret
= (uint64_t) 1 << (gic
->irq_state
[irq_src
].map_vp
);
163 /* VP-Local Register */
164 case VP_LOCAL_SECTION_OFS
... (VP_LOCAL_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
165 ret
= gic_read_vp(gic
, vp_index
, addr
- VP_LOCAL_SECTION_OFS
, size
);
167 /* VP-Other Register */
168 case VP_OTHER_SECTION_OFS
... (VP_OTHER_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
169 other_index
= gic
->vps
[vp_index
].other_addr
;
170 ret
= gic_read_vp(gic
, other_index
, addr
- VP_OTHER_SECTION_OFS
, size
);
172 /* User-Mode Visible section */
173 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERLO
:
174 ret
= mips_gictimer_get_sh_count(gic
->gic_timer
);
176 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERHI
:
180 qemu_log_mask(LOG_UNIMP
, "Read %d bytes at GIC offset 0x%" PRIx64
"\n",
186 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
190 static void gic_timer_expire_cb(void *opaque
, uint32_t vp_index
)
192 MIPSGICState
*gic
= opaque
;
194 gic
->vps
[vp_index
].pend
|= (1 << GIC_LOCAL_INT_COMPARE
);
195 if (gic
->vps
[vp_index
].pend
&
196 (gic
->vps
[vp_index
].mask
& GIC_VP_MASK_CMP_MSK
)) {
197 if (gic
->vps
[vp_index
].compare_map
& GIC_MAP_TO_PIN_MSK
) {
198 /* it is safe to set the irq high regardless of other GIC IRQs */
199 uint32_t pin
= (gic
->vps
[vp_index
].compare_map
& GIC_MAP_MSK
);
200 qemu_irq_raise(gic
->vps
[vp_index
].env
->irq
201 [pin
+ GIC_CPU_PIN_OFFSET
]);
206 static void gic_timer_store_vp_compare(MIPSGICState
*gic
, uint32_t vp_index
,
209 gic
->vps
[vp_index
].pend
&= ~(1 << GIC_LOCAL_INT_COMPARE
);
210 if (gic
->vps
[vp_index
].compare_map
& GIC_MAP_TO_PIN_MSK
) {
211 uint32_t pin
= (gic
->vps
[vp_index
].compare_map
& GIC_MAP_MSK
);
212 mips_gic_set_vp_irq(gic
, vp_index
, pin
, 0);
214 mips_gictimer_store_vp_compare(gic
->gic_timer
, vp_index
, compare
);
217 /* GIC Write VP Local/Other Registers */
218 static void gic_write_vp(MIPSGICState
*gic
, uint32_t vp_index
, hwaddr addr
,
219 uint64_t data
, unsigned size
)
223 /* EIC isn't supported */
225 case GIC_VP_RMASK_OFS
:
226 gic
->vps
[vp_index
].mask
&= ~(data
& GIC_VP_SET_RESET_MSK
) &
227 GIC_VP_SET_RESET_MSK
;
229 case GIC_VP_SMASK_OFS
:
230 gic
->vps
[vp_index
].mask
|= data
& GIC_VP_SET_RESET_MSK
;
232 case GIC_VP_COMPARE_MAP_OFS
:
233 /* EIC isn't supported */
234 OFFSET_CHECK((data
& GIC_MAP_MSK
) <= GIC_CPU_INT_MAX
);
235 gic
->vps
[vp_index
].compare_map
= data
& GIC_MAP_TO_PIN_REG_MSK
;
237 case GIC_VP_OTHER_ADDR_OFS
:
238 OFFSET_CHECK(data
< gic
->num_vps
);
239 gic
->vps
[vp_index
].other_addr
= data
;
241 case GIC_VP_COMPARE_LO_OFS
:
242 gic_timer_store_vp_compare(gic
, vp_index
, data
);
245 qemu_log_mask(LOG_UNIMP
, "Write %d bytes at GIC offset LOCAL/OTHER "
246 "0x%" PRIx64
" 0x%08" PRIx64
"\n", size
, addr
, data
);
251 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
255 static void gic_write(void *opaque
, hwaddr addr
, uint64_t data
, unsigned size
)
258 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
259 uint32_t vp_index
= current_cpu
->cpu_index
;
260 int i
, base
, irq_src
;
261 uint32_t other_index
;
264 case GIC_SH_CONFIG_OFS
:
266 uint32_t pre_cntstop
= mips_gictimer_get_countstop(gic
->gic_timer
);
267 uint32_t new_cntstop
= (data
& GIC_SH_CONFIG_COUNTSTOP_MSK
) >>
268 GIC_SH_CONFIG_COUNTSTOP_SHF
;
269 if (pre_cntstop
!= new_cntstop
) {
270 if (new_cntstop
== 1) {
271 mips_gictimer_stop_count(gic
->gic_timer
);
273 mips_gictimer_start_count(gic
->gic_timer
);
278 case GIC_SH_COUNTERLO_OFS
:
279 if (mips_gictimer_get_countstop(gic
->gic_timer
)) {
280 mips_gictimer_store_sh_count(gic
->gic_timer
, data
);
283 case GIC_SH_RMASK_OFS
... GIC_SH_RMASK_LAST_OFS
:
284 /* up to 64 bits per a pin */
285 base
= (addr
- GIC_SH_RMASK_OFS
) * 8;
286 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
287 for (i
= 0; i
< size
* 8; i
++) {
288 gic
->irq_state
[base
+ i
].enabled
&= !((data
>> i
) & 1);
291 case GIC_SH_WEDGE_OFS
:
292 /* Figure out which VP/HW Interrupt this maps to */
293 intr
= data
& ~GIC_SH_WEDGE_RW_MSK
;
294 /* Mask/Enabled Checks */
295 OFFSET_CHECK(intr
< gic
->num_irq
);
296 if (data
& GIC_SH_WEDGE_RW_MSK
) {
297 gic_set_irq(gic
, intr
, 1);
299 gic_set_irq(gic
, intr
, 0);
302 case GIC_SH_SMASK_OFS
... GIC_SH_SMASK_LAST_OFS
:
303 /* up to 64 bits per a pin */
304 base
= (addr
- GIC_SH_SMASK_OFS
) * 8;
305 OFFSET_CHECK((base
+ size
* 8) <= gic
->num_irq
);
306 for (i
= 0; i
< size
* 8; i
++) {
307 gic
->irq_state
[base
+ i
].enabled
|= (data
>> i
) & 1;
310 case GIC_SH_MAP0_PIN_OFS
... GIC_SH_MAP255_PIN_OFS
:
311 /* 32 bits per a pin */
312 irq_src
= (addr
- GIC_SH_MAP0_PIN_OFS
) / 4;
313 OFFSET_CHECK(irq_src
< gic
->num_irq
);
314 /* EIC isn't supported */
315 OFFSET_CHECK((data
& GIC_MAP_MSK
) <= GIC_CPU_INT_MAX
);
316 gic
->irq_state
[irq_src
].map_pin
= data
& GIC_MAP_TO_PIN_REG_MSK
;
318 case GIC_SH_MAP0_VP_OFS
... GIC_SH_MAP255_VP_LAST_OFS
:
319 /* up to 32 bytes per a pin */
320 irq_src
= (addr
- GIC_SH_MAP0_VP_OFS
) / 32;
321 OFFSET_CHECK(irq_src
< gic
->num_irq
);
322 data
= data
? ctz64(data
) : -1;
323 OFFSET_CHECK(data
< gic
->num_vps
);
324 gic
->irq_state
[irq_src
].map_vp
= data
;
326 case VP_LOCAL_SECTION_OFS
... (VP_LOCAL_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
327 gic_write_vp(gic
, vp_index
, addr
- VP_LOCAL_SECTION_OFS
, data
, size
);
329 case VP_OTHER_SECTION_OFS
... (VP_OTHER_SECTION_OFS
+ GIC_VL_BRK_GROUP
):
330 other_index
= gic
->vps
[vp_index
].other_addr
;
331 gic_write_vp(gic
, other_index
, addr
- VP_OTHER_SECTION_OFS
, data
, size
);
333 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERLO
:
334 case USM_VISIBLE_SECTION_OFS
+ GIC_USER_MODE_COUNTERHI
:
335 /* do nothing. Read-only section */
338 qemu_log_mask(LOG_UNIMP
, "Write %d bytes at GIC offset 0x%" PRIx64
339 " 0x%08" PRIx64
"\n", size
, addr
, data
);
344 qemu_log_mask(LOG_GUEST_ERROR
, "Wrong GIC offset at 0x%" PRIx64
"\n", addr
);
347 static void gic_reset(void *opaque
)
350 MIPSGICState
*gic
= (MIPSGICState
*) opaque
;
351 int numintrs
= (gic
->num_irq
/ 8) - 1;
353 gic
->sh_config
= /* COUNTSTOP = 0 it is accessible via MIPSGICTimer*/
354 /* CounterHi not implemented */
355 (0 << GIC_SH_CONFIG_COUNTBITS_SHF
) |
356 (numintrs
<< GIC_SH_CONFIG_NUMINTRS_SHF
) |
357 (gic
->num_vps
<< GIC_SH_CONFIG_PVPS_SHF
);
358 for (i
= 0; i
< gic
->num_vps
; i
++) {
359 gic
->vps
[i
].ctl
= 0x0;
360 gic
->vps
[i
].pend
= 0x0;
361 /* PERFCNT, TIMER and WD not implemented */
362 gic
->vps
[i
].mask
= 0x32;
363 gic
->vps
[i
].compare_map
= GIC_MAP_TO_PIN_MSK
;
364 mips_gictimer_store_vp_compare(gic
->gic_timer
, i
, 0xffffffff);
365 gic
->vps
[i
].other_addr
= 0x0;
367 for (i
= 0; i
< gic
->num_irq
; i
++) {
368 gic
->irq_state
[i
].enabled
= 0;
369 gic
->irq_state
[i
].pending
= 0;
370 gic
->irq_state
[i
].map_pin
= GIC_MAP_TO_PIN_MSK
;
371 gic
->irq_state
[i
].map_vp
= -1;
373 mips_gictimer_store_sh_count(gic
->gic_timer
, 0);
375 mips_gictimer_start_count(gic
->gic_timer
);
378 static const MemoryRegionOps gic_ops
= {
381 .endianness
= DEVICE_NATIVE_ENDIAN
,
383 .max_access_size
= 8,
387 static void mips_gic_init(Object
*obj
)
389 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
390 MIPSGICState
*s
= MIPS_GIC(obj
);
392 memory_region_init_io(&s
->mr
, OBJECT(s
), &gic_ops
, s
,
393 "mips-gic", GIC_ADDRSPACE_SZ
);
394 sysbus_init_mmio(sbd
, &s
->mr
);
395 qemu_register_reset(gic_reset
, s
);
398 static void mips_gic_realize(DeviceState
*dev
, Error
**errp
)
400 MIPSGICState
*s
= MIPS_GIC(dev
);
401 CPUState
*cs
= first_cpu
;
404 if (s
->num_vps
> GIC_MAX_VPS
) {
405 error_setg(errp
, "Exceeded maximum CPUs %d", s
->num_vps
);
408 if ((s
->num_irq
> GIC_MAX_INTRS
) || (s
->num_irq
% 8) || (s
->num_irq
<= 0)) {
409 error_setg(errp
, "GIC supports up to %d external interrupts in "
410 "multiples of 8 : %d", GIC_MAX_INTRS
, s
->num_irq
);
413 s
->vps
= g_new(MIPSGICVPState
, s
->num_vps
);
414 s
->irq_state
= g_new(MIPSGICIRQState
, s
->num_irq
);
415 /* Register the env for all VPs with the GIC */
416 for (i
= 0; i
< s
->num_vps
; i
++) {
418 s
->vps
[i
].env
= cs
->env_ptr
;
422 "Unable to initialize GIC, CPUState for CPU#%d not valid.", i
);
426 s
->gic_timer
= mips_gictimer_init(s
, s
->num_vps
, gic_timer_expire_cb
);
427 qdev_init_gpio_in(dev
, gic_set_irq
, s
->num_irq
);
428 for (i
= 0; i
< s
->num_irq
; i
++) {
429 s
->irq_state
[i
].irq
= qdev_get_gpio_in(dev
, i
);
433 static Property mips_gic_properties
[] = {
434 DEFINE_PROP_INT32("num-vp", MIPSGICState
, num_vps
, 1),
435 DEFINE_PROP_INT32("num-irq", MIPSGICState
, num_irq
, 256),
436 DEFINE_PROP_END_OF_LIST(),
439 static void mips_gic_class_init(ObjectClass
*klass
, void *data
)
441 DeviceClass
*dc
= DEVICE_CLASS(klass
);
443 dc
->props
= mips_gic_properties
;
444 dc
->realize
= mips_gic_realize
;
447 static const TypeInfo mips_gic_info
= {
448 .name
= TYPE_MIPS_GIC
,
449 .parent
= TYPE_SYS_BUS_DEVICE
,
450 .instance_size
= sizeof(MIPSGICState
),
451 .instance_init
= mips_gic_init
,
452 .class_init
= mips_gic_class_init
,
455 static void mips_gic_register_types(void)
457 type_register_static(&mips_gic_info
);
460 type_init(mips_gic_register_types
)