riscv_aclint.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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. #include "qemu/osdep.h"
  24. #include "qapi/error.h"
  25. #include "qemu/error-report.h"
  26. #include "qemu/log.h"
  27. #include "qemu/module.h"
  28. #include "hw/sysbus.h"
  29. #include "target/riscv/cpu.h"
  30. #include "hw/qdev-properties.h"
  31. #include "hw/intc/riscv_aclint.h"
  32. #include "qemu/timer.h"
  33. #include "hw/irq.h"
  34. #include "migration/vmstate.h"
  35. typedef struct riscv_aclint_mtimer_callback {
  36. RISCVAclintMTimerState *s;
  37. int num;
  38. } riscv_aclint_mtimer_callback;
  39. static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
  40. {
  41. return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
  42. timebase_freq, NANOSECONDS_PER_SECOND);
  43. }
  44. static uint64_t cpu_riscv_read_rtc(void *opaque)
  45. {
  46. RISCVAclintMTimerState *mtimer = opaque;
  47. return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_delta;
  48. }
  49. /*
  50. * Called when timecmp is written to update the QEMU timer or immediately
  51. * trigger timer interrupt if mtimecmp <= current timer value.
  52. */
  53. static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
  54. RISCVCPU *cpu,
  55. int hartid,
  56. uint64_t value)
  57. {
  58. uint32_t timebase_freq = mtimer->timebase_freq;
  59. uint64_t next;
  60. uint64_t diff;
  61. uint64_t rtc = cpu_riscv_read_rtc(mtimer);
  62. /* Compute the relative hartid w.r.t the socket */
  63. hartid = hartid - mtimer->hartid_base;
  64. mtimer->timecmp[hartid] = value;
  65. if (mtimer->timecmp[hartid] <= rtc) {
  66. /*
  67. * If we're setting an MTIMECMP value in the "past",
  68. * immediately raise the timer interrupt
  69. */
  70. qemu_irq_raise(mtimer->timer_irqs[hartid]);
  71. return;
  72. }
  73. /* otherwise, set up the future timer interrupt */
  74. qemu_irq_lower(mtimer->timer_irqs[hartid]);
  75. diff = mtimer->timecmp[hartid] - rtc;
  76. /* back to ns (note args switched in muldiv64) */
  77. uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
  78. /*
  79. * check if ns_diff overflowed and check if the addition would potentially
  80. * overflow
  81. */
  82. if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) ||
  83. ns_diff > INT64_MAX) {
  84. next = INT64_MAX;
  85. } else {
  86. /*
  87. * as it is very unlikely qemu_clock_get_ns will return a value
  88. * greater than INT64_MAX, no additional check is needed for an
  89. * unsigned integer overflow.
  90. */
  91. next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff;
  92. /*
  93. * if ns_diff is INT64_MAX next may still be outside the range
  94. * of a signed integer.
  95. */
  96. next = MIN(next, INT64_MAX);
  97. }
  98. timer_mod(mtimer->timers[hartid], next);
  99. }
  100. /*
  101. * Callback used when the timer set using timer_mod expires.
  102. * Should raise the timer interrupt line
  103. */
  104. static void riscv_aclint_mtimer_cb(void *opaque)
  105. {
  106. riscv_aclint_mtimer_callback *state = opaque;
  107. qemu_irq_raise(state->s->timer_irqs[state->num]);
  108. }
  109. /* CPU read MTIMER register */
  110. static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr,
  111. unsigned size)
  112. {
  113. RISCVAclintMTimerState *mtimer = opaque;
  114. if (addr >= mtimer->timecmp_base &&
  115. addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
  116. size_t hartid = mtimer->hartid_base +
  117. ((addr - mtimer->timecmp_base) >> 3);
  118. CPUState *cpu = cpu_by_arch_id(hartid);
  119. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  120. if (!env) {
  121. qemu_log_mask(LOG_GUEST_ERROR,
  122. "aclint-mtimer: invalid hartid: %zu", hartid);
  123. } else if ((addr & 0x7) == 0) {
  124. /* timecmp_lo for RV32/RV64 or timecmp for RV64 */
  125. uint64_t timecmp = mtimer->timecmp[hartid];
  126. return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp;
  127. } else if ((addr & 0x7) == 4) {
  128. /* timecmp_hi */
  129. uint64_t timecmp = mtimer->timecmp[hartid];
  130. return (timecmp >> 32) & 0xFFFFFFFF;
  131. } else {
  132. qemu_log_mask(LOG_UNIMP,
  133. "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
  134. return 0;
  135. }
  136. } else if (addr == mtimer->time_base) {
  137. /* time_lo for RV32/RV64 or timecmp for RV64 */
  138. uint64_t rtc = cpu_riscv_read_rtc(mtimer);
  139. return (size == 4) ? (rtc & 0xFFFFFFFF) : rtc;
  140. } else if (addr == mtimer->time_base + 4) {
  141. /* time_hi */
  142. return (cpu_riscv_read_rtc(mtimer) >> 32) & 0xFFFFFFFF;
  143. }
  144. qemu_log_mask(LOG_UNIMP,
  145. "aclint-mtimer: invalid read: %08x", (uint32_t)addr);
  146. return 0;
  147. }
  148. /* CPU write MTIMER register */
  149. static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr,
  150. uint64_t value, unsigned size)
  151. {
  152. RISCVAclintMTimerState *mtimer = opaque;
  153. int i;
  154. if (addr >= mtimer->timecmp_base &&
  155. addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
  156. size_t hartid = mtimer->hartid_base +
  157. ((addr - mtimer->timecmp_base) >> 3);
  158. CPUState *cpu = cpu_by_arch_id(hartid);
  159. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  160. if (!env) {
  161. qemu_log_mask(LOG_GUEST_ERROR,
  162. "aclint-mtimer: invalid hartid: %zu", hartid);
  163. } else if ((addr & 0x7) == 0) {
  164. if (size == 4) {
  165. /* timecmp_lo for RV32/RV64 */
  166. uint64_t timecmp_hi = mtimer->timecmp[hartid] >> 32;
  167. riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
  168. timecmp_hi << 32 | (value & 0xFFFFFFFF));
  169. } else {
  170. /* timecmp for RV64 */
  171. riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
  172. value);
  173. }
  174. } else if ((addr & 0x7) == 4) {
  175. if (size == 4) {
  176. /* timecmp_hi for RV32/RV64 */
  177. uint64_t timecmp_lo = mtimer->timecmp[hartid];
  178. riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
  179. value << 32 | (timecmp_lo & 0xFFFFFFFF));
  180. } else {
  181. qemu_log_mask(LOG_GUEST_ERROR,
  182. "aclint-mtimer: invalid timecmp_hi write: %08x",
  183. (uint32_t)addr);
  184. }
  185. } else {
  186. qemu_log_mask(LOG_UNIMP,
  187. "aclint-mtimer: invalid timecmp write: %08x",
  188. (uint32_t)addr);
  189. }
  190. return;
  191. } else if (addr == mtimer->time_base || addr == mtimer->time_base + 4) {
  192. uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq);
  193. uint64_t rtc = cpu_riscv_read_rtc(mtimer);
  194. if (addr == mtimer->time_base) {
  195. if (size == 4) {
  196. /* time_lo for RV32/RV64 */
  197. mtimer->time_delta = ((rtc & ~0xFFFFFFFFULL) | value) - rtc_r;
  198. } else {
  199. /* time for RV64 */
  200. mtimer->time_delta = value - rtc_r;
  201. }
  202. } else {
  203. if (size == 4) {
  204. /* time_hi for RV32/RV64 */
  205. mtimer->time_delta = (value << 32 | (rtc & 0xFFFFFFFF)) - rtc_r;
  206. } else {
  207. qemu_log_mask(LOG_GUEST_ERROR,
  208. "aclint-mtimer: invalid time_hi write: %08x",
  209. (uint32_t)addr);
  210. return;
  211. }
  212. }
  213. /* Check if timer interrupt is triggered for each hart. */
  214. for (i = 0; i < mtimer->num_harts; i++) {
  215. CPUState *cpu = cpu_by_arch_id(mtimer->hartid_base + i);
  216. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  217. if (!env) {
  218. continue;
  219. }
  220. riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu),
  221. mtimer->hartid_base + i,
  222. mtimer->timecmp[i]);
  223. }
  224. return;
  225. }
  226. qemu_log_mask(LOG_UNIMP,
  227. "aclint-mtimer: invalid write: %08x", (uint32_t)addr);
  228. }
  229. static const MemoryRegionOps riscv_aclint_mtimer_ops = {
  230. .read = riscv_aclint_mtimer_read,
  231. .write = riscv_aclint_mtimer_write,
  232. .endianness = DEVICE_LITTLE_ENDIAN,
  233. .valid = {
  234. .min_access_size = 4,
  235. .max_access_size = 8
  236. },
  237. .impl = {
  238. .min_access_size = 4,
  239. .max_access_size = 8,
  240. }
  241. };
  242. static const Property riscv_aclint_mtimer_properties[] = {
  243. DEFINE_PROP_UINT32("hartid-base", RISCVAclintMTimerState,
  244. hartid_base, 0),
  245. DEFINE_PROP_UINT32("num-harts", RISCVAclintMTimerState, num_harts, 1),
  246. DEFINE_PROP_UINT32("timecmp-base", RISCVAclintMTimerState,
  247. timecmp_base, RISCV_ACLINT_DEFAULT_MTIMECMP),
  248. DEFINE_PROP_UINT32("time-base", RISCVAclintMTimerState,
  249. time_base, RISCV_ACLINT_DEFAULT_MTIME),
  250. DEFINE_PROP_UINT32("aperture-size", RISCVAclintMTimerState,
  251. aperture_size, RISCV_ACLINT_DEFAULT_MTIMER_SIZE),
  252. DEFINE_PROP_UINT32("timebase-freq", RISCVAclintMTimerState,
  253. timebase_freq, 0),
  254. };
  255. static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp)
  256. {
  257. RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
  258. int i;
  259. memory_region_init_io(&s->mmio, OBJECT(dev), &riscv_aclint_mtimer_ops,
  260. s, TYPE_RISCV_ACLINT_MTIMER, s->aperture_size);
  261. sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
  262. s->timer_irqs = g_new(qemu_irq, s->num_harts);
  263. qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
  264. s->timers = g_new0(QEMUTimer *, s->num_harts);
  265. s->timecmp = g_new0(uint64_t, s->num_harts);
  266. /* Claim timer interrupt bits */
  267. for (i = 0; i < s->num_harts; i++) {
  268. RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(s->hartid_base + i));
  269. if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) {
  270. error_report("MTIP already claimed");
  271. exit(1);
  272. }
  273. }
  274. }
  275. static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
  276. {
  277. /*
  278. * According to RISC-V ACLINT spec:
  279. * - On MTIMER device reset, the MTIME register is cleared to zero.
  280. * - On MTIMER device reset, the MTIMECMP registers are in unknown state.
  281. */
  282. RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj);
  283. /*
  284. * Clear mtime register by writing to 0 it.
  285. * Pending mtime interrupts will also be cleared at the same time.
  286. */
  287. riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
  288. }
  289. static const VMStateDescription vmstate_riscv_mtimer = {
  290. .name = "riscv_mtimer",
  291. .version_id = 1,
  292. .minimum_version_id = 1,
  293. .fields = (const VMStateField[]) {
  294. VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState,
  295. num_harts, 0,
  296. vmstate_info_uint64, uint64_t),
  297. VMSTATE_END_OF_LIST()
  298. }
  299. };
  300. static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
  301. {
  302. DeviceClass *dc = DEVICE_CLASS(klass);
  303. dc->realize = riscv_aclint_mtimer_realize;
  304. device_class_set_props(dc, riscv_aclint_mtimer_properties);
  305. ResettableClass *rc = RESETTABLE_CLASS(klass);
  306. rc->phases.enter = riscv_aclint_mtimer_reset_enter;
  307. dc->vmsd = &vmstate_riscv_mtimer;
  308. }
  309. static const TypeInfo riscv_aclint_mtimer_info = {
  310. .name = TYPE_RISCV_ACLINT_MTIMER,
  311. .parent = TYPE_SYS_BUS_DEVICE,
  312. .instance_size = sizeof(RISCVAclintMTimerState),
  313. .class_init = riscv_aclint_mtimer_class_init,
  314. };
  315. /*
  316. * Create ACLINT MTIMER device.
  317. */
  318. DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
  319. uint32_t hartid_base, uint32_t num_harts,
  320. uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
  321. bool provide_rdtime)
  322. {
  323. int i;
  324. DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER);
  325. RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev);
  326. assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
  327. assert(!(addr & 0x7));
  328. assert(!(timecmp_base & 0x7));
  329. assert(!(time_base & 0x7));
  330. qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
  331. qdev_prop_set_uint32(dev, "num-harts", num_harts);
  332. qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base);
  333. qdev_prop_set_uint32(dev, "time-base", time_base);
  334. qdev_prop_set_uint32(dev, "aperture-size", size);
  335. qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq);
  336. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  337. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
  338. for (i = 0; i < num_harts; i++) {
  339. CPUState *cpu = cpu_by_arch_id(hartid_base + i);
  340. RISCVCPU *rvcpu = RISCV_CPU(cpu);
  341. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  342. riscv_aclint_mtimer_callback *cb =
  343. g_new0(riscv_aclint_mtimer_callback, 1);
  344. if (!env) {
  345. g_free(cb);
  346. continue;
  347. }
  348. if (provide_rdtime) {
  349. riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev);
  350. }
  351. cb->s = s;
  352. cb->num = i;
  353. s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL,
  354. &riscv_aclint_mtimer_cb, cb);
  355. s->timecmp[i] = 0;
  356. qdev_connect_gpio_out(dev, i,
  357. qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER));
  358. }
  359. return dev;
  360. }
  361. /* CPU read [M|S]SWI register */
  362. static uint64_t riscv_aclint_swi_read(void *opaque, hwaddr addr,
  363. unsigned size)
  364. {
  365. RISCVAclintSwiState *swi = opaque;
  366. if (addr < (swi->num_harts << 2)) {
  367. size_t hartid = swi->hartid_base + (addr >> 2);
  368. CPUState *cpu = cpu_by_arch_id(hartid);
  369. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  370. if (!env) {
  371. qemu_log_mask(LOG_GUEST_ERROR,
  372. "aclint-swi: invalid hartid: %zu", hartid);
  373. } else if ((addr & 0x3) == 0) {
  374. return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0);
  375. }
  376. }
  377. qemu_log_mask(LOG_UNIMP,
  378. "aclint-swi: invalid read: %08x", (uint32_t)addr);
  379. return 0;
  380. }
  381. /* CPU write [M|S]SWI register */
  382. static void riscv_aclint_swi_write(void *opaque, hwaddr addr, uint64_t value,
  383. unsigned size)
  384. {
  385. RISCVAclintSwiState *swi = opaque;
  386. if (addr < (swi->num_harts << 2)) {
  387. size_t hartid = swi->hartid_base + (addr >> 2);
  388. CPUState *cpu = cpu_by_arch_id(hartid);
  389. CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
  390. if (!env) {
  391. qemu_log_mask(LOG_GUEST_ERROR,
  392. "aclint-swi: invalid hartid: %zu", hartid);
  393. } else if ((addr & 0x3) == 0) {
  394. if (value & 0x1) {
  395. qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]);
  396. } else {
  397. if (!swi->sswi) {
  398. qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_base]);
  399. }
  400. }
  401. return;
  402. }
  403. }
  404. qemu_log_mask(LOG_UNIMP,
  405. "aclint-swi: invalid write: %08x", (uint32_t)addr);
  406. }
  407. static const MemoryRegionOps riscv_aclint_swi_ops = {
  408. .read = riscv_aclint_swi_read,
  409. .write = riscv_aclint_swi_write,
  410. .endianness = DEVICE_LITTLE_ENDIAN,
  411. .valid = {
  412. .min_access_size = 4,
  413. .max_access_size = 4
  414. }
  415. };
  416. static const Property riscv_aclint_swi_properties[] = {
  417. DEFINE_PROP_UINT32("hartid-base", RISCVAclintSwiState, hartid_base, 0),
  418. DEFINE_PROP_UINT32("num-harts", RISCVAclintSwiState, num_harts, 1),
  419. DEFINE_PROP_UINT32("sswi", RISCVAclintSwiState, sswi, false),
  420. };
  421. static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp)
  422. {
  423. RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(dev);
  424. int i;
  425. memory_region_init_io(&swi->mmio, OBJECT(dev), &riscv_aclint_swi_ops, swi,
  426. TYPE_RISCV_ACLINT_SWI, RISCV_ACLINT_SWI_SIZE);
  427. sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio);
  428. swi->soft_irqs = g_new(qemu_irq, swi->num_harts);
  429. qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts);
  430. /* Claim software interrupt bits */
  431. for (i = 0; i < swi->num_harts; i++) {
  432. RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i));
  433. /* We don't claim mip.SSIP because it is writable by software */
  434. if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) {
  435. error_report("MSIP already claimed");
  436. exit(1);
  437. }
  438. }
  439. }
  440. static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
  441. {
  442. /*
  443. * According to RISC-V ACLINT spec:
  444. * - On MSWI device reset, each MSIP register is cleared to zero.
  445. *
  446. * p.s. SSWI device reset does nothing since SETSIP register always reads 0.
  447. */
  448. RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj);
  449. int i;
  450. if (!swi->sswi) {
  451. for (i = 0; i < swi->num_harts; i++) {
  452. /* Clear MSIP registers by lowering software interrupts. */
  453. qemu_irq_lower(swi->soft_irqs[i]);
  454. }
  455. }
  456. }
  457. static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
  458. {
  459. DeviceClass *dc = DEVICE_CLASS(klass);
  460. dc->realize = riscv_aclint_swi_realize;
  461. device_class_set_props(dc, riscv_aclint_swi_properties);
  462. ResettableClass *rc = RESETTABLE_CLASS(klass);
  463. rc->phases.enter = riscv_aclint_swi_reset_enter;
  464. }
  465. static const TypeInfo riscv_aclint_swi_info = {
  466. .name = TYPE_RISCV_ACLINT_SWI,
  467. .parent = TYPE_SYS_BUS_DEVICE,
  468. .instance_size = sizeof(RISCVAclintSwiState),
  469. .class_init = riscv_aclint_swi_class_init,
  470. };
  471. /*
  472. * Create ACLINT [M|S]SWI device.
  473. */
  474. DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
  475. uint32_t num_harts, bool sswi)
  476. {
  477. int i;
  478. DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_SWI);
  479. assert(num_harts <= RISCV_ACLINT_MAX_HARTS);
  480. assert(!(addr & 0x3));
  481. qdev_prop_set_uint32(dev, "hartid-base", hartid_base);
  482. qdev_prop_set_uint32(dev, "num-harts", num_harts);
  483. qdev_prop_set_uint32(dev, "sswi", sswi ? true : false);
  484. sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  485. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
  486. for (i = 0; i < num_harts; i++) {
  487. CPUState *cpu = cpu_by_arch_id(hartid_base + i);
  488. RISCVCPU *rvcpu = RISCV_CPU(cpu);
  489. qdev_connect_gpio_out(dev, i,
  490. qdev_get_gpio_in(DEVICE(rvcpu),
  491. (sswi) ? IRQ_S_SOFT : IRQ_M_SOFT));
  492. }
  493. return dev;
  494. }
  495. static void riscv_aclint_register_types(void)
  496. {
  497. type_register_static(&riscv_aclint_mtimer_info);
  498. type_register_static(&riscv_aclint_swi_info);
  499. }
  500. type_init(riscv_aclint_register_types)