From nobody Sun Apr 28 21:35:33 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1643190947260412.4717164455286; Wed, 26 Jan 2022 01:55:47 -0800 (PST) Received: from localhost ([::1]:35908 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nCf1m-0004a2-Fi for importer@patchew.org; Wed, 26 Jan 2022 04:55:46 -0500 Received: from eggs.gnu.org ([209.51.188.92]:38324) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nCf0z-0003mP-8V for qemu-devel@nongnu.org; Wed, 26 Jan 2022 04:54:57 -0500 Received: from [2607:f8b0:4864:20::631] (port=41758 helo=mail-pl1-x631.google.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nCf0x-0004pu-72 for qemu-devel@nongnu.org; Wed, 26 Jan 2022 04:54:56 -0500 Received: by mail-pl1-x631.google.com with SMTP id z5so7999687plg.8 for ; Wed, 26 Jan 2022 01:54:54 -0800 (PST) Received: from hsinchu16.internal.sifive.com (59-124-168-89.hinet-ip.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id v13sm1493212pfi.201.2022.01.26.01.54.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Jan 2022 01:54:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=mot5uTOeoIQ+Uj8dfdkxe2AV8KUdpUNbbNM09aH8+z0=; b=BcWR8ledvtyOYzNF6LjObeY8GKAssjJDFAUGms2rvaH6nr4691XdaJydNp7Cr0Sxks xhB+nuE110WJQ2VPuWcbiwa6XcbH9Z7MHQ9gKHdpo181ja/3q/g5a9dLXjP7Ga6VmghV DWoUH280uVR4u5ujMgmkMtMnEsn8wc/Qg6WiyCA+BMT26H/+hSB3subTSbGQs2X4XY9V bZc5avh0F+IEb/sPyDFfNSJwRoYGd87HTQ/gB2t1766d8D/Q9pVlZXIAHC3hdjK1LIPc 5cmJpfpVYnCwgLnUluthFTXkcM1ASIyMAhI+RguFTqgZzLHamxcETkTHhlZlHz+aWqkT F7ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=mot5uTOeoIQ+Uj8dfdkxe2AV8KUdpUNbbNM09aH8+z0=; b=bi+iG5VPDGQtM0rVHYvS/Q9aH/NhPIR4tDRwOYnYAk3OrCfhcJj1c30V0/j7uXwK4E lfBD+DBNTJAuQtlHtVUm2NuJM81vk7bO+pl11NwFKuMK0dr9PE08BF5ulLk3k2aFN4pM 7RCCOsAXCKDw0j7/LRab+Wa+fZUoszso9Di9gmi41dDLqgrlJzcuZ1uf3OGZyH64qy5T JeLFcgkk4fYv1injg+fCNvw25ryKYGLQdgkNL/lWQCnSvG0Z6tLu8oLeWOR83TYqXUuO q8ouVeIOUNjUcUWbhhPt58zU3FvkRGEJGmsN23pwGA3rzgsYqd/z28Ns09OmmTYZ8Sks aatw== X-Gm-Message-State: AOAM533EBq/pJpY038ubrI9AsQSkGuD8YXfmPBvQvt7vcF1ijGhp/3lN efWmaJXVuA5ukqdEEKWrQUnMVs6A3QRZdQ== X-Google-Smtp-Source: ABdhPJxZMlVduUp267wwHQcYTA23qnJ9//99E7pzh0DXbCSvuGG9FoEsMtkphx4J3zx2UokzFSxbEQ== X-Received: by 2002:a17:902:ecc5:b0:14b:3d4c:450 with SMTP id a5-20020a170902ecc500b0014b3d4c0450mr15938793plh.22.1643190893381; Wed, 26 Jan 2022 01:54:53 -0800 (PST) From: frank.chang@sifive.com To: qemu-devel@nongnu.org Subject: [RFC PATCH] hw/intc: Make RISC-V ACLINT mtime MMIO register writable Date: Wed, 26 Jan 2022 17:54:46 +0800 Message-Id: <20220126095448.2964-1-frank.chang@sifive.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Host-Lookup-Failed: Reverse DNS lookup failed for 2607:f8b0:4864:20::631 (failed) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::631; envelope-from=frank.chang@sifive.com; helo=mail-pl1-x631.google.com X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 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, PDS_HP_HELO_NORDNS=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RDNS_NONE=0.793, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no 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 , qemu-riscv@nongnu.org, Frank Chang , Bin Meng , Palmer Dabbelt , Alistair Francis , LIU Zhiwei Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1643190951472100001 Content-Type: text/plain; charset="utf-8" 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 --- hw/intc/riscv_aclint.c | 58 ++++++++++++++++++++++------------ include/hw/intc/riscv_aclint.h | 1 + target/riscv/cpu.h | 8 ++--- target/riscv/cpu_helper.c | 4 +-- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index f1a5d3d284..ffbe211a3d 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; =20 -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); } =20 +static uint64_t cpu_riscv_read_rtc(void *opaque) +{ + RISCVAclintMTimerState *mtimer =3D opaque; + return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_de= lta; +} + /* * Called when timecmp is written to update the QEMU timer or immediately * trigger timer interrupt if mtimecmp <=3D current timer value. @@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_fr= eq) static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtim= er, RISCVCPU *cpu, int hartid, - uint64_t value, - uint32_t timebase_freq) + uint64_t value) { + uint32_t timebase_freq =3D mtimer->timebase_freq; uint64_t next; uint64_t diff; =20 - uint64_t rtc_r =3D cpu_riscv_read_rtc(timebase_freq); + uint64_t rtc_r =3D cpu_riscv_read_rtc(mtimer); =20 cpu->env.timecmp =3D value; if (cpu->env.timecmp <=3D rtc_r) { @@ -140,10 +146,10 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque= , hwaddr addr, } } else if (addr =3D=3D mtimer->time_base) { /* time_lo */ - return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0xFFFFFFFF; + return cpu_riscv_read_rtc(mtimer) & 0xFFFFFFFF; } else if (addr =3D=3D mtimer->time_base + 4) { /* time_hi */ - return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0xFFFFF= FFF; + return (cpu_riscv_read_rtc(mtimer) >> 32) & 0xFFFFFFFF; } =20 qemu_log_mask(LOG_UNIMP, @@ -156,6 +162,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwa= ddr addr, uint64_t value, unsigned size) { RISCVAclintMTimerState *mtimer =3D opaque; + int i; =20 if (addr >=3D mtimer->timecmp_base && addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) { @@ -170,31 +177,40 @@ static void riscv_aclint_mtimer_write(void *opaque, h= waddr addr, /* timecmp_lo */ uint64_t timecmp_hi =3D env->timecmp >> 32; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hart= id, - timecmp_hi << 32 | (value & 0xFFFFFFFF), - mtimer->timebase_freq); + timecmp_hi << 32 | (value & 0xFFFFFFFF)); return; } else if ((addr & 0x7) =3D=3D 4) { /* timecmp_hi */ uint64_t timecmp_lo =3D env->timecmp; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hart= id, - value << 32 | (timecmp_lo & 0xFFFFFFFF), - mtimer->timebase_freq); + value << 32 | (timecmp_lo & 0xFFFFFFFF)); } else { qemu_log_mask(LOG_UNIMP, "aclint-mtimer: invalid timecmp write: %08x", (uint32_t)addr); } return; - } else if (addr =3D=3D mtimer->time_base) { - /* time_lo */ - qemu_log_mask(LOG_UNIMP, - "aclint-mtimer: time_lo write not implemented"); - return; - } else if (addr =3D=3D mtimer->time_base + 4) { - /* time_hi */ - qemu_log_mask(LOG_UNIMP, - "aclint-mtimer: time_hi write not implemented"); - return; + } else if (addr =3D=3D mtimer->time_base || addr =3D=3D mtimer->time_b= ase + 4) { + uint64_t rtc_r =3D cpu_riscv_read_rtc_raw(mtimer->timebase_freq); + + if (addr =3D=3D mtimer->time_base) { + /* time_lo */ + mtimer->time_delta =3D ((rtc_r & ~0xFFFFFFFFULL) | value) - rt= c_r; + } else { + /* time_hi */ + mtimer->time_delta =3D (value << 32 | (rtc_r & 0xFFFFFFFF)) - = rtc_r; + } + + /* Check if timer interrupt is triggered for each hart. */ + for (i =3D 0; i < mtimer->num_harts; i++) { + CPUState *cpu =3D qemu_get_cpu(mtimer->hartid_base + i); + CPURISCVState *env =3D cpu ? cpu->env_ptr : NULL; + if (!env) { + continue; + } + riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), + i, env->timecmp); + } } =20 qemu_log_mask(LOG_UNIMP, @@ -299,7 +315,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hw= addr 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); } =20 cb->s =3D 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; =20 /*< public >*/ MemoryRegion mmio; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 55635d68d5..46cac9df76 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -249,8 +249,8 @@ struct CPURISCVState { target_ulong mseccfg; =20 /* machine specific rdtime callback */ - uint64_t (*rdtime_fn)(uint32_t); - uint32_t rdtime_fn_arg; + uint64_t (*rdtime_fn)(void *); + void *rdtime_fn_arg; =20 /* True if in debugger mode. */ bool debugger; @@ -413,8 +413,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts); uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_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); #endif void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv); =20 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 327a2c4f1d..73bf1bafa7 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -345,8 +345,8 @@ uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t m= ask, uint32_t value) return old; } =20 -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 =3D fn; env->rdtime_fn_arg =3D arg; --=20 2.31.1