From nobody Mon Feb 9 13:59:32 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1559068407; cv=none; d=zoho.com; s=zohoarc; b=gcZOU3BuXTm6u2ZccGONQ1yBsOw2APdH98WBxt+PtWEnhDXDDodTV7YPsb8AJG7M8nUp3dj8wj8N/f6XtXa+D1hNFH7G/SbzKxtW7DrQLfdKS5lnOeIDDXu+XYpnp1R7Y7ucYC1zvLwoImUv6xuXjqFg8S79Q0BkQfL/k0GwVZE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559068407; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To:ARC-Authentication-Results; bh=nEcuwIlVHsRxXcVicnYj6GVZmMZCKRdLrLrqRXh7teE=; b=Arwb9f0nV/E7FvJY+UNMJXDjjKo+hE3H5bUlvowPbmH2UX9R0NsnOQJeK6L3yr0rJGj5qxIBryntetYr9dnH7NCQ+KzwCyf56hWToVArwtS8EYh9MmO21uBx099i6V7Mv9yFYN72gBn0Hl+08XWxkB1pTBPA9OjvGj9roFl4E6E= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=pass (zoho.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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1559068406980331.80113232623444; Tue, 28 May 2019 11:33:26 -0700 (PDT) Received: from localhost ([127.0.0.1]:40865 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVguW-0002C2-O3 for importer@patchew.org; Tue, 28 May 2019 14:33:20 -0400 Received: from eggs.gnu.org ([209.51.188.92]:53784) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hVgt2-0001S2-2w for qemu-devel@nongnu.org; Tue, 28 May 2019 14:31:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hVgsz-0006IU-0s for qemu-devel@nongnu.org; Tue, 28 May 2019 14:31:47 -0400 Received: from rs224.mailgun.us ([209.61.151.224]:23312) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hVgsp-000666-K5 for qemu-devel@nongnu.org; Tue, 28 May 2019 14:31:40 -0400 Received: from localhost.localdomain (cpe-174-100-208-63.neo.res.rr.com [174.100.208.63]) by mxa.mailgun.org with ESMTP id 5ced7e7a.7f4b0c0727f0-smtp-out-n03; Tue, 28 May 2019 18:31:22 -0000 (UTC) DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=fintelia.io; q=dns/txt; s=pic; t=1559068285; h=Content-Transfer-Encoding: MIME-Version: Message-Id: Date: Subject: Cc: To: From: Sender; bh=nEcuwIlVHsRxXcVicnYj6GVZmMZCKRdLrLrqRXh7teE=; b=7U4ulSj3Hsb9P9um5dNOfi8y9gm9OcyXJlNFb/5ygAdB1SfgU2zuLh8NFnhD0L1VvFvEmLpX qzKKByBJ0tKr73Q8kxojaiNysQno8DH5W0hMv5nlHYGgEOqFH6XvxgG5ZvYYUHpXfdrj2nKe BioXsayM/m797PZgBPWvWvStQaMZWDrKKY2X6lkmLARC9nm64059kgZlWEfohV9LJMY54xWa /+n6ubdKN1cFvAE+HEqfAY1JQGfWRqpdF2T2c74r8hBJ5IsIOq7ovzSbFtxhwgRE9/AZZawp WBQr2cro7nTn5/dYF0p9tJhxbBnSyKfzgHbpRp3NES+5WMOhJgDjyA== X-Mailgun-Sending-Ip: 209.61.151.224 X-Mailgun-Sid: WyJlMGM5NSIsICJxZW11LWRldmVsQG5vbmdudS5vcmciLCAiOWI0ZTc2Il0= From: Jonathan Behrens To: qemu-devel@nongnu.org Date: Tue, 28 May 2019 14:30:20 -0400 Message-Id: <20190528183020.17915-1-jonathan@fintelia.io> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.61.151.224 Subject: [Qemu-devel] [PATCH for 4.1 v3] target/riscv: Expose time CSRs when allowed by [m|s]counteren X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "open list:RISC-V" , Sagar Karandikar , Jonathan Behrens , Palmer Dabbelt , Alistair Francis , Bastian Koppelmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Currently mcounteren.TM acts as though it is hardwired to zero, even though= QEMU allows it to be set. This change resolves the issue by allowing reads= to the time and timeh control registers when running in a privileged mode = where such accesses are allowed. The frequency of the time register is stored in the time_freq field of each= hart so that it is accessible during CSR reads, but must be the same acros= s all harts. Each board can initialize it to a custom value, although all c= urrently use a 10 MHz frequency. Signed-off-by: Jonathan Behrens --- hw/riscv/riscv_hart.c | 4 ++++ hw/riscv/sifive_clint.c | 30 ++++++++++++++++++++++-------- hw/riscv/sifive_e.c | 2 ++ hw/riscv/sifive_u.c | 4 +++- hw/riscv/spike.c | 6 +++++- hw/riscv/virt.c | 4 +++- include/hw/riscv/riscv_hart.h | 1 + include/hw/riscv/sifive_clint.h | 4 ---- include/hw/riscv/sifive_e.h | 4 ++++ include/hw/riscv/sifive_u.h | 1 + include/hw/riscv/spike.h | 1 + include/hw/riscv/virt.h | 1 + target/riscv/cpu.h | 2 ++ target/riscv/csr.c | 17 +++++++++++------ 14 files changed, 60 insertions(+), 21 deletions(-) diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index e34a26a0ef..c39cd55330 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -19,6 +19,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/timer.h" #include "qapi/error.h" #include "hw/sysbus.h" #include "target/riscv/cpu.h" @@ -27,6 +28,8 @@ static Property riscv_harts_props[] =3D { DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1), DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type), + DEFINE_PROP_UINT64("timebase-frequency", RISCVHartArrayState, time_fre= q, + NANOSECONDS_PER_SECOND), DEFINE_PROP_END_OF_LIST(), }; =20 @@ -49,6 +52,7 @@ static void riscv_harts_realize(DeviceState *dev, Error *= *errp) sizeof(RISCVCPU), s->cpu_type, &error_abort, NULL); s->harts[n].env.mhartid =3D n; + s->harts[n].env.time_freq =3D s->time_freq; qemu_register_reset(riscv_harts_cpu_reset, &s->harts[n]); object_property_set_bool(OBJECT(&s->harts[n]), true, "realized", &err); diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c index d4c159e937..71edf4dcc6 100644 --- a/hw/riscv/sifive_clint.c +++ b/hw/riscv/sifive_clint.c @@ -26,10 +26,10 @@ #include "hw/riscv/sifive_clint.h" #include "qemu/timer.h" =20 -static uint64_t cpu_riscv_read_rtc(void) +static uint64_t cpu_riscv_read_rtc(CPURISCVState *env) { return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND); + env->time_freq, NANOSECONDS_PER_SECOND); } =20 /* @@ -41,7 +41,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uin= t64_t value) uint64_t next; uint64_t diff; =20 - uint64_t rtc_r =3D cpu_riscv_read_rtc(); + uint64_t rtc_r =3D cpu_riscv_read_rtc(&cpu->env); =20 cpu->env.timecmp =3D value; if (cpu->env.timecmp <=3D rtc_r) { @@ -56,7 +56,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uin= t64_t value) diff =3D cpu->env.timecmp - rtc_r; /* back to ns (note args switched in muldiv64) */ next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ); + muldiv64(diff, NANOSECONDS_PER_SECOND, cpu->env.time_freq); timer_mod(cpu->env.timer, next); } =20 @@ -107,11 +107,25 @@ static uint64_t sifive_clint_read(void *opaque, hwadd= r addr, unsigned size) return 0; } } else if (addr =3D=3D clint->time_base) { - /* time_lo */ - return cpu_riscv_read_rtc() & 0xFFFFFFFF; + /* All harts must have the same time frequency, so just use hart 0= */ + CPUState *cpu =3D qemu_get_cpu(0); + CPURISCVState *env =3D cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: hart 0 not valid?!"); + } else { + /* time_lo */ + return cpu_riscv_read_rtc(env) & 0xFFFFFFFF; + } } else if (addr =3D=3D clint->time_base + 4) { - /* time_hi */ - return (cpu_riscv_read_rtc() >> 32) & 0xFFFFFFFF; + /* All harts must have the same time frequency, so just use hart 0= */ + CPUState *cpu =3D qemu_get_cpu(0); + CPURISCVState *env =3D cpu ? cpu->env_ptr : NULL; + if (!env) { + error_report("clint: hart 0 not valid?!"); + } else { + /* time_hi */ + return (cpu_riscv_read_rtc(env) >> 32) & 0xFFFFFFFF; + } } =20 error_report("clint: invalid read: %08x", (uint32_t)addr); diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 80ac56fa7d..2d6f768ff1 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -146,6 +146,8 @@ static void riscv_sifive_e_soc_init(Object *obj) &error_abort); object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", &error_abort); + object_property_set_int(OBJECT(&s->cpus), SIFIVE_E_TIMEBASE_FREQ, + "timebase-frequency", &error_abort); sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0", &s->gpio, sizeof(s->gpio), TYPE_SIFIVE_GPIO); diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 5ecc47cea3..ab2b00106b 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -116,7 +116,7 @@ static void create_fdt(SiFiveUState *s, const struct Me= mmapEntry *memmap, =20 qemu_fdt_add_subnode(fdt, "/cpus"); qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", - SIFIVE_CLINT_TIMEBASE_FREQ); + SIFIVE_U_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); =20 @@ -329,6 +329,8 @@ static void riscv_sifive_u_soc_init(Object *obj) &error_abort); object_property_set_int(OBJECT(&s->cpus), smp_cpus, "num-harts", &error_abort); + object_property_set_int(OBJECT(&s->cpus), SIFIVE_U_TIMEBASE_FREQ, + "timebase-frequency", &error_abort); =20 sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem), TYPE_CADENCE_GEM); diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 5b33d4be3b..7c1872aad0 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -106,7 +106,7 @@ static void create_fdt(SpikeState *s, const struct Memm= apEntry *memmap, =20 qemu_fdt_add_subnode(fdt, "/cpus"); qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", - SIFIVE_CLINT_TIMEBASE_FREQ); + SPIKE_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); =20 @@ -180,6 +180,8 @@ static void spike_board_init(MachineState *machine) &error_abort); object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", &error_abort); + object_property_set_int(OBJECT(&s->soc), SPIKE_TIMEBASE_FREQ, + "timebase-frequency", &error_abort); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); =20 @@ -268,6 +270,8 @@ static void spike_v1_10_0_board_init(MachineState *mach= ine) &error_abort); object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", &error_abort); + object_property_set_int(OBJECT(&s->soc), SPIKE_TIMEBASE_FREQ, + "timebase-frequency", &error_abort); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); =20 diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 84d94d0c42..e3a2474cea 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -185,7 +185,7 @@ static void *create_fdt(RISCVVirtState *s, const struct= MemmapEntry *memmap, =20 qemu_fdt_add_subnode(fdt, "/cpus"); qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", - SIFIVE_CLINT_TIMEBASE_FREQ); + VIRT_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); =20 @@ -403,6 +403,8 @@ static void riscv_virt_board_init(MachineState *machine) &error_abort); object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", &error_abort); + object_property_set_int(OBJECT(&s->soc), VIRT_TIMEBASE_FREQ, + "timebase-frequency", &error_abort); object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort); =20 diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h index 0671d88a44..2e82e85b2b 100644 --- a/include/hw/riscv/riscv_hart.h +++ b/include/hw/riscv/riscv_hart.h @@ -33,6 +33,7 @@ typedef struct RISCVHartArrayState { /*< public >*/ uint32_t num_harts; char *cpu_type; + uint64_t time_freq; RISCVCPU *harts; } RISCVHartArrayState; =20 diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clin= t.h index e2865be1d1..aaa2a58c6e 100644 --- a/include/hw/riscv/sifive_clint.h +++ b/include/hw/riscv/sifive_clint.h @@ -47,8 +47,4 @@ enum { SIFIVE_TIME_BASE =3D 0xBFF8 }; =20 -enum { - SIFIVE_CLINT_TIMEBASE_FREQ =3D 10000000 -}; - #endif diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 3b14eb7462..95bd33d872 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -71,6 +71,10 @@ enum { SIFIVE_E_GPIO0_IRQ0 =3D 8 }; =20 +enum { + SIFIVE_E_TIMEBASE_FREQ =3D 10000000, +}; + #define SIFIVE_E_PLIC_HART_CONFIG "M" #define SIFIVE_E_PLIC_NUM_SOURCES 127 #define SIFIVE_E_PLIC_NUM_PRIORITIES 7 diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 892f0eee21..85ee1eca78 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -63,6 +63,7 @@ enum { }; =20 enum { + SIFIVE_U_TIMEBASE_FREQ =3D 10000000, SIFIVE_U_CLOCK_FREQ =3D 1000000000, SIFIVE_U_GEM_CLOCK_FREQ =3D 125000000 }; diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h index 641b70da67..2d391d1559 100644 --- a/include/hw/riscv/spike.h +++ b/include/hw/riscv/spike.h @@ -36,6 +36,7 @@ enum { }; =20 enum { + SPIKE_TIMEBASE_FREQ =3D 10000000, SPIKE_CLOCK_FREQ =3D 1000000000 }; =20 diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index d01a1a85c4..53d4318f76 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -53,6 +53,7 @@ enum { }; =20 enum { + VIRT_TIMEBASE_FREQ =3D 10000000, VIRT_CLOCK_FREQ =3D 1000000000 }; =20 diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 74e726c1c9..9c09bbbffd 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -175,7 +175,9 @@ struct CPURISCVState { /* temporary htif regs */ uint64_t mfromhost; uint64_t mtohost; + uint64_t timecmp; + uint64_t time_freq; =20 /* physical memory protection */ pmp_table_t pmp_state; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index f9e2910643..303c362782 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -191,22 +191,31 @@ static int read_instreth(CPURISCVState *env, int csrn= o, target_ulong *val) } #endif /* TARGET_RISCV32 */ =20 -#if defined(CONFIG_USER_ONLY) static int read_time(CPURISCVState *env, int csrno, target_ulong *val) { +#if !defined(CONFIG_USER_ONLY) + *val =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + env->time_freq, NANOSECONDS_PER_SECOND); +#else *val =3D cpu_get_host_ticks(); +#endif return 0; } =20 #if defined(TARGET_RISCV32) static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val) { +#if !defined(CONFIG_USER_ONLY) + *val =3D muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + env->time_freq, NANOSECONDS_PER_SECOND) >> 32; +#else *val =3D cpu_get_host_ticks() >> 32; +#endif return 0; } #endif =20 -#else /* CONFIG_USER_ONLY */ +#if !defined(CONFIG_USER_ONLY) =20 /* Machine constants */ =20 @@ -856,14 +865,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = =3D { [CSR_INSTRETH] =3D { ctr, read_instreth = }, #endif =20 - /* User-level time CSRs are only available in linux-user - * In privileged mode, the monitor emulates these CSRs */ -#if defined(CONFIG_USER_ONLY) [CSR_TIME] =3D { ctr, read_time = }, #if defined(TARGET_RISCV32) [CSR_TIMEH] =3D { ctr, read_timeh = }, #endif -#endif =20 #if !defined(CONFIG_USER_ONLY) /* Machine Timers and Counters */ --=20 2.20.1