From dc9acc9ce4add37bc5b4437ae9117c318b4f09d4 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Sat, 20 Aug 2022 09:59:58 +0530 Subject: target/riscv: Use official extension names for AIA CSRs The arch review of AIA spec is completed and we now have official extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode AIA CSRs). Refer, section 1.6 of the latest AIA v0.3.1 stable specification at https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf) Based on above, we update QEMU RISC-V to: 1) Have separate config options for Smaia and Ssaia extensions which replace RISCV_FEATURE_AIA in CPU features 2) Not generate AIA INTC compatible string in virt machine Signed-off-by: Anup Patel Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Message-id: 20220820042958.377018-1-apatel@ventanamicro.com Signed-off-by: Alistair Francis --- hw/intc/riscv_imsic.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'hw/intc') diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index 8615e4c..4d4d5b5 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp) /* Force select AIA feature and setup CSR read-modify-write callback */ if (env) { - riscv_set_feature(env, RISCV_FEATURE_AIA); if (!imsic->mmode) { + rcpu->cfg.ext_ssaia = true; riscv_cpu_set_geilen(env, imsic->num_pages - 1); + } else { + rcpu->cfg.ext_smaia = true; } riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S, riscv_imsic_rmw, imsic); -- cgit v1.1 From 7cbcc538f4b3040db1e39a6547efa501a8a44907 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:13:55 -0700 Subject: hw/intc: Move mtimer/mtimecmp to aclint Historically, The mtime/mtimecmp has been part of the CPU because they are per hart entities. However, they actually belong to aclint which is a MMIO device. Move them to the ACLINT device. This also emulates the real hardware more closely. Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Signed-off-by: Atish Patra Message-Id: <20220824221357.41070-2-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- hw/intc/riscv_aclint.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) (limited to 'hw/intc') diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index e7942c4..eee0464 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -32,6 +32,7 @@ #include "hw/intc/riscv_aclint.h" #include "qemu/timer.h" #include "hw/irq.h" +#include "migration/vmstate.h" typedef struct riscv_aclint_mtimer_callback { RISCVAclintMTimerState *s; @@ -65,19 +66,22 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer, uint64_t rtc_r = cpu_riscv_read_rtc(mtimer); - cpu->env.timecmp = value; - if (cpu->env.timecmp <= rtc_r) { + /* Compute the relative hartid w.r.t the socket */ + hartid = hartid - mtimer->hartid_base; + + mtimer->timecmp[hartid] = value; + if (mtimer->timecmp[hartid] <= rtc_r) { /* * If we're setting an MTIMECMP value in the "past", * immediately raise the timer interrupt */ - qemu_irq_raise(mtimer->timer_irqs[hartid - mtimer->hartid_base]); + qemu_irq_raise(mtimer->timer_irqs[hartid]); return; } /* otherwise, set up the future timer interrupt */ - qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]); - diff = cpu->env.timecmp - rtc_r; + qemu_irq_lower(mtimer->timer_irqs[hartid]); + diff = mtimer->timecmp[hartid] - rtc_r; /* back to ns (note args switched in muldiv64) */ uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); @@ -102,7 +106,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer, next = MIN(next, INT64_MAX); } - timer_mod(cpu->env.timer, next); + timer_mod(mtimer->timers[hartid], next); } /* @@ -133,11 +137,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr, "aclint-mtimer: invalid hartid: %zu", hartid); } else if ((addr & 0x7) == 0) { /* timecmp_lo for RV32/RV64 or timecmp for RV64 */ - uint64_t timecmp = env->timecmp; + uint64_t timecmp = mtimer->timecmp[hartid]; return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp; } else if ((addr & 0x7) == 4) { /* timecmp_hi */ - uint64_t timecmp = env->timecmp; + uint64_t timecmp = mtimer->timecmp[hartid]; return (timecmp >> 32) & 0xFFFFFFFF; } else { qemu_log_mask(LOG_UNIMP, @@ -177,7 +181,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 0) { if (size == 4) { /* timecmp_lo for RV32/RV64 */ - uint64_t timecmp_hi = env->timecmp >> 32; + uint64_t timecmp_hi = mtimer->timecmp[hartid] >> 32; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, timecmp_hi << 32 | (value & 0xFFFFFFFF)); } else { @@ -188,7 +192,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 4) { if (size == 4) { /* timecmp_hi for RV32/RV64 */ - uint64_t timecmp_lo = env->timecmp; + uint64_t timecmp_lo = mtimer->timecmp[hartid]; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, value << 32 | (timecmp_lo & 0xFFFFFFFF)); } else { @@ -234,7 +238,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), mtimer->hartid_base + i, - env->timecmp); + mtimer->timecmp[i]); } return; } @@ -284,6 +288,8 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) s->timer_irqs = g_new(qemu_irq, s->num_harts); qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); + s->timers = g_new0(QEMUTimer *, s->num_harts); + s->timecmp = g_new0(uint64_t, s->num_harts); /* Claim timer interrupt bits */ for (i = 0; i < s->num_harts; i++) { RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); @@ -310,6 +316,18 @@ static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type) riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); } +static const VMStateDescription vmstate_riscv_mtimer = { + .name = "riscv_mtimer", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState, + num_harts, 0, + vmstate_info_uint64, uint64_t), + VMSTATE_END_OF_LIST() + } +}; + static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -317,6 +335,7 @@ static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, riscv_aclint_mtimer_properties); ResettableClass *rc = RESETTABLE_CLASS(klass); rc->phases.enter = riscv_aclint_mtimer_reset_enter; + dc->vmsd = &vmstate_riscv_mtimer; } static const TypeInfo riscv_aclint_mtimer_info = { @@ -336,6 +355,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size, { int i; DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER); + RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev); assert(num_harts <= RISCV_ACLINT_MAX_HARTS); assert(!(addr & 0x7)); @@ -366,11 +386,11 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size, riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev); } - cb->s = RISCV_ACLINT_MTIMER(dev); + cb->s = s; cb->num = i; - env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_aclint_mtimer_cb, cb); - env->timecmp = 0; + s->timecmp[i] = 0; qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)); -- cgit v1.1