All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stafford Horne <shorne@gmail.com>
To: QEMU Development <qemu-devel@nongnu.org>
Cc: Richard Henderson <rth@twiddle.net>,
	Openrisc <openrisc@lists.librecores.org>,
	Stafford Horne <shorne@gmail.com>
Subject: [Qemu-devel] [PATCH 3/5] openrisc/cputimer: Perparation for Multicore
Date: Wed, 23 Aug 2017 14:57:11 +0900	[thread overview]
Message-ID: <9ff134a8c36d63ad667d94cacb5ef490e2227e1e.1503467674.git.shorne@gmail.com> (raw)
In-Reply-To: <cover.1503467674.git.shorne@gmail.com>
In-Reply-To: <cover.1503467674.git.shorne@gmail.com>

In order to support multicore system we move some of the previously
static state variables into the state of each core.

On the other hand in order to allow timers to be synced between each
code the ttcr (tick timer count register) is moved out of the core.
This is not as per real hardware spec which has a separate timer counter
per core, but it seems the most simple way to keep each clock in sync.

Signed-off-by: Stafford Horne <shorne@gmail.com>
---
 hw/openrisc/cputimer.c       | 62 +++++++++++++++++++++++++++++++++-----------
 target/openrisc/cpu.c        |  1 -
 target/openrisc/cpu.h        |  4 ++-
 target/openrisc/machine.c    |  1 -
 target/openrisc/sys_helper.c |  4 +--
 5 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index febc469170..4c5415ff75 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -25,39 +25,56 @@
 
 #define TIMER_PERIOD 50 /* 50 ns period for 20 MHz timer */
 
-/* The time when TTCR changes */
-static uint64_t last_clk;
-static int is_counting;
+/* Tick Timer global state to allow all cores to be in sync */
+typedef struct OR1KTimerState {
+    uint32_t ttcr;
+    uint64_t last_clk;
+} OR1KTimerState;
 
+static OR1KTimerState *or1k_timer;
+
+void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val)
+{
+    or1k_timer->ttcr = val;
+}
+
+uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu)
+{
+    return or1k_timer->ttcr;
+}
+
+/* Add elapsed ticks to ttcr */
 void cpu_openrisc_count_update(OpenRISCCPU *cpu)
 {
     uint64_t now;
 
-    if (!is_counting) {
+    if (!cpu->env.is_counting) {
         return;
     }
     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-    cpu->env.ttcr += (uint32_t)((now - last_clk) / TIMER_PERIOD);
-    last_clk = now;
+    or1k_timer->ttcr += (uint32_t)((now - or1k_timer->last_clk)
+                                    / TIMER_PERIOD);
+    or1k_timer->last_clk = now;
 }
 
+/* Update the next timeout time as difference between ttmr and ttcr */
 void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
 {
     uint32_t wait;
     uint64_t now, next;
 
-    if (!is_counting) {
+    if (!cpu->env.is_counting) {
         return;
     }
 
     cpu_openrisc_count_update(cpu);
-    now = last_clk;
+    now = or1k_timer->last_clk;
 
-    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
-        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
+    if ((cpu->env.ttmr & TTMR_TP) <= (or1k_timer->ttcr & TTMR_TP)) {
+        wait = TTMR_TP - (or1k_timer->ttcr & TTMR_TP) + 1;
         wait += cpu->env.ttmr & TTMR_TP;
     } else {
-        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
+        wait = (cpu->env.ttmr & TTMR_TP) - (or1k_timer->ttcr & TTMR_TP);
     }
     next = now + (uint64_t)wait * TIMER_PERIOD;
     timer_mod(cpu->env.timer, next);
@@ -66,7 +83,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
 
 void cpu_openrisc_count_start(OpenRISCCPU *cpu)
 {
-    is_counting = 1;
+    cpu->env.is_counting = 1;
     cpu_openrisc_count_update(cpu);
 }
 
@@ -74,7 +91,7 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
 {
     timer_del(cpu->env.timer);
     cpu_openrisc_count_update(cpu);
-    is_counting = 0;
+    cpu->env.is_counting = 0;
 }
 
 static void openrisc_timer_cb(void *opaque)
@@ -93,7 +110,7 @@ static void openrisc_timer_cb(void *opaque)
     case TIMER_NONE:
         break;
     case TIMER_INTR:
-        cpu->env.ttcr = 0;
+        or1k_timer->ttcr = 0;
         break;
     case TIMER_SHOT:
         cpu_openrisc_count_stop(cpu);
@@ -105,9 +122,24 @@ static void openrisc_timer_cb(void *opaque)
     cpu_openrisc_timer_update(cpu);
 }
 
+static const VMStateDescription vmstate_or1k_timer = {
+    .name = "or1k_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ttcr, OR1KTimerState),
+        VMSTATE_UINT64(last_clk, OR1KTimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
 {
     cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &openrisc_timer_cb, cpu);
     cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
+
+    if (or1k_timer == NULL) {
+        or1k_timer = g_new0(OR1KTimerState, 1);
+        vmstate_register(NULL, 0, &vmstate_or1k_timer, or1k_timer);
+    }
 }
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 1d6330cbcc..0a46684987 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -61,7 +61,6 @@ static void openrisc_cpu_reset(CPUState *s)
     cpu->env.picsr = 0x00000000;
 
     cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
 #endif
 }
 
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 4a61e5abfc..265f48ca43 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -315,7 +315,7 @@ typedef struct CPUOpenRISCState {
 
     QEMUTimer *timer;
     uint32_t ttmr;          /* Timer tick mode register */
-    uint32_t ttcr;          /* Timer tick count register */
+    int is_counting;
 
     uint32_t picmr;         /* Interrupt mask register */
     uint32_t picsr;         /* Interrupt contrl register*/
@@ -376,6 +376,8 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
 
 /* hw/openrisc_timer.c */
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
+uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu);
+void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val);
 void cpu_openrisc_count_update(OpenRISCCPU *cpu);
 void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
 void cpu_openrisc_count_start(OpenRISCCPU *cpu);
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index a879b2b539..c6a945f0df 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -147,7 +147,6 @@ static const VMStateDescription vmstate_env = {
 
         VMSTATE_TIMER_PTR(timer, CPUOpenRISCState),
         VMSTATE_UINT32(ttmr, CPUOpenRISCState),
-        VMSTATE_UINT32(ttcr, CPUOpenRISCState),
 
         VMSTATE_UINT32(picmr, CPUOpenRISCState),
         VMSTATE_UINT32(picsr, CPUOpenRISCState),
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index e138bcf9db..35be44beff 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -188,7 +188,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         break;
 
     case TO_SPR(10, 1): /* TTCR */
-        env->ttcr = rb;
+        cpu_openrisc_count_set(cpu, rb);
         if (env->ttmr & TIMER_NONE) {
             return;
         }
@@ -311,7 +311,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
 
     case TO_SPR(10, 1): /* TTCR */
         cpu_openrisc_count_update(cpu);
-        return env->ttcr;
+        return cpu_openrisc_count_get(cpu);
 
     default:
         break;
-- 
2.13.5

WARNING: multiple messages have this Message-ID (diff)
From: Stafford Horne <shorne@gmail.com>
To: openrisc@lists.librecores.org
Subject: [OpenRISC] [PATCH 3/5] openrisc/cputimer: Perparation for Multicore
Date: Wed, 23 Aug 2017 14:57:11 +0900	[thread overview]
Message-ID: <9ff134a8c36d63ad667d94cacb5ef490e2227e1e.1503467674.git.shorne@gmail.com> (raw)
In-Reply-To: <cover.1503467674.git.shorne@gmail.com>

In order to support multicore system we move some of the previously
static state variables into the state of each core.

On the other hand in order to allow timers to be synced between each
code the ttcr (tick timer count register) is moved out of the core.
This is not as per real hardware spec which has a separate timer counter
per core, but it seems the most simple way to keep each clock in sync.

Signed-off-by: Stafford Horne <shorne@gmail.com>
---
 hw/openrisc/cputimer.c       | 62 +++++++++++++++++++++++++++++++++-----------
 target/openrisc/cpu.c        |  1 -
 target/openrisc/cpu.h        |  4 ++-
 target/openrisc/machine.c    |  1 -
 target/openrisc/sys_helper.c |  4 +--
 5 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index febc469170..4c5415ff75 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -25,39 +25,56 @@
 
 #define TIMER_PERIOD 50 /* 50 ns period for 20 MHz timer */
 
-/* The time when TTCR changes */
-static uint64_t last_clk;
-static int is_counting;
+/* Tick Timer global state to allow all cores to be in sync */
+typedef struct OR1KTimerState {
+    uint32_t ttcr;
+    uint64_t last_clk;
+} OR1KTimerState;
 
+static OR1KTimerState *or1k_timer;
+
+void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val)
+{
+    or1k_timer->ttcr = val;
+}
+
+uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu)
+{
+    return or1k_timer->ttcr;
+}
+
+/* Add elapsed ticks to ttcr */
 void cpu_openrisc_count_update(OpenRISCCPU *cpu)
 {
     uint64_t now;
 
-    if (!is_counting) {
+    if (!cpu->env.is_counting) {
         return;
     }
     now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-    cpu->env.ttcr += (uint32_t)((now - last_clk) / TIMER_PERIOD);
-    last_clk = now;
+    or1k_timer->ttcr += (uint32_t)((now - or1k_timer->last_clk)
+                                    / TIMER_PERIOD);
+    or1k_timer->last_clk = now;
 }
 
+/* Update the next timeout time as difference between ttmr and ttcr */
 void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
 {
     uint32_t wait;
     uint64_t now, next;
 
-    if (!is_counting) {
+    if (!cpu->env.is_counting) {
         return;
     }
 
     cpu_openrisc_count_update(cpu);
-    now = last_clk;
+    now = or1k_timer->last_clk;
 
-    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
-        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
+    if ((cpu->env.ttmr & TTMR_TP) <= (or1k_timer->ttcr & TTMR_TP)) {
+        wait = TTMR_TP - (or1k_timer->ttcr & TTMR_TP) + 1;
         wait += cpu->env.ttmr & TTMR_TP;
     } else {
-        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
+        wait = (cpu->env.ttmr & TTMR_TP) - (or1k_timer->ttcr & TTMR_TP);
     }
     next = now + (uint64_t)wait * TIMER_PERIOD;
     timer_mod(cpu->env.timer, next);
@@ -66,7 +83,7 @@ void cpu_openrisc_timer_update(OpenRISCCPU *cpu)
 
 void cpu_openrisc_count_start(OpenRISCCPU *cpu)
 {
-    is_counting = 1;
+    cpu->env.is_counting = 1;
     cpu_openrisc_count_update(cpu);
 }
 
@@ -74,7 +91,7 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
 {
     timer_del(cpu->env.timer);
     cpu_openrisc_count_update(cpu);
-    is_counting = 0;
+    cpu->env.is_counting = 0;
 }
 
 static void openrisc_timer_cb(void *opaque)
@@ -93,7 +110,7 @@ static void openrisc_timer_cb(void *opaque)
     case TIMER_NONE:
         break;
     case TIMER_INTR:
-        cpu->env.ttcr = 0;
+        or1k_timer->ttcr = 0;
         break;
     case TIMER_SHOT:
         cpu_openrisc_count_stop(cpu);
@@ -105,9 +122,24 @@ static void openrisc_timer_cb(void *opaque)
     cpu_openrisc_timer_update(cpu);
 }
 
+static const VMStateDescription vmstate_or1k_timer = {
+    .name = "or1k_timer",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(ttcr, OR1KTimerState),
+        VMSTATE_UINT64(last_clk, OR1KTimerState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
 {
     cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &openrisc_timer_cb, cpu);
     cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
+
+    if (or1k_timer == NULL) {
+        or1k_timer = g_new0(OR1KTimerState, 1);
+        vmstate_register(NULL, 0, &vmstate_or1k_timer, or1k_timer);
+    }
 }
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 1d6330cbcc..0a46684987 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -61,7 +61,6 @@ static void openrisc_cpu_reset(CPUState *s)
     cpu->env.picsr = 0x00000000;
 
     cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
 #endif
 }
 
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index 4a61e5abfc..265f48ca43 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -315,7 +315,7 @@ typedef struct CPUOpenRISCState {
 
     QEMUTimer *timer;
     uint32_t ttmr;          /* Timer tick mode register */
-    uint32_t ttcr;          /* Timer tick count register */
+    int is_counting;
 
     uint32_t picmr;         /* Interrupt mask register */
     uint32_t picsr;         /* Interrupt contrl register*/
@@ -376,6 +376,8 @@ void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
 
 /* hw/openrisc_timer.c */
 void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
+uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu);
+void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val);
 void cpu_openrisc_count_update(OpenRISCCPU *cpu);
 void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
 void cpu_openrisc_count_start(OpenRISCCPU *cpu);
diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c
index a879b2b539..c6a945f0df 100644
--- a/target/openrisc/machine.c
+++ b/target/openrisc/machine.c
@@ -147,7 +147,6 @@ static const VMStateDescription vmstate_env = {
 
         VMSTATE_TIMER_PTR(timer, CPUOpenRISCState),
         VMSTATE_UINT32(ttmr, CPUOpenRISCState),
-        VMSTATE_UINT32(ttcr, CPUOpenRISCState),
 
         VMSTATE_UINT32(picmr, CPUOpenRISCState),
         VMSTATE_UINT32(picsr, CPUOpenRISCState),
diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index e138bcf9db..35be44beff 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -188,7 +188,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env,
         break;
 
     case TO_SPR(10, 1): /* TTCR */
-        env->ttcr = rb;
+        cpu_openrisc_count_set(cpu, rb);
         if (env->ttmr & TIMER_NONE) {
             return;
         }
@@ -311,7 +311,7 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env,
 
     case TO_SPR(10, 1): /* TTCR */
         cpu_openrisc_count_update(cpu);
-        return env->ttcr;
+        return cpu_openrisc_count_get(cpu);
 
     default:
         break;
-- 
2.13.5


  parent reply	other threads:[~2017-08-23  5:58 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-23  5:57 [Qemu-devel] [PATCH 0/5] OpenRISC SMP Support Stafford Horne
2017-08-23  5:57 ` [OpenRISC] " Stafford Horne
2017-08-23  5:57 ` [Qemu-devel] [PATCH 1/5] openrisc/ompic: Add OpenRISC Multicore PIC (OMPIC) Stafford Horne
2017-08-23  5:57   ` [OpenRISC] " Stafford Horne
2017-10-12 20:48   ` [Qemu-devel] " Richard Henderson
2017-10-12 20:48     ` [OpenRISC] " Richard Henderson
2017-08-23  5:57 ` [Qemu-devel] [PATCH 2/5] target/openrisc: Make coreid and numcores configurable in state Stafford Horne
2017-08-23  5:57   ` [OpenRISC] " Stafford Horne
2017-10-12 20:48   ` [Qemu-devel] " Richard Henderson
2017-10-12 20:48     ` [OpenRISC] " Richard Henderson
2017-08-23  5:57 ` Stafford Horne [this message]
2017-08-23  5:57   ` [OpenRISC] [PATCH 3/5] openrisc/cputimer: Perparation for Multicore Stafford Horne
2017-10-12 20:50   ` [Qemu-devel] " Richard Henderson
2017-10-12 20:50     ` [OpenRISC] " Richard Henderson
2017-08-23  5:57 ` [Qemu-devel] [PATCH 4/5] openrisc: Initial SMP support Stafford Horne
2017-08-23  5:57   ` [OpenRISC] " Stafford Horne
2017-10-12 21:28   ` [Qemu-devel] " Richard Henderson
2017-10-12 21:28     ` [OpenRISC] " Richard Henderson
2017-08-23  5:57 ` [Qemu-devel] [PATCH 5/5] openrisc: Only kick cpu on timeout, not on update Stafford Horne
2017-08-23  5:57   ` [OpenRISC] " Stafford Horne
2017-10-12 21:28   ` [Qemu-devel] " Richard Henderson
2017-10-12 21:28     ` [OpenRISC] " Richard Henderson
2017-10-07  0:21 ` [Qemu-devel] [PATCH 0/5] OpenRISC SMP Support Stafford Horne
2017-10-07  0:21   ` [OpenRISC] " Stafford Horne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9ff134a8c36d63ad667d94cacb5ef490e2227e1e.1503467674.git.shorne@gmail.com \
    --to=shorne@gmail.com \
    --cc=openrisc@lists.librecores.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.