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