[prev in list] [next in list] [prev in thread] [next in thread] 

List:       qemu-riscv
Subject:    [Qemu-riscv] [PATCH for 4.1 v2] target/riscv: Expose time CSRs when allowed by [m|s]counteren
From:       Jonathan Behrens <fintelia () gmail ! com>
Date:       2019-04-30 17:36:01
Message-ID: CANnJOVH_Jt0pCeqnqpZdCY97pUf72EiABXtOvHWLAkpfqhKbqg () mail ! gmail ! com
[Download RAW message or body]

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 across
all harts. Each board can initialize it to a custom value, although all
currently use a 10 MHz frequency.
---
 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 @@
  */

 #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[] = {
     DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
     DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
+    DEFINE_PROP_UINT64("timebase-frequency", RISCVHartArrayState,
time_freq,
+                       NANOSECONDS_PER_SECOND),
     DEFINE_PROP_END_OF_LIST(),
 };

@@ -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 = n;
+        s->harts[n].env.time_freq = 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"

-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);
 }

 /*
@@ -41,7 +41,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu,
uint64_t value)
     uint64_t next;
     uint64_t diff;

-    uint64_t rtc_r = cpu_riscv_read_rtc();
+    uint64_t rtc_r = cpu_riscv_read_rtc(&cpu->env);

     cpu->env.timecmp = value;
     if (cpu->env.timecmp <= rtc_r) {
@@ -56,7 +56,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu,
uint64_t value)
     diff = cpu->env.timecmp - rtc_r;
     /* back to ns (note args switched in muldiv64) */
     next = 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);
 }

@@ -107,11 +107,25 @@ static uint64_t sifive_clint_read(void *opaque,
hwaddr addr, unsigned size)
             return 0;
         }
     } else if (addr == 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 = qemu_get_cpu(0);
+        CPURISCVState *env = 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 == 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 = qemu_get_cpu(0);
+        CPURISCVState *env = 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;
+        }
     }

     error_report("clint: invalid read: %08x", (uint32_t)addr);
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index b1cd11363c..0a6bb629b6 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);
 }

 static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
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
MemmapEntry *memmap,

     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);

@@ -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);

     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 2a000a5800..6b85083308 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -105,7 +105,7 @@ static void create_fdt(SpikeState *s, const struct
MemmapEntry *memmap,

     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);

@@ -179,6 +179,8 @@ static void spike_v1_10_0_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);

@@ -261,6 +263,8 @@ static void spike_v1_09_1_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);

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 3526463034..beeccba4ac 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,

     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);

@@ -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);

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;

diff --git a/include/hw/riscv/sifive_clint.h
b/include/hw/riscv/sifive_clint.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    = 0xBFF8
 };

-enum {
-    SIFIVE_CLINT_TIMEBASE_FREQ = 10000000
-};
-
 #endif
diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
index 7b6d8aed96..b83e60493e 100644
--- a/include/hw/riscv/sifive_e.h
+++ b/include/hw/riscv/sifive_e.h
@@ -67,6 +67,10 @@ enum {
     SIFIVE_E_UART1_IRQ = 4
 };

+enum {
+    SIFIVE_E_TIMEBASE_FREQ = 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 be13cc1304..e94eb89866 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -63,6 +63,7 @@ enum {
 };

 enum {
+    SIFIVE_U_TIMEBASE_FREQ = 10000000,
     SIFIVE_U_CLOCK_FREQ = 1000000000,
     SIFIVE_U_GEM_CLOCK_FREQ = 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 {
 };

 enum {
+    SPIKE_TIMEBASE_FREQ = 10000000,
     SPIKE_CLOCK_FREQ = 1000000000
 };

diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index f12deaebd6..f807bbfe1e 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -53,6 +53,7 @@ enum {
 };

 enum {
+    VIRT_TIMEBASE_FREQ = 10000000,
     VIRT_CLOCK_FREQ = 1000000000
 };

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 20bce8742e..67b1769ad3 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -173,7 +173,9 @@ struct CPURISCVState {
     /* temporary htif regs */
     uint64_t mfromhost;
     uint64_t mtohost;
+
     uint64_t timecmp;
+    uint64_t time_freq;

     /* physical memory protection */
     pmp_table_t pmp_state;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e1d91b6c60..6083c782a1 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -191,22 +191,31 @@ static int read_instreth(CPURISCVState *env, int
csrno, target_ulong *val)
 }
 #endif /* TARGET_RISCV32 */

-#if defined(CONFIG_USER_ONLY)
 static int read_time(CPURISCVState *env, int csrno, target_ulong *val)
 {
+#if !defined(CONFIG_USER_ONLY)
+    *val = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+                    env->time_freq, NANOSECONDS_PER_SECOND);
+#else
     *val = cpu_get_host_ticks();
+#endif
     return 0;
 }

 #if defined(TARGET_RISCV32)
 static int read_timeh(CPURISCVState *env, int csrno, target_ulong *val)
 {
+#if !defined(CONFIG_USER_ONLY)
+    *val = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+                    env->time_freq, NANOSECONDS_PER_SECOND) >> 32;
+#else
     *val = cpu_get_host_ticks() >> 32;
+#endif
     return 0;
 }
 #endif

-#else /* CONFIG_USER_ONLY */
+#if !defined(CONFIG_USER_ONLY)

 /* Machine constants */

@@ -854,14 +863,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =
{
     [CSR_INSTRETH] =            { ctr,
read_instreth                       },
 #endif

-    /* 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] =                { ctr,
read_time                           },
 #if defined(TARGET_RISCV32)
     [CSR_TIMEH] =               { ctr,
read_timeh                          },
 #endif
-#endif

 #if !defined(CONFIG_USER_ONLY)
     /* Machine Timers and Counters */
-- 
2.20.1

[Attachment #3 (text/html)]

<div dir="ltr"><div dir="ltr"><div dir="ltr">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.</div><div \
dir="ltr"><br></div><div>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 across all harts. Each board can initialize it to a custom value, although \
all currently use a 10 MHz frequency.<br></div><div>---<br></div><div dir="ltr"> \
hw/riscv/riscv_hart.c           |  4 ++++<br> hw/riscv/sifive_clint.c         | 30 \
++++++++++++++++++++++--------<br> hw/riscv/sifive_e.c             |  2 ++<br> \
hw/riscv/sifive_u.c             |  4 +++-<br> hw/riscv/spike.c                |  6 \
+++++-<br> hw/riscv/virt.c                 |  4 +++-<br> \
include/hw/riscv/riscv_hart.h   |  1 +<br> include/hw/riscv/sifive_clint.h |  4 \
----<br> include/hw/riscv/sifive_e.h     |  4 ++++<br> include/hw/riscv/sifive_u.h    \
|  1 +<br> include/hw/riscv/spike.h        |  1 +<br> include/hw/riscv/virt.h         \
|  1 +<br> target/riscv/cpu.h              |  2 ++<br> target/riscv/csr.c             \
| 17 +++++++++++------<br> 14 files changed, 60 insertions(+), 21 \
deletions(-)<br><br>diff --git a/hw/riscv/riscv_hart.c \
b/hw/riscv/riscv_hart.c<br>index e34a26a0ef..c39cd55330 100644<br>--- \
a/hw/riscv/riscv_hart.c<br>+++ b/hw/riscv/riscv_hart.c<br>@@ -19,6 +19,7 @@<br>  \
*/<br> <br> #include &quot;qemu/osdep.h&quot;<br>+#include \
&quot;qemu/timer.h&quot;<br> #include &quot;qapi/error.h&quot;<br> #include \
&quot;hw/sysbus.h&quot;<br> #include &quot;target/riscv/cpu.h&quot;<br>@@ -27,6 +28,8 \
@@<br> static Property riscv_harts_props[] = {<br>     \
DEFINE_PROP_UINT32(&quot;num-harts&quot;, RISCVHartArrayState, num_harts, 1),<br>     \
DEFINE_PROP_STRING(&quot;cpu-type&quot;, RISCVHartArrayState, cpu_type),<br>+    \
DEFINE_PROP_UINT64(&quot;timebase-frequency&quot;, RISCVHartArrayState, \
time_freq,<br>+                       NANOSECONDS_PER_SECOND),<br>     \
DEFINE_PROP_END_OF_LIST(),<br> };<br> <br>@@ -49,6 +52,7 @@ static void \
riscv_harts_realize(DeviceState *dev, Error **errp)<br>                               \
sizeof(RISCVCPU), s-&gt;cpu_type,<br>                                 \
&amp;error_abort, NULL);<br>         s-&gt;harts[n].env.mhartid = n;<br>+        \
s-&gt;harts[n].env.time_freq = s-&gt;time_freq;<br>         \
qemu_register_reset(riscv_harts_cpu_reset, &amp;s-&gt;harts[n]);<br>         \
object_property_set_bool(OBJECT(&amp;s-&gt;harts[n]), true,<br>                       \
&quot;realized&quot;, &amp;err);<br>diff --git a/hw/riscv/sifive_clint.c \
b/hw/riscv/sifive_clint.c<br>index d4c159e937..71edf4dcc6 100644<br>--- \
a/hw/riscv/sifive_clint.c<br>+++ b/hw/riscv/sifive_clint.c<br>@@ -26,10 +26,10 @@<br> \
#include &quot;hw/riscv/sifive_clint.h&quot;<br> #include \
&quot;qemu/timer.h&quot;<br> <br>-static uint64_t cpu_riscv_read_rtc(void)<br>+static \
uint64_t cpu_riscv_read_rtc(CPURISCVState *env)<br> {<br>     return \
muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),<br>-        \
SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND);<br>+        env-&gt;time_freq, \
NANOSECONDS_PER_SECOND);<br> }<br> <br> /*<br>@@ -41,7 +41,7 @@ static void \
sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)<br>     uint64_t next;<br>  \
uint64_t diff;<br> <br>-    uint64_t rtc_r = cpu_riscv_read_rtc();<br>+    uint64_t \
rtc_r = cpu_riscv_read_rtc(&amp;cpu-&gt;env);<br> <br>     cpu-&gt;env.timecmp = \
value;<br>     if (cpu-&gt;env.timecmp &lt;= rtc_r) {<br>@@ -56,7 +56,7 @@ static \
void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)<br>     diff = \
cpu-&gt;env.timecmp - rtc_r;<br>     /* back to ns (note args switched in muldiv64) \
*/<br>     next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +<br>-        muldiv64(diff, \
NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ);<br>+        muldiv64(diff, \
NANOSECONDS_PER_SECOND, cpu-&gt;env.time_freq);<br>     timer_mod(cpu-&gt;env.timer, \
next);<br> }<br> <br>@@ -107,11 +107,25 @@ static uint64_t sifive_clint_read(void \
*opaque, hwaddr addr, unsigned size)<br>             return 0;<br>         }<br>     \
} else if (addr == clint-&gt;time_base) {<br>-        /* time_lo */<br>-        \
return cpu_riscv_read_rtc() &amp; 0xFFFFFFFF;<br>+        /* All harts must have the \
same time frequency, so just use hart 0 */<br>+        CPUState *cpu = \
qemu_get_cpu(0);<br>+        CPURISCVState *env = cpu ? cpu-&gt;env_ptr : NULL;<br>+  \
if (!env) {<br>+            error_report(&quot;clint: hart 0 not valid?!&quot;);<br>+ \
} else {<br>+            /* time_lo */<br>+            return cpu_riscv_read_rtc(env) \
&amp; 0xFFFFFFFF;<br>+        }<br>     } else if (addr == clint-&gt;time_base + 4) \
{<br>-        /* time_hi */<br>-        return (cpu_riscv_read_rtc() &gt;&gt; 32) \
&amp; 0xFFFFFFFF;<br>+        /* All harts must have the same time frequency, so just \
use hart 0 */<br>+        CPUState *cpu = qemu_get_cpu(0);<br>+        CPURISCVState \
*env = cpu ? cpu-&gt;env_ptr : NULL;<br>+        if (!env) {<br>+            \
error_report(&quot;clint: hart 0 not valid?!&quot;);<br>+        } else {<br>+        \
/* time_hi */<br>+            return (cpu_riscv_read_rtc(env) &gt;&gt; 32) &amp; \
0xFFFFFFFF;<br>+        }<br>     }<br> <br>     error_report(&quot;clint: invalid \
read: %08x&quot;, (uint32_t)addr);<br>diff --git a/hw/riscv/sifive_e.c \
b/hw/riscv/sifive_e.c<br>index b1cd11363c..0a6bb629b6 100644<br>--- \
a/hw/riscv/sifive_e.c<br>+++ b/hw/riscv/sifive_e.c<br>@@ -146,6 +146,8 @@ static void \
riscv_sifive_e_soc_init(Object *obj)<br>                             \
&amp;error_abort);<br>     object_property_set_int(OBJECT(&amp;s-&gt;cpus), smp_cpus, \
&quot;num-harts&quot;,<br>                             &amp;error_abort);<br>+    \
object_property_set_int(OBJECT(&amp;s-&gt;cpus), SIFIVE_E_TIMEBASE_FREQ,<br>+         \
&quot;timebase-frequency&quot;, &amp;error_abort);<br> }<br> <br> static void \
riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)<br>diff --git \
a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c<br>index 5ecc47cea3..ab2b00106b \
100644<br>--- a/hw/riscv/sifive_u.c<br>+++ b/hw/riscv/sifive_u.c<br>@@ -116,7 +116,7 \
@@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,<br> <br> \
qemu_fdt_add_subnode(fdt, &quot;/cpus&quot;);<br>     qemu_fdt_setprop_cell(fdt, \
&quot;/cpus&quot;, &quot;timebase-frequency&quot;,<br>-        \
SIFIVE_CLINT_TIMEBASE_FREQ);<br>+        SIFIVE_U_TIMEBASE_FREQ);<br>     \
qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, &quot;#size-cells&quot;, 0x0);<br>     \
qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, &quot;#address-cells&quot;, 0x1);<br> \
<br>@@ -329,6 +329,8 @@ static void riscv_sifive_u_soc_init(Object *obj)<br>          \
&amp;error_abort);<br>     object_property_set_int(OBJECT(&amp;s-&gt;cpus), smp_cpus, \
&quot;num-harts&quot;,<br>                             &amp;error_abort);<br>+    \
object_property_set_int(OBJECT(&amp;s-&gt;cpus), SIFIVE_U_TIMEBASE_FREQ,<br>+         \
&quot;timebase-frequency&quot;, &amp;error_abort);<br> <br>     \
sysbus_init_child_obj(obj, &quot;gem&quot;, &amp;s-&gt;gem, sizeof(s-&gt;gem),<br>    \
TYPE_CADENCE_GEM);<br>diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c<br>index \
2a000a5800..6b85083308 100644<br>--- a/hw/riscv/spike.c<br>+++ \
b/hw/riscv/spike.c<br>@@ -105,7 +105,7 @@ static void create_fdt(SpikeState *s, const \
struct MemmapEntry *memmap,<br> <br>     qemu_fdt_add_subnode(fdt, \
&quot;/cpus&quot;);<br>     qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, \
&quot;timebase-frequency&quot;,<br>-        SIFIVE_CLINT_TIMEBASE_FREQ);<br>+        \
SPIKE_TIMEBASE_FREQ);<br>     qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, \
&quot;#size-cells&quot;, 0x0);<br>     qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, \
&quot;#address-cells&quot;, 0x1);<br> <br>@@ -179,6 +179,8 @@ static void \
spike_v1_10_0_board_init(MachineState *machine)<br>                             \
&amp;error_abort);<br>     object_property_set_int(OBJECT(&amp;s-&gt;soc), smp_cpus, \
&quot;num-harts&quot;,<br>                             &amp;error_abort);<br>+    \
object_property_set_int(OBJECT(&amp;s-&gt;soc), SPIKE_TIMEBASE_FREQ,<br>+             \
&quot;timebase-frequency&quot;, &amp;error_abort);<br>     \
object_property_set_bool(OBJECT(&amp;s-&gt;soc), true, &quot;realized&quot;,<br>      \
&amp;error_abort);<br> <br>@@ -261,6 +263,8 @@ static void \
spike_v1_09_1_board_init(MachineState *machine)<br>                             \
&amp;error_abort);<br>     object_property_set_int(OBJECT(&amp;s-&gt;soc), smp_cpus, \
&quot;num-harts&quot;,<br>                             &amp;error_abort);<br>+    \
object_property_set_int(OBJECT(&amp;s-&gt;soc), SPIKE_TIMEBASE_FREQ,<br>+             \
&quot;timebase-frequency&quot;, &amp;error_abort);<br>     \
object_property_set_bool(OBJECT(&amp;s-&gt;soc), true, &quot;realized&quot;,<br>      \
&amp;error_abort);<br> <br>diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c<br>index \
3526463034..beeccba4ac 100644<br>--- a/hw/riscv/virt.c<br>+++ b/hw/riscv/virt.c<br>@@ \
-185,7 +185,7 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry \
*memmap,<br> <br>     qemu_fdt_add_subnode(fdt, &quot;/cpus&quot;);<br>     \
qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, &quot;timebase-frequency&quot;,<br>-    \
SIFIVE_CLINT_TIMEBASE_FREQ);<br>+                          VIRT_TIMEBASE_FREQ);<br>   \
qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, &quot;#size-cells&quot;, 0x0);<br>     \
qemu_fdt_setprop_cell(fdt, &quot;/cpus&quot;, &quot;#address-cells&quot;, 0x1);<br> \
<br>@@ -403,6 +403,8 @@ static void riscv_virt_board_init(MachineState *machine)<br>  \
&amp;error_abort);<br>     object_property_set_int(OBJECT(&amp;s-&gt;soc), smp_cpus, \
&quot;num-harts&quot;,<br>                             &amp;error_abort);<br>+    \
object_property_set_int(OBJECT(&amp;s-&gt;soc), VIRT_TIMEBASE_FREQ,<br>+              \
&quot;timebase-frequency&quot;, &amp;error_abort);<br>     \
object_property_set_bool(OBJECT(&amp;s-&gt;soc), true, &quot;realized&quot;,<br>      \
&amp;error_abort);<br> <br>diff --git a/include/hw/riscv/riscv_hart.h \
b/include/hw/riscv/riscv_hart.h<br>index 0671d88a44..2e82e85b2b 100644<br>--- \
a/include/hw/riscv/riscv_hart.h<br>+++ b/include/hw/riscv/riscv_hart.h<br>@@ -33,6 \
+33,7 @@ typedef struct RISCVHartArrayState {<br>     /*&lt; public &gt;*/<br>     \
uint32_t num_harts;<br>     char *cpu_type;<br>+    uint64_t time_freq;<br>     \
RISCVCPU *harts;<br> } RISCVHartArrayState;<br> <br>diff --git \
a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h<br>index \
e2865be1d1..aaa2a58c6e 100644<br>--- a/include/hw/riscv/sifive_clint.h<br>+++ \
b/include/hw/riscv/sifive_clint.h<br>@@ -47,8 +47,4 @@ enum {<br>     \
SIFIVE_TIME_BASE    = 0xBFF8<br> };<br> <br>-enum {<br>-    \
SIFIVE_CLINT_TIMEBASE_FREQ = 10000000<br>-};<br>-<br> #endif<br>diff --git \
a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h<br>index \
7b6d8aed96..b83e60493e 100644<br>--- a/include/hw/riscv/sifive_e.h<br>+++ \
b/include/hw/riscv/sifive_e.h<br>@@ -67,6 +67,10 @@ enum {<br>     SIFIVE_E_UART1_IRQ \
= 4<br> };<br> <br>+enum {<br>+    SIFIVE_E_TIMEBASE_FREQ = 10000000,<br>+};<br>+<br> \
#define SIFIVE_E_PLIC_HART_CONFIG &quot;M&quot;<br> #define SIFIVE_E_PLIC_NUM_SOURCES \
127<br> #define SIFIVE_E_PLIC_NUM_PRIORITIES 7<br>diff --git \
a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h<br>index \
be13cc1304..e94eb89866 100644<br>--- a/include/hw/riscv/sifive_u.h<br>+++ \
b/include/hw/riscv/sifive_u.h<br>@@ -63,6 +63,7 @@ enum {<br> };<br> <br> enum {<br>+ \
SIFIVE_U_TIMEBASE_FREQ = 10000000,<br>     SIFIVE_U_CLOCK_FREQ = 1000000000,<br>     \
SIFIVE_U_GEM_CLOCK_FREQ = 125000000<br> };<br>diff --git a/include/hw/riscv/spike.h \
b/include/hw/riscv/spike.h<br>index 641b70da67..2d391d1559 100644<br>--- \
a/include/hw/riscv/spike.h<br>+++ b/include/hw/riscv/spike.h<br>@@ -36,6 +36,7 @@ \
enum {<br> };<br> <br> enum {<br>+    SPIKE_TIMEBASE_FREQ = 10000000,<br>     \
SPIKE_CLOCK_FREQ = 1000000000<br> };<br> <br>diff --git a/include/hw/riscv/virt.h \
b/include/hw/riscv/virt.h<br>index f12deaebd6..f807bbfe1e 100644<br>--- \
a/include/hw/riscv/virt.h<br>+++ b/include/hw/riscv/virt.h<br>@@ -53,6 +53,7 @@ enum \
{<br> };<br> <br> enum {<br>+    VIRT_TIMEBASE_FREQ = 10000000,<br>     \
VIRT_CLOCK_FREQ = 1000000000<br> };<br> <br>diff --git a/target/riscv/cpu.h \
b/target/riscv/cpu.h<br>index 20bce8742e..67b1769ad3 100644<br>--- \
a/target/riscv/cpu.h<br>+++ b/target/riscv/cpu.h<br>@@ -173,7 +173,9 @@ struct \
CPURISCVState {<br>     /* temporary htif regs */<br>     uint64_t mfromhost;<br>     \
uint64_t mtohost;<br>+<br>     uint64_t timecmp;<br>+    uint64_t time_freq;<br> <br> \
/* physical memory protection */<br>     pmp_table_t pmp_state;<br>diff --git \
a/target/riscv/csr.c b/target/riscv/csr.c<br>index e1d91b6c60..6083c782a1 \
100644<br>--- a/target/riscv/csr.c<br>+++ b/target/riscv/csr.c<br>@@ -191,22 +191,31 \
@@ static int read_instreth(CPURISCVState *env, int csrno, target_ulong *val)<br> \
}<br> #endif /* TARGET_RISCV32 */<br> <br>-#if defined(CONFIG_USER_ONLY)<br> static \
int read_time(CPURISCVState *env, int csrno, target_ulong *val)<br> {<br>+#if \
!defined(CONFIG_USER_ONLY)<br>+    *val = \
muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),<br>+                    \
env-&gt;time_freq, NANOSECONDS_PER_SECOND);<br>+#else<br>     *val = \
cpu_get_host_ticks();<br>+#endif<br>     return 0;<br> }<br> <br> #if \
defined(TARGET_RISCV32)<br> static int read_timeh(CPURISCVState *env, int csrno, \
target_ulong *val)<br> {<br>+#if !defined(CONFIG_USER_ONLY)<br>+    *val = \
muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),<br>+                    \
env-&gt;time_freq, NANOSECONDS_PER_SECOND) &gt;&gt; 32;<br>+#else<br>     *val = \
cpu_get_host_ticks() &gt;&gt; 32;<br>+#endif<br>     return 0;<br> }<br> #endif<br> \
<br>-#else /* CONFIG_USER_ONLY */<br>+#if !defined(CONFIG_USER_ONLY)<br> <br> /* \
Machine constants */<br> <br>@@ -854,14 +863,10 @@ static riscv_csr_operations \
csr_ops[CSR_TABLE_SIZE] = {<br>     [CSR_INSTRETH] =            { ctr,  read_instreth \
},<br> #endif<br> <br>-    /* User-level time CSRs are only available in \
linux-user<br>-     * In privileged mode, the monitor emulates these CSRs */<br>-#if \
defined(CONFIG_USER_ONLY)<br>     [CSR_TIME] =                { ctr,  read_time       \
},<br> #if defined(TARGET_RISCV32)<br>     [CSR_TIMEH] =               { ctr,  \
read_timeh                          },<br> #endif<br>-#endif<br> <br> #if \
!defined(CONFIG_USER_ONLY)<br>     /* Machine Timers and Counters */<br>-- \
<br>2.20.1<br></div></div></div>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic