master
c 596 lines 20.5 KB
Raw
1 /*
2 * RISC-V ACLINT (Advanced Core Local Interruptor)
3 * URL: https://github.com/riscv/riscv-aclint
4 *
5 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
6 * Copyright (c) 2017 SiFive, Inc.
7 * Copyright (c) 2021 Western Digital Corporation or its affiliates.
8 *
9 * This provides real-time clock, timer and interprocessor interrupts.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2 or later, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "qemu/osdep.h"
25 #include "qapi/error.h"
26 #include "qemu/error-report.h"
27 #include "qemu/log.h"
28 #include "qemu/module.h"
29 #include "hw/core/sysbus.h"
30 #include "target/riscv/cpu.h"
31 #include "target/riscv/time_helper.h"
32 #include "hw/core/qdev-properties.h"
33 #include "hw/intc/riscv_aclint.h"
34 #include "qemu/timer.h"
35 #include "hw/core/irq.h"
36 #include "migration/vmstate.h"
37
38 typedef struct riscv_aclint_mtimer_callback {
39 RISCVAclintMTimerState *s;
40 int num;
41 } riscv_aclint_mtimer_callback;
42
43 static void riscv_cpu_set_rdtime_fn(CPURISCVState *env,
44 uint64_t (*fn)(void *),
45 void *arg)
46 {
47 env->rdtime_fn = fn;
48 env->rdtime_fn_arg = arg;
49 }
50
51 static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
52 {
53 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
54 timebase_freq, NANOSECONDS_PER_SECOND);
55 }
56
57 static uint64_t cpu_riscv_read_rtc(void *opaque)
58 {
59 RISCVAclintMTimerState *mtimer = opaque;
60 return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_delta;
61 }
62
63 /*
64 * Called when timecmp is written to update the QEMU timer or immediately
65 * trigger timer interrupt if mtimecmp <= current timer value.
66 */
67 static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
68 RISCVCPU *cpu,
69 int hartid,
70 uint64_t value)
71 {
72 uint32_t timebase_freq = mtimer->timebase_freq;
73 uint64_t next;
74 uint64_t diff;
75
76 uint64_t rtc = cpu_riscv_read_rtc(mtimer);
77
78 /* Compute the relative hartid w.r.t the socket */
79 hartid = hartid - mtimer->hartid_base;
80
81 mtimer->timecmp[hartid] = value;
82 if (mtimer->timecmp[hartid] <= rtc) {
83 /*
84 * If we're setting an MTIMECMP value in the "past",
85 * immediately raise the timer interrupt
86 */
87 qemu_irq_raise(mtimer->timer_irqs[hartid]);
88 return;
89 }
90
91 /* otherwise, set up the future timer interrupt */
92 qemu_irq_lower(mtimer->timer_irqs[hartid]);
93 diff = mtimer->timecmp[hartid] - rtc;
94 /* back to ns (note args switched in muldiv64) */
95 uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
96
97 /*
98 * check if ns_diff overflowed and check if the addition would potentially
99 * overflow
100 */
101 if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) ||
102 ns_diff > INT64_MAX) {
103 next = INT64_MAX;
104 } else {
105 /*
106 * as it is very unlikely qemu_clock_get_ns will return a value
107 * greater than INT64_MAX, no additional check is needed for an
108 * unsigned integer overflow.
109 */
110 next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff;
111 /*
112 * if ns_diff is INT64_MAX next may still be outside the range
113 * of a signed integer.
114 */
115 next = MIN(next, INT64_MAX);
116 }
117
118 timer_mod(mtimer->timers[hartid], next);
119 }
120
121 /*
122 * Callback used when the timer set using timer_mod expires.
123 * Should raise the timer interrupt line
124 */
125 static void riscv_aclint_mtimer_cb(void *opaque)
126 {
127 riscv_aclint_mtimer_callback *state = opaque;
128
129 qemu_irq_raise(state->s->timer_irqs[state->num]);
130 }
131
132 /* CPU read MTIMER register */
133 static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
134 unsigned size)
135 {
136 RISCVAclintMTimerState *mtimer = opaque;
137
138 if (addr >= mtimer->timecmp_base &&
139 addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
140 size_t hartid = mtimer->hartid_base +
141 ((addr - mtimer->timecmp_base) >> 3);
142 size_t hartid_offset = hartid - mtimer->hartid_base;
143 CPUState *cpu = cpu_by_arch_id(hartid);
144 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
145 if (!env) {
146 qemu_log_mask(LOG_GUEST_ERROR,
147 "aclint-mtimer: invalid hartid: %zu", hartid);
148 } else if ((addr & 0x7) == 0) {
149 /* timecmp_lo for RV32/RV64 or timecmp for RV64 */
150 uint64_t timecmp = mtimer->timecmp[hartid_offset];
151 return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp;
152 } else if ((addr & 0x7) == 4) {
153 /* timecmp_hi */
154 uint64_t timecmp = mtimer->timecmp[hartid_offset];
155 return (timecmp >> 32) & 0xFFFFFFFF;
156 } else {
157 qemu_log_mask(LOG_UNIMP,
158 "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
159 return 0;
160 }
161 } else if (addr == mtimer->time_base) {
162 /* time_lo for RV32/RV64 or timecmp for RV64 */
163 uint64_t rtc = cpu_riscv_read_rtc(mtimer);
164 return (size == 4) ? (rtc & 0xFFFFFFFF) : rtc;
165 } else if (addr == mtimer->time_base + 4) {
166 /* time_hi */
167 return (cpu_riscv_read_rtc(mtimer) >> 32) & 0xFFFFFFFF;
168 }
169
170 qemu_log_mask(LOG_UNIMP,
171 "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
172 return 0;
173 }
174
175 /* CPU write MTIMER register */
176 static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
177 uint64_t value, unsigned size)
178 {
179 RISCVAclintMTimerState *mtimer = opaque;
180 int i;
181
182 if (addr >= mtimer->timecmp_base &&
183 addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
184 size_t hartid = mtimer->hartid_base +
185 ((addr - mtimer->timecmp_base) >> 3);
186 size_t hartid_offset = hartid - mtimer->hartid_base;
187 CPUState *cpu = cpu_by_arch_id(hartid);
188 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
189 if (!env) {
190 qemu_log_mask(LOG_GUEST_ERROR,
191 "aclint-mtimer: invalid hartid: %zu", hartid);
192 } else if ((addr & 0x7) == 0) {
193 if (size == 4) {
194 /* timecmp_lo for RV32/RV64 */
195 uint64_t timecmp_hi = mtimer->timecmp[hartid_offset] >> 32;
196 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
197 timecmp_hi << 32 | (value & 0xFFFFFFFF));
198 } else {
199 /* timecmp for RV64 */
200 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
201 value);
202 }
203 } else if ((addr & 0x7) == 4) {
204 if (size == 4) {
205 /* timecmp_hi for RV32/RV64 */
206 uint64_t timecmp_lo = mtimer->timecmp[hartid_offset];
207 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
208 value << 32 | (timecmp_lo & 0xFFFFFFFF));
209 } else {
210 qemu_log_mask(LOG_GUEST_ERROR,
211 "aclint-mtimer: invalid timecmp_hi write: %08x",
212 (uint32_t)addr);
213 }
214 } else {
215 qemu_log_mask(LOG_UNIMP,
216 "aclint-mtimer: invalid timecmp write: %08x",
217 (uint32_t)addr);
218 }
219 return;
220 } else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
221 uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
222 uint64_t rtc = cpu_riscv_read_rtc(mtimer);
223
224 if (addr == mtimer->time_base) {
225 if (size == 4) {
226 /* time_lo for RV32/RV64 */
227 mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
228 } else {
229 /* time for RV64 */
230 mtimer->time_delta = value - rtc_r;
231 }
232 } else {
233 if (size == 4) {
234 /* time_hi for RV32/RV64 */
235 mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
236 } else {
237 qemu_log_mask(LOG_GUEST_ERROR,
238 "aclint-mtimer: invalid time_hi write: %08x",
239 (uint32_t)addr);
240 return;
241 }
242 }
243
244 /* Check if timer interrupt is triggered for each hart. */
245 for (i = 0; i < mtimer->num_harts; i++) {
246 CPUState *cpu = cpu_by_arch_id(mtimer->hartid_base + i);
247 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
248 if (!env) {
249 continue;
250 }
251 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu),
252 mtimer->hartid_base + i,
253 mtimer->timecmp[i]);
254 riscv_timer_write_timecmp(env, env->stimer, env->stimecmp, 0, MIP_STIP);
255 riscv_timer_write_timecmp(env, env->vstimer, env->vstimecmp,
256 env->htimedelta, MIP_VSTIP);
257
258 }
259 return;
260 }
261
262 qemu_log_mask(LOG_UNIMP,
263 "aclint-mtimer: invalid write: %08x", (uint32_t)addr);
264 }
265
266 static const MemoryRegionOps riscv_aclint_mtimer_ops = {
267 .read = riscv_aclint_mtimer_read,
268 .write = riscv_aclint_mtimer_write,
269 .endianness = DEVICE_LITTLE_ENDIAN,
270 .valid = {
271 .min_access_size = 4,
272 .max_access_size = 8
273 },
274 .impl = {
275 .min_access_size = 4,
276 .max_access_size = 8,
277 }
278 };
279
280 static const Property riscv_aclint_mtimer_properties[] = {
281 DEFINE_PROP_UINT32("hartid-base", RISCVAclintMTimerState,
282 hartid_base, 0),
283 DEFINE_PROP_UINT32("num-harts", RISCVAclintMTimerState, num_harts, 1),
284 DEFINE_PROP_UINT32("timecmp-base", RISCVAclintMTimerState,
285 timecmp_base, RISCV_ACLINT_DEFAULT_MTIMECMP),
286 DEFINE_PROP_UINT32("time-base", RISCVAclintMTimerState,
287 time_base, RISCV_ACLINT_DEFAULT_MTIME),
288 DEFINE_PROP_UINT32("aperture-size", RISCVAclintMTimerState,
289 aperture_size, RISCV_ACLINT_DEFAULT_MTIMER_SIZE),
290 DEFINE_PROP_UINT32("timebase-freq", RISCVAclintMTimerState,
291 timebase_freq, 0),
292 };
293
294 static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
295 {
296 RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
297 int i;
298
299 memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops,
300 s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size);
301 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
302
303 s->timer_irqs = g_new(qemu_irq, s->num_harts);
304 qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
305
306 s->timers = g_new0(QEMUTimer *, s->num_harts);
307 s->timecmp = g_new0(uint64_t, s->num_harts);
308 /* Claim timer interrupt bits */
309 for (i = 0; i < s->num_harts; i++) {
310 CPUState *cpu_by_hartid = cpu_by_arch_id(s->hartid_base + i);
311 if (cpu_by_hartid == NULL) {
312 /* Valid for sparse hart layouts - skip this hart ID */
313 continue;
314 }
315 RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid);
316 if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
317 error_report("MTIP already claimed");
318 exit(1);
319 }
320 }
321 }
322
323 static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
324 {
325 /*
326 * According to RISC-V ACLINT spec:
327 * - On MTIMER device reset, the MTIME register is cleared to zero.
328 * - On MTIMER device reset, the MTIMECMP registers are in unknown state.
329 */
330 RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj);
331
332 /*
333 * Clear mtime register by writing to 0 it.
334 * Pending mtime interrupts will also be cleared at the same time.
335 */
336 riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
337 }
338
339 static const VMStateDescription vmstate_riscv_mtimer = {
340 .name = "riscv_mtimer",
341 .version_id = 3,
342 .minimum_version_id = 3,
343 .fields = (const VMStateField[]) {
344 VMSTATE_UINT64(time_delta, RISCVAclintMTimerState),
345 VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState,
346 num_harts, 0,
347 vmstate_info_uint64, uint64_t),
348 VMSTATE_TIMER_PTR_VARRAY(timers, RISCVAclintMTimerState,
349 num_harts),
350 VMSTATE_END_OF_LIST()
351 }
352 };
353
354 static void riscv_aclint_mtimer_class_init(ObjectClass *klass, const void *data)
355 {
356 DeviceClass *dc = DEVICE_CLASS(klass);
357 dc->realize = riscv_aclint_mtimer_realize;
358 device_class_set_props(dc, riscv_aclint_mtimer_properties);
359 ResettableClass *rc = RESETTABLE_CLASS(klass);
360 rc->phases.enter = riscv_aclint_mtimer_reset_enter;
361 dc->vmsd = &vmstate_riscv_mtimer;
362 }
363
364 static const TypeInfo riscv_aclint_mtimer_info = {
365 .name = TYPE_RISCV_ACLINT_MTIMER,
366 .parent = TYPE_SYS_BUS_DEVICE,
367 .instance_size = sizeof(RISCVAclintMTimerState),
368 .class_init = riscv_aclint_mtimer_class_init,
369 };
370
371 /*
372 * Create ACLINT MTIMER device.
373 */
374 DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
375 uint32_t hartid_base, uint32_t num_harts,
376 uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
377 bool provide_rdtime)
378 {
379 int i;
380 DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER);
381 RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
382
383 assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
384 assert(!(addr & 0x7));
385 assert(!(timecmp_base & 0x7));
386 assert(!(time_base & 0x7));
387
388 qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
389 qdev_prop_set_uint32(dev, "num-harts", num_harts);
390 qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
391 qdev_prop_set_uint32(dev, "time-base", time_base);
392 qdev_prop_set_uint32(dev, "aperture-size", size);
393 qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
394 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
395 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
396
397 for (i = 0; i < num_harts; i++) {
398 CPUState *cpu = cpu_by_arch_id(hartid_base + i);
399 RISCVCPU *rvcpu = RISCV_CPU(cpu);
400 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
401 riscv_aclint_mtimer_callback *cb =
402 g_new0(riscv_aclint_mtimer_callback, 1);
403
404 if (!env) {
405 g_free(cb);
406 continue;
407 }
408 if (provide_rdtime) {
409 riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev);
410 }
411
412 cb->s = s;
413 cb->num = i;
414 s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
415 &riscv_aclint_mtimer_cb, cb);
416 s->timecmp[i] = 0;
417
418 qdev_connect_gpio_out(dev, i,
419 qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
420 }
421
422 return dev;
423 }
424
425 /* CPU read [M|S]SWI register */
426 static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr,
427 unsigned size)
428 {
429 RISCVAclintSwiState *swi = opaque;
430
431 if (addr < (swi->num_harts << 2)) {
432 size_t hartid = swi->hartid_base + (addr >> 2);
433 CPUState *cpu = cpu_by_arch_id(hartid);
434 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
435 if (!env) {
436 qemu_log_mask(LOG_GUEST_ERROR,
437 "aclint-swi: invalid hartid: %zu", hartid);
438 } else if ((addr & 0x3) == 0) {
439 return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0);
440 }
441 }
442
443 qemu_log_mask(LOG_UNIMP,
444 "aclint-swi: invalid read: %08x", (uint32_t)addr);
445 return 0;
446 }
447
448 /* CPU write [M|S]SWI register */
449 static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
450 unsigned size)
451 {
452 RISCVAclintSwiState *swi = opaque;
453
454 if (addr < (swi->num_harts << 2)) {
455 size_t hartid = swi->hartid_base + (addr >> 2);
456 CPUState *cpu = cpu_by_arch_id(hartid);
457 CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
458 if (!env) {
459 qemu_log_mask(LOG_GUEST_ERROR,
460 "aclint-swi: invalid hartid: %zu", hartid);
461 } else if ((addr & 0x3) == 0) {
462 if (value & 0x1) {
463 qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]);
464 } else {
465 if (!swi->sswi) {
466 qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_base]);
467 }
468 }
469 return;
470 }
471 }
472
473 qemu_log_mask(LOG_UNIMP,
474 "aclint-swi: invalid write: %08x", (uint32_t)addr);
475 }
476
477 static const MemoryRegionOps riscv_aclint_swi_ops = {
478 .read = riscv_aclint_swi_read,
479 .write = riscv_aclint_swi_write,
480 .endianness = DEVICE_LITTLE_ENDIAN,
481 .valid = {
482 .min_access_size = 4,
483 .max_access_size = 4
484 }
485 };
486
487 static const Property riscv_aclint_swi_properties[] = {
488 DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
489 DEFINE_PROP_UINT32("num-harts", RISCVAclintSwiState, num_harts, 1),
490 DEFINE_PROP_UINT32("sswi", RISCVAclintSwiState, sswi, false),
491 };
492
493 static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
494 {
495 RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev);
496 int i;
497
498 memory_region_init_io(&swi->mmio, OBJECT(dev), &riscv_aclint_swi_ops, swi,
499 TYPE_RISCV_ACLINT_SWI, RISCV_ACLINT_SWI_SIZE);
500 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio);
501
502 swi->soft_irqs = g_new(qemu_irq, swi->num_harts);
503 qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts);
504
505 /* Claim software interrupt bits */
506 for (i = 0; i < swi->num_harts; i++) {
507 CPUState *cpu_by_hartid = cpu_by_arch_id(swi->hartid_base + i);
508 if (cpu_by_hartid == NULL) {
509 /* Valid for sparse hart layouts - skip this hart ID */
510 continue;
511 }
512 RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid);
513 /* We don't claim mip.SSIP because it is writable by software */
514 if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) {
515 error_report("MSIP already claimed");
516 exit(1);
517 }
518 }
519 }
520
521 static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
522 {
523 /*
524 * According to RISC-V ACLINT spec:
525 * - On MSWI device reset, each MSIP register is cleared to zero.
526 *
527 * p.s. SSWI device reset does nothing since SETSIP register always reads 0.
528 */
529 RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj);
530 int i;
531
532 if (!swi->sswi) {
533 for (i = 0; i < swi->num_harts; i++) {
534 /* Clear MSIP registers by lowering software interrupts. */
535 qemu_irq_lower(swi->soft_irqs[i]);
536 }
537 }
538 }
539
540 static void riscv_aclint_swi_class_init(ObjectClass *klass, const void *data)
541 {
542 DeviceClass *dc = DEVICE_CLASS(klass);
543 dc->realize = riscv_aclint_swi_realize;
544 device_class_set_props(dc, riscv_aclint_swi_properties);
545 ResettableClass *rc = RESETTABLE_CLASS(klass);
546 rc->phases.enter = riscv_aclint_swi_reset_enter;
547 }
548
549 static const TypeInfo riscv_aclint_swi_info = {
550 .name = TYPE_RISCV_ACLINT_SWI,
551 .parent = TYPE_SYS_BUS_DEVICE,
552 .instance_size = sizeof(RISCVAclintSwiState),
553 .class_init = riscv_aclint_swi_class_init,
554 };
555
556 /*
557 * Create ACLINT [M|S]SWI device.
558 */
559 DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
560 uint32_t num_harts, bool sswi)
561 {
562 int i;
563 DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI);
564
565 assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
566 assert(!(addr & 0x3));
567
568 qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
569 qdev_prop_set_uint32(dev, "num-harts", num_harts);
570 qdev_prop_set_uint32(dev, "sswi", sswi ? true : false);
571 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
572 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
573
574 for (i = 0; i < num_harts; i++) {
575 CPUState *cpu = cpu_by_arch_id(hartid_base + i);
576 if (cpu == NULL) {
577 /* Valid for sparse hart layouts - skip this hart ID */
578 continue;
579 }
580 RISCVCPU *rvcpu = RISCV_CPU(cpu);
581
582 qdev_connect_gpio_out(dev, i,
583 qdev_get_gpio_in(DEVICE(rvcpu),
584 (sswi) ? IRQ_S_SOFT : IRQ_M_SOFT));
585 }
586
587 return dev;
588 }
589
590 static void riscv_aclint_register_types(void)
591 {
592 type_register_static(&riscv_aclint_mtimer_info);
593 type_register_static(&riscv_aclint_swi_info);
594 }
595
596 type_init(riscv_aclint_register_types)