]> git.proxmox.com Git - mirror_qemu.git/commitdiff
openrisc/cputimer: Perparation for Multicore
authorStafford Horne <shorne@gmail.com>
Mon, 21 Aug 2017 21:37:10 +0000 (06:37 +0900)
committerStafford Horne <shorne@gmail.com>
Fri, 20 Oct 2017 21:35:47 +0000 (06:35 +0900)
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.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Stafford Horne <shorne@gmail.com>
hw/openrisc/cputimer.c
target/openrisc/cpu.c
target/openrisc/cpu.h
target/openrisc/machine.c
target/openrisc/sys_helper.c

index febc469170e74f75c0f2e587bb42db7e473483d6..4c5415ff75d0d5038c56e32bcdaf69135f461c70 100644 (file)
 
 #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);
+    }
 }
index af9cdcc10249b6fe161558b2a80114a4cd81188b..a6d20496848e42242b2909f9d8095b5aebfff0e7 100644 (file)
@@ -61,7 +61,6 @@ static void openrisc_cpu_reset(CPUState *s)
     cpu->env.picsr = 0x00000000;
 
     cpu->env.ttmr = 0x00000000;
-    cpu->env.ttcr = 0x00000000;
 #endif
 }
 
index f51b89a11ce633c2e6749ccfaa7e94631a2dc8a3..892dc4210fa71ce4880c7ea89279e642107c4666 100644 (file)
@@ -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*/
@@ -371,6 +371,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);
index a20cce705d3d551daaccd653d925373b995149d1..0a793eb14d0388043bce74bbeadd6525b3fe9100 100644 (file)
@@ -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),
index dc6e5cc7f27df68e96df951dd4bb92a4f6c51583..9fb7d86b4bae939837115eda86e31f18c99a1ba9 100644 (file)
@@ -189,7 +189,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;
         }
@@ -312,7 +312,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;