aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuís Marques <luismarques@lowrisc.org>2019-10-22 17:56:54 +0100
committerAndrew Waterman <andrew@sifive.com>2019-10-22 09:56:53 -0700
commit99d6d0a93f9c83b63343a00693d5085e3949fe1a (patch)
tree2be05e20bf3956c1578bd32055c6195117087b85
parent78e61baf432bd2d796c5b1e0498af363967322f4 (diff)
downloadpk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.zip
pk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.tar.gz
pk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.tar.bz2
Make performance counters always 64 bits wide (#178)
This prevents the counters from easily overflowing for a 32-bit pk.
-rw-r--r--pk/boot.h6
-rw-r--r--pk/pk.c6
-rw-r--r--pk/pk.h58
-rw-r--r--pk/syscall.c25
-rw-r--r--util/snprintf.c19
5 files changed, 93 insertions, 21 deletions
diff --git a/pk/boot.h b/pk/boot.h
index f16ab15..f8bc51c 100644
--- a/pk/boot.h
+++ b/pk/boot.h
@@ -20,9 +20,9 @@ typedef struct {
size_t brk_max;
size_t mmap_max;
size_t stack_top;
- size_t time0;
- size_t cycle0;
- size_t instret0;
+ uint64_t time0;
+ uint64_t cycle0;
+ uint64_t instret0;
} elf_info;
extern elf_info current;
diff --git a/pk/pk.c b/pk/pk.c
index b8b0b1c..8ba9dc3 100644
--- a/pk/pk.c
+++ b/pk/pk.c
@@ -132,9 +132,9 @@ static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top)
STACK_INIT(uintptr_t);
if (current.cycle0) { // start timer if so requested
- current.time0 = rdtime();
- current.cycle0 = rdcycle();
- current.instret0 = rdinstret();
+ current.time0 = rdtime64();
+ current.cycle0 = rdcycle64();
+ current.instret0 = rdinstret64();
}
trapframe_t tf;
diff --git a/pk/pk.h b/pk/pk.h
index 1167f6e..a55ab6c 100644
--- a/pk/pk.h
+++ b/pk/pk.h
@@ -41,6 +41,64 @@ static inline int insn_len(long insn)
return (insn & 0x3) < 0x3 ? 2 : 4;
}
+#if __riscv_xlen == 32
+
+static inline uint64_t rdtime64()
+{
+ uint32_t time;
+ uint32_t timeh1;
+ uint32_t timeh2;
+
+ do
+ {
+ timeh1 = read_csr(timeh);
+ time = read_csr(time);
+ timeh2 = read_csr(timeh);
+ } while(timeh1 != timeh2);
+
+ return (((uint64_t) timeh1) << 32) | time;
+}
+
+static inline uint64_t rdcycle64()
+{
+ uint32_t cycle;
+ uint32_t cycleh1;
+ uint32_t cycleh2;
+
+ do
+ {
+ cycleh1 = read_csr(cycleh);
+ cycle = read_csr(cycle);
+ cycleh2 = read_csr(cycleh);
+ } while(cycleh1 != cycleh2);
+
+ return (((uint64_t) cycleh1) << 32) | cycle;
+}
+
+static inline uint64_t rdinstret64()
+{
+ uint32_t instret;
+ uint32_t instreth1;
+ uint32_t instreth2;
+
+ do
+ {
+ instreth1 = read_csr(instreth);
+ instret = read_csr(instret);
+ instreth2 = read_csr(instreth);
+ } while(instreth1 != instreth2);
+
+ return (((uint64_t) instreth1) << 32) | instret;
+}
+
+#else
+
+#define rdtime64 rdtime
+#define rdcycle64 rdcycle
+#define rdinstret64 rdinstret
+
+#endif
+
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
#ifdef __cplusplus
diff --git a/pk/syscall.c b/pk/syscall.c
index 8903ecc..07fa41d 100644
--- a/pk/syscall.c
+++ b/pk/syscall.c
@@ -16,14 +16,15 @@ typedef long (*syscall_t)(long, long, long, long, long, long, long);
void sys_exit(int code)
{
if (current.cycle0) {
- size_t dt = rdtime() - current.time0;
- size_t dc = rdcycle() - current.cycle0;
- size_t di = rdinstret() - current.instret0;
-
- printk("%ld ticks\n", dt);
- printk("%ld cycles\n", dc);
- printk("%ld instructions\n", di);
- printk("%d.%d%d CPI\n", dc/di, 10ULL*dc/di % 10, (100ULL*dc + di/2)/di % 10);
+ uint64_t dt = rdtime64() - current.time0;
+ uint64_t dc = rdcycle64() - current.cycle0;
+ uint64_t di = rdinstret64() - current.instret0;
+
+ printk("%lld ticks\n", dt);
+ printk("%lld cycles\n", dc);
+ printk("%lld instructions\n", di);
+ printk("%d.%d%d CPI\n", (int)(dc/di), (int)(10ULL*dc/di % 10),
+ (int)((100ULL*dc + di/2)/di % 10));
}
shutdown(code);
}
@@ -353,7 +354,7 @@ int sys_rt_sigaction(int sig, const void* act, void* oact, size_t sssz)
long sys_time(long* loc)
{
- uintptr_t t = rdcycle() / CLOCK_FREQ;
+ uint64_t t = rdcycle64() / CLOCK_FREQ;
if (loc)
*loc = t;
return t;
@@ -361,7 +362,7 @@ long sys_time(long* loc)
int sys_times(long* loc)
{
- uintptr_t t = rdcycle();
+ uint64_t t = rdcycle64();
kassert(CLOCK_FREQ % 1000000 == 0);
loc[0] = t / (CLOCK_FREQ / 1000000);
loc[1] = 0;
@@ -373,7 +374,7 @@ int sys_times(long* loc)
int sys_gettimeofday(long* loc)
{
- uintptr_t t = rdcycle();
+ uint64_t t = rdcycle64();
loc[0] = t / CLOCK_FREQ;
loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000);
@@ -382,7 +383,7 @@ int sys_gettimeofday(long* loc)
long sys_clock_gettime(int clk_id, long *loc)
{
- uintptr_t t = rdcycle();
+ uint64_t t = rdcycle64();
loc[0] = t / CLOCK_FREQ;
loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000000);
diff --git a/util/snprintf.c b/util/snprintf.c
index 1544a6c..a11a4f7 100644
--- a/util/snprintf.c
+++ b/util/snprintf.c
@@ -9,6 +9,7 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
{
bool format = false;
bool longarg = false;
+ bool longlongarg = false;
size_t pos = 0;
for( ; *s; s++)
{
@@ -17,7 +18,12 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
switch(*s)
{
case 'l':
- longarg = true;
+ if (s[1] == 'l') {
+ longlongarg = true;
+ s++;
+ }
+ else
+ longarg = true;
break;
case 'p':
longarg = true;
@@ -36,13 +42,19 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
}
case 'd':
{
- long num = longarg ? va_arg(vl, long) : va_arg(vl, int);
+ long long num;
+ if (longarg)
+ num = va_arg(vl, long);
+ else if (longlongarg)
+ num = va_arg(vl, long long);
+ else
+ num = va_arg(vl, int);
if (num < 0) {
num = -num;
if (++pos < n) out[pos-1] = '-';
}
long digits = 1;
- for (long nn = num; nn /= 10; digits++)
+ for (long long nn = num; nn /= 10; digits++)
;
for (int i = digits-1; i >= 0; i--) {
if (pos + i + 1 < n) out[pos + i] = '0' + (num % 10);
@@ -50,6 +62,7 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl)
}
pos += digits;
longarg = false;
+ longlongarg = false;
format = false;
break;
}