From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 065E8C433F5 for ; Wed, 20 Apr 2022 07:57:25 +0000 (UTC) Received: from localhost ([::1]:43634 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nh5DH-0002uj-Tb for qemu-devel@archiver.kernel.org; Wed, 20 Apr 2022 03:57:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57176) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nh59l-0007wR-GI for qemu-devel@nongnu.org; Wed, 20 Apr 2022 03:53:45 -0400 Received: from mail-ed1-x531.google.com ([2a00:1450:4864:20::531]:38910) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nh59i-0007M9-DN for qemu-devel@nongnu.org; Wed, 20 Apr 2022 03:53:45 -0400 Received: by mail-ed1-x531.google.com with SMTP id z99so1190152ede.5 for ; Wed, 20 Apr 2022 00:53:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=f4HFnli/JzkEvfYGogWMd39LsbtpgKBiIybEj140pYQ=; b=el3LcRGruM+xxmafiprasrkBHuv070yGhoJvHhdIrP/CI5ayZazK+tcowf7xUxvSFS ctWiLpVpM1rv8ZImFzzfzbhgDqr/JCziV5eLh2jzURFL77LxGpeWUt3KKJpXdXFWDCgW A0zKHg0piGLqCH2GaYfpur8v7oLa3gNlk4W09vuerfT2epm1uAmDmCQkq1+6LVASUO69 xr2gqGflHDO8TL9HfFuYhRI/o96ayTIojvH/f6wZccw5HiLouwdFHpmO1oGFyv56zcfG I31S8KyPriUj9PK8sCtLoPXYEfCR55+F8VByJXQE9Y0FcNA3rUE9+clTczGOfDlt223r gvZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=f4HFnli/JzkEvfYGogWMd39LsbtpgKBiIybEj140pYQ=; b=vcB+3P4wkwzm72G6Ja+k09/k87nD5Rt6Ld/n+ze9ztwcSTONsirEc+iE0AZbDXrB/u TyoRrEzOJj2sJ4l/TdSIXR8r65snTp9vWy9FnmRF5DzXRhUPm77Um7KIAgfaEL8WQ5uE NeIgkoMkk0YlPf3JFh3Wg3IEcai3FtFgEHBuMwPPnLnbwIHSTr6GjJdb0ED7rNIZinH7 n+nAGHJqG6b9EmYU/hkqbYIEYXG8fZc8CemExobdKfXSd981r53LUia7b8yg5B7gS7tC /XH9m5jb0x39djed0zLOkvTkRsEMLq9VdqNS8GBDL42ErHcxxMGf38r7IhcxLfcWADpj DmXg== X-Gm-Message-State: AOAM533E4ZfFGPUkZqf3E/BI3ljnApfHUWVP2sNZB1YNYvv8KTPWQsFv XLk0fvS17X145r09lOUWsgJESGKzWNRJ6ArwA1/4pQ== X-Google-Smtp-Source: ABdhPJyMh8a12ux9aZLyRiVUCqjmqQpZizcq2CtYHm+OunGNjVAi6Mlogq9A10xVAfZpgF26uUtvo5URoszkwAeZ5/s= X-Received: by 2002:aa7:d553:0:b0:416:4dfc:126d with SMTP id u19-20020aa7d553000000b004164dfc126dmr21464227edr.213.1650441220580; Wed, 20 Apr 2022 00:53:40 -0700 (PDT) MIME-Version: 1.0 References: <20220419090848.9018-1-frank.chang@sifive.com> <20220419090848.9018-4-frank.chang@sifive.com> In-Reply-To: From: Frank Chang Date: Wed, 20 Apr 2022 15:53:29 +0800 Message-ID: Subject: Re: [PATCH v3 3/4] hw/intc: Make RISC-V ACLINT mtime MMIO register writable To: Alistair Francis Content-Type: multipart/alternative; boundary="000000000000ad018505dd114ac8" Received-SPF: pass client-ip=2a00:1450:4864:20::531; envelope-from=frank.chang@sifive.com; helo=mail-ed1-x531.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anup Patel , "open list:RISC-V" , Bin Meng , "qemu-devel@nongnu.org Developers" , Jim Shu , Palmer Dabbelt , Alistair Francis , LIU Zhiwei Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" --000000000000ad018505dd114ac8 Content-Type: text/plain; charset="UTF-8" On Wed, Apr 20, 2022 at 3:42 PM Alistair Francis wrote: > On Tue, Apr 19, 2022 at 7:10 PM wrote: > > > > From: Frank Chang > > > > RISC-V privilege spec defines that mtime is exposed as a memory-mapped > > machine-mode read-write register. However, as QEMU uses host monotonic > > timer as timer source, this makes mtime to be read-only in RISC-V > > ACLINT. > > > > This patch makes mtime to be writable by recording the time delta value > > between the mtime value to be written and the timer value at the time > > mtime is written. Time delta value is then added back whenever the timer > > value is retrieved. > > > > Signed-off-by: Frank Chang > > Reviewed-by: Jim Shu > > --- > > hw/intc/riscv_aclint.c | 71 ++++++++++++++++++++++++---------- > > include/hw/intc/riscv_aclint.h | 1 + > > target/riscv/cpu.h | 8 ++-- > > target/riscv/cpu_helper.c | 4 +- > > 4 files changed, 57 insertions(+), 27 deletions(-) > > > > diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c > > index ad3c49706f..ad7ccf96cd 100644 > > --- a/hw/intc/riscv_aclint.c > > +++ b/hw/intc/riscv_aclint.c > > @@ -38,12 +38,18 @@ typedef struct riscv_aclint_mtimer_callback { > > int num; > > } riscv_aclint_mtimer_callback; > > > > -static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) > > +static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq) > > { > > return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), > > timebase_freq, NANOSECONDS_PER_SECOND); > > } > > > > +static uint64_t cpu_riscv_read_rtc(void *opaque) > > +{ > > + RISCVAclintMTimerState *mtimer = opaque; > > + return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + > mtimer->time_delta; > > +} > > + > > /* > > * Called when timecmp is written to update the QEMU timer or > immediately > > * trigger timer interrupt if mtimecmp <= current timer value. > > @@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t > timebase_freq) > > static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState > *mtimer, > > RISCVCPU *cpu, > > int hartid, > > - uint64_t value, > > - uint32_t timebase_freq) > > + uint64_t value) > > { > > + uint32_t timebase_freq = mtimer->timebase_freq; > > uint64_t next; > > uint64_t diff; > > > > - uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq); > > + uint64_t rtc_r = cpu_riscv_read_rtc(mtimer); > > > > cpu->env.timecmp = value; > > if (cpu->env.timecmp <= rtc_r) { > > @@ -140,11 +146,11 @@ static uint64_t riscv_aclint_mtimer_read(void > *opaque, hwaddr addr, > > } > > } else if (addr == mtimer->time_base) { > > /* time_lo for RV32/RV64 or timecmp for RV64 */ > > - uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq); > > + uint64_t rtc = cpu_riscv_read_rtc(mtimer); > > return (size == 4) ? (rtc & 0xFFFFFFFF) : rtc; > > } else if (addr == mtimer->time_base + 4) { > > /* time_hi */ > > - return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & > 0xFFFFFFFF; > > + return (cpu_riscv_read_rtc(mtimer) >> 32) & 0xFFFFFFFF; > > } > > > > qemu_log_mask(LOG_UNIMP, > > @@ -157,6 +163,7 @@ static void riscv_aclint_mtimer_write(void *opaque, > hwaddr addr, > > uint64_t value, unsigned size) > > { > > RISCVAclintMTimerState *mtimer = opaque; > > + int i; > > > > if (addr >= mtimer->timecmp_base && > > addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) { > > @@ -172,20 +179,18 @@ static void riscv_aclint_mtimer_write(void > *opaque, hwaddr addr, > > /* timecmp_lo for RV32/RV64 */ > > uint64_t timecmp_hi = env->timecmp >> 32; > > riscv_aclint_mtimer_write_timecmp(mtimer, > RISCV_CPU(cpu), hartid, > > - timecmp_hi << 32 | (value & 0xFFFFFFFF), > > - mtimer->timebase_freq); > > + timecmp_hi << 32 | (value & 0xFFFFFFFF)); > > } else { > > /* timecmp for RV64 */ > > riscv_aclint_mtimer_write_timecmp(mtimer, > RISCV_CPU(cpu), hartid, > > - value, > mtimer->timebase_freq); > > + value); > > } > > } else if ((addr & 0x7) == 4) { > > if (size == 4) { > > /* timecmp_hi for RV32/RV64 */ > > uint64_t timecmp_lo = env->timecmp; > > riscv_aclint_mtimer_write_timecmp(mtimer, > RISCV_CPU(cpu), hartid, > > - value << 32 | (timecmp_lo & 0xFFFFFFFF), > > - mtimer->timebase_freq); > > + value << 32 | (timecmp_lo & 0xFFFFFFFF)); > > } else { > > qemu_log_mask(LOG_UNIMP, > > "aclint-mtimer: invalid timecmp_hi write: > %08x", > > @@ -197,15 +202,39 @@ static void riscv_aclint_mtimer_write(void > *opaque, hwaddr addr, > > (uint32_t)addr); > > } > > return; > > - } else if (addr == mtimer->time_base) { > > - /* time_lo */ > > - qemu_log_mask(LOG_UNIMP, > > - "aclint-mtimer: time_lo write not implemented"); > > - return; > > - } else if (addr == mtimer->time_base + 4) { > > - /* time_hi */ > > - qemu_log_mask(LOG_UNIMP, > > - "aclint-mtimer: time_hi write not implemented"); > > + } else if (addr == mtimer->time_base || addr == mtimer->time_base + > 4) { > > + uint64_t rtc_r = cpu_riscv_read_rtc_raw(mtimer->timebase_freq); > > + > > + if (addr == mtimer->time_base) { > > + if (size == 4) { > > + /* time_lo for RV32/RV64 */ > > + mtimer->time_delta = ((rtc_r & ~0xFFFFFFFFULL) | value) > - rtc_r; > > + } else { > > + /* time for RV64 */ > > + mtimer->time_delta = value - rtc_r; > > + } > > + } else { > > + if (size == 4) { > > + /* time_hi for RV32/RV64 */ > > + mtimer->time_delta = (value << 32 | (rtc_r & > 0xFFFFFFFF)) - rtc_r; > > + } else { > > + qemu_log_mask(LOG_UNIMP, > > This should be a guest error instead > Thanks, I'll fix this in the next version patchset. Regards, Frank Chang > > Otherwise: > > Reviewed-by: Alistair Francis > > Alistair > > > + "aclint-mtimer: invalid time_hi write: > %08x", > > + (uint32_t)addr); > > + return; > > + } > > + } > > + > > + /* Check if timer interrupt is triggered for each hart. */ > > + for (i = 0; i < mtimer->num_harts; i++) { > > + CPUState *cpu = qemu_get_cpu(mtimer->hartid_base + i); > > + CPURISCVState *env = cpu ? cpu->env_ptr : NULL; > > + if (!env) { > > + continue; > > + } > > + riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), > > + i, env->timecmp); > > + } > > return; > > } > > > > @@ -315,7 +344,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, > hwaddr size, > > continue; > > } > > if (provide_rdtime) { > > - riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, > timebase_freq); > > + riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev); > > } > > > > cb->s = RISCV_ACLINT_MTIMER(dev); > > diff --git a/include/hw/intc/riscv_aclint.h > b/include/hw/intc/riscv_aclint.h > > index 229bd08d25..26d4048687 100644 > > --- a/include/hw/intc/riscv_aclint.h > > +++ b/include/hw/intc/riscv_aclint.h > > @@ -31,6 +31,7 @@ > > typedef struct RISCVAclintMTimerState { > > /*< private >*/ > > SysBusDevice parent_obj; > > + uint64_t time_delta; > > > > /*< public >*/ > > MemoryRegion mmio; > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > > index 249fce4c3b..0cb7c2a05a 100644 > > --- a/target/riscv/cpu.h > > +++ b/target/riscv/cpu.h > > @@ -286,8 +286,8 @@ struct CPUArchState { > > type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM]; > > > > /* machine specific rdtime callback */ > > - uint64_t (*rdtime_fn)(uint32_t); > > - uint32_t rdtime_fn_arg; > > + uint64_t (*rdtime_fn)(void *); > > + void *rdtime_fn_arg; > > > > /* machine specific AIA ireg read-modify-write callback */ > > #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \ > > @@ -505,8 +505,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState > *env); > > int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); > > uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t > value); > > #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip > value */ > > -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t > (*fn)(uint32_t), > > - uint32_t arg); > > +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), > > + void *arg); > > void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv, > > int (*rmw_fn)(void *arg, > > target_ulong reg, > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > > index b5bbe6fc39..51a3d96a66 100644 > > --- a/target/riscv/cpu_helper.c > > +++ b/target/riscv/cpu_helper.c > > @@ -632,8 +632,8 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, > uint64_t mask, uint64_t value) > > return old; > > } > > > > -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t > (*fn)(uint32_t), > > - uint32_t arg) > > +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), > > + void *arg) > > { > > env->rdtime_fn = fn; > > env->rdtime_fn_arg = arg; > > -- > > 2.35.1 > > > > > --000000000000ad018505dd114ac8 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Wed, Apr 20, 2022 at 3:42 PM Alistair = Francis <alistair23@gmail.com> wrote:
On Tue, Apr 19, 2022 at 7:10 PM <frank.chang@sifive.com>= wrote:
>
> From: Frank Chang <frank.chang@sifive.com>
>
> RISC-V privilege spec defines that mtime is exposed as a memory-mapped=
> machine-mode read-write register. However, as QEMU uses host monotonic=
> timer as timer source, this makes mtime to be read-only in RISC-V
> ACLINT.
>
> This patch makes mtime to be writable by recording the time delta valu= e
> between the mtime value to be written and the timer value at the time<= br> > mtime is written. Time delta value is then added back whenever the tim= er
> value is retrieved.
>
> Signed-off-by: Frank Chang <frank.chang@sifive.com>
> Reviewed-by: Jim Shu <jim.shu@sifive.com>
> ---
>=C2=A0 hw/intc/riscv_aclint.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| 71 +++= +++++++++++++++++++++----------
>=C2=A0 include/hw/intc/riscv_aclint.h |=C2=A0 1 +
>=C2=A0 target/riscv/cpu.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0|=C2=A0 8 ++--
>=C2=A0 target/riscv/cpu_helper.c=C2=A0 =C2=A0 =C2=A0 |=C2=A0 4 +-
>=C2=A0 4 files changed, 57 insertions(+), 27 deletions(-)
>
> diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
> index ad3c49706f..ad7ccf96cd 100644
> --- a/hw/intc/riscv_aclint.c
> +++ b/hw/intc/riscv_aclint.c
> @@ -38,12 +38,18 @@ typedef struct riscv_aclint_mtimer_callback {
>=C2=A0 =C2=A0 =C2=A0 int num;
>=C2=A0 } riscv_aclint_mtimer_callback;
>
> -static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
> +static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
>=C2=A0 {
>=C2=A0 =C2=A0 =C2=A0 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTU= AL),
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 timebase_freq, NANOSECONDS_PER_SECON= D);
>=C2=A0 }
>
> +static uint64_t cpu_riscv_read_rtc(void *opaque)
> +{
> +=C2=A0 =C2=A0 RISCVAclintMTimerState *mtimer =3D opaque;
> +=C2=A0 =C2=A0 return cpu_riscv_read_rtc_raw(mtimer->timebase_freq)= + mtimer->time_delta;
> +}
> +
>=C2=A0 /*
>=C2=A0 =C2=A0* Called when timecmp is written to update the QEMU timer = or immediately
>=C2=A0 =C2=A0* trigger timer interrupt if mtimecmp <=3D current time= r value.
> @@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timeba= se_freq)
>=C2=A0 static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerS= tate *mtimer,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 RISCVCPU *cpu,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 int hartid,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 uint64_t value,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 uint32_t timebase_freq)
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 uint64_t value)
>=C2=A0 {
> +=C2=A0 =C2=A0 uint32_t timebase_freq =3D mtimer->timebase_freq; >=C2=A0 =C2=A0 =C2=A0 uint64_t next;
>=C2=A0 =C2=A0 =C2=A0 uint64_t diff;
>
> -=C2=A0 =C2=A0 uint64_t rtc_r =3D cpu_riscv_read_rtc(timebase_freq); > +=C2=A0 =C2=A0 uint64_t rtc_r =3D cpu_riscv_read_rtc(mtimer);
>
>=C2=A0 =C2=A0 =C2=A0 cpu->env.timecmp =3D value;
>=C2=A0 =C2=A0 =C2=A0 if (cpu->env.timecmp <=3D rtc_r) {
> @@ -140,11 +146,11 @@ static uint64_t riscv_aclint_mtimer_read(void *o= paque, hwaddr addr,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 } else if (addr =3D=3D mtimer->time_base) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_lo for RV32/RV64 or timecmp = for RV64 */
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t rtc =3D cpu_riscv_read_rtc(mtime= r->timebase_freq);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t rtc =3D cpu_riscv_read_rtc(mtime= r);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return (size =3D=3D 4) ? (rtc & = 0xFFFFFFFF) : rtc;
>=C2=A0 =C2=A0 =C2=A0 } else if (addr =3D=3D mtimer->time_base + 4) {=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_hi */
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (cpu_riscv_read_rtc(mtimer->tim= ebase_freq) >> 32) & 0xFFFFFFFF;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (cpu_riscv_read_rtc(mtimer) >&g= t; 32) & 0xFFFFFFFF;
>=C2=A0 =C2=A0 =C2=A0 }
>
>=C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_UNIMP,
> @@ -157,6 +163,7 @@ static void riscv_aclint_mtimer_write(void *opaque= , hwaddr addr,
>=C2=A0 =C2=A0 =C2=A0 uint64_t value, unsigned size)
>=C2=A0 {
>=C2=A0 =C2=A0 =C2=A0 RISCVAclintMTimerState *mtimer =3D opaque;
> +=C2=A0 =C2=A0 int i;
>
>=C2=A0 =C2=A0 =C2=A0 if (addr >=3D mtimer->timecmp_base &&= ;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 addr < (mtimer->timecmp_base += (mtimer->num_harts << 3))) {
> @@ -172,20 +179,18 @@ static void riscv_aclint_mtimer_write(void *opaq= ue, hwaddr addr,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* timec= mp_lo for RV32/RV64 */
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t= timecmp_hi =3D env->timecmp >> 32;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_ac= lint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= timecmp_hi << 32 | (value & 0xFFFFFFFF),
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= mtimer->timebase_freq);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= timecmp_hi << 32 | (value & 0xFFFFFFFF));
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* timec= mp for RV64 */
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_ac= lint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value, mtimer->timebase_freq);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else if ((addr & 0x7) =3D=3D 4= ) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (size =3D=3D 4) { >=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* timec= mp_hi for RV32/RV64 */
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t= timecmp_lo =3D env->timecmp;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_ac= lint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= value << 32 | (timecmp_lo & 0xFFFFFFFF),
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= mtimer->timebase_freq);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= value << 32 | (timecmp_lo & 0xFFFFFFFF));
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log= _mask(LOG_UNIMP,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "aclint-mtimer: invalid time= cmp_hi write: %08x",
> @@ -197,15 +202,39 @@ static void riscv_aclint_mtimer_write(void *opaq= ue, hwaddr addr,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 (uint32_t)addr);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
> -=C2=A0 =C2=A0 } else if (addr =3D=3D mtimer->time_base) {
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_lo */
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_UNIMP,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 "aclint-mtimer: time_lo write not implemented");
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
> -=C2=A0 =C2=A0 } else if (addr =3D=3D mtimer->time_base + 4) {
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_hi */
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask(LOG_UNIMP,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 "aclint-mtimer: time_hi write not implemented");
> +=C2=A0 =C2=A0 } else if (addr =3D=3D mtimer->time_base || addr =3D= =3D mtimer->time_base + 4) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint64_t rtc_r =3D cpu_riscv_read_rtc_raw= (mtimer->timebase_freq);
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (addr =3D=3D mtimer->time_base) { > +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (size =3D=3D 4) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_lo fo= r RV32/RV64 */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mtimer->ti= me_delta =3D ((rtc_r & ~0xFFFFFFFFULL) | value) - rtc_r;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time for R= V64 */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mtimer->ti= me_delta =3D value - rtc_r;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (size =3D=3D 4) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* time_hi fo= r RV32/RV64 */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 mtimer->ti= me_delta =3D (value << 32 | (rtc_r & 0xFFFFFFFF)) - rtc_r;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 qemu_log_mask= (LOG_UNIMP,

This should be a guest error instead

Th= anks, I'll fix this in the next version patchset.

<= div>Regards,
Frank Chang
=C2=A0

Otherwise:

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "aclint-mtimer: invalid time_hi wr= ite: %08x",
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (uint32_t)addr);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Check if timer interrupt is triggered = for each hart. */
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (i =3D 0; i < mtimer->num_harts= ; i++) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPUState *cpu =3D qemu_get_= cpu(mtimer->hartid_base + i);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPURISCVState *env =3D cpu = ? cpu->env_ptr : NULL;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (!env) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_aclint_mtimer_write_t= imecmp(mtimer, RISCV_CPU(cpu),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 i, env->timecmp);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
>=C2=A0 =C2=A0 =C2=A0 }
>
> @@ -315,7 +344,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr add= r, hwaddr size,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (provide_rdtime) {
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_cpu_set_rdtime_fn(env= , cpu_riscv_read_rtc, timebase_freq);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 riscv_cpu_set_rdtime_fn(env= , cpu_riscv_read_rtc, dev);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 cb->s =3D RISCV_ACLINT_MTIMER(dev= );
> diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_ac= lint.h
> index 229bd08d25..26d4048687 100644
> --- a/include/hw/intc/riscv_aclint.h
> +++ b/include/hw/intc/riscv_aclint.h
> @@ -31,6 +31,7 @@
>=C2=A0 typedef struct RISCVAclintMTimerState {
>=C2=A0 =C2=A0 =C2=A0 /*< private >*/
>=C2=A0 =C2=A0 =C2=A0 SysBusDevice parent_obj;
> +=C2=A0 =C2=A0 uint64_t time_delta;
>
>=C2=A0 =C2=A0 =C2=A0 /*< public >*/
>=C2=A0 =C2=A0 =C2=A0 MemoryRegion mmio;
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 249fce4c3b..0cb7c2a05a 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -286,8 +286,8 @@ struct CPUArchState {
>=C2=A0 =C2=A0 =C2=A0 type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM];
>
>=C2=A0 =C2=A0 =C2=A0 /* machine specific rdtime callback */
> -=C2=A0 =C2=A0 uint64_t (*rdtime_fn)(uint32_t);
> -=C2=A0 =C2=A0 uint32_t rdtime_fn_arg;
> +=C2=A0 =C2=A0 uint64_t (*rdtime_fn)(void *);
> +=C2=A0 =C2=A0 void *rdtime_fn_arg;
>
>=C2=A0 =C2=A0 =C2=A0 /* machine specific AIA ireg read-modify-write cal= lback */
>=C2=A0 #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \=
> @@ -505,8 +505,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState = *env);
>=C2=A0 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupt= s);
>=C2=A0 uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint= 64_t value);
>=C2=A0 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_= mip value */
> -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint3= 2_t),
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0uint32_t arg);
> +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void = *),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0void *arg);
>=C2=A0 void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t = priv,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int (*rmw_fn)= (void *arg,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target_ulong reg,
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index b5bbe6fc39..51a3d96a66 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -632,8 +632,8 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint6= 4_t mask, uint64_t value)
>=C2=A0 =C2=A0 =C2=A0 return old;
>=C2=A0 }
>
> -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint3= 2_t),
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0uint32_t arg)
> +void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void = *),
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0void *arg)
>=C2=A0 {
>=C2=A0 =C2=A0 =C2=A0 env->rdtime_fn =3D fn;
>=C2=A0 =C2=A0 =C2=A0 env->rdtime_fn_arg =3D arg;
> --
> 2.35.1
>
>
--000000000000ad018505dd114ac8--