diff options
-rw-r--r-- | hw/openrisc/cputimer.c | 62 | ||||
-rw-r--r-- | target/openrisc/cpu.c | 1 | ||||
-rw-r--r-- | target/openrisc/cpu.h | 4 | ||||
-rw-r--r-- | target/openrisc/machine.c | 1 | ||||
-rw-r--r-- | 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 af9cdcc102..a6d2049684 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 f51b89a11c..892dc4210f 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*/ @@ -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); diff --git a/target/openrisc/machine.c b/target/openrisc/machine.c index a20cce705d..0a793eb14d 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 dc6e5cc7f2..9fb7d86b4b 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -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; |