sun4m: fix slavio timer RUN/STOP bit
The sun4m architecture has one 'system' timer and one timer per CPU.
The CPU timers can be configured in two modes:
  * 22 bits Counter/Timer. Periodic interrupts.
  * 54 bits User timer. For profiling. In this mode, the Run/Stop bit
    controls the timer.
The run/stop bit controls the timer only when it is in "User" mode, but
its state shall be persistent.
Signed-off-by: Olivier Danet <odanet@caramail.com>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
			
			
This commit is contained in:
		
							parent
							
								
									f9681f116c
								
							
						
					
					
						commit
						ead4cf04f8
					
				@ -51,7 +51,7 @@ typedef struct CPUTimerState {
 | 
				
			|||||||
    ptimer_state *timer;
 | 
					    ptimer_state *timer;
 | 
				
			||||||
    uint32_t count, counthigh, reached;
 | 
					    uint32_t count, counthigh, reached;
 | 
				
			||||||
    /* processor only */
 | 
					    /* processor only */
 | 
				
			||||||
    uint32_t running;
 | 
					    uint32_t run;
 | 
				
			||||||
    uint64_t limit;
 | 
					    uint64_t limit;
 | 
				
			||||||
} CPUTimerState;
 | 
					} CPUTimerState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -177,7 +177,7 @@ static uint64_t slavio_timer_mem_readl(void *opaque, hwaddr addr,
 | 
				
			|||||||
        // only available in processor counter/timer
 | 
					        // only available in processor counter/timer
 | 
				
			||||||
        // read start/stop status
 | 
					        // read start/stop status
 | 
				
			||||||
        if (timer_index > 0) {
 | 
					        if (timer_index > 0) {
 | 
				
			||||||
            ret = t->running;
 | 
					            ret = t->run;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            ret = 0;
 | 
					            ret = 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -260,16 +260,15 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
 | 
				
			|||||||
    case TIMER_STATUS:
 | 
					    case TIMER_STATUS:
 | 
				
			||||||
        if (slavio_timer_is_user(tc)) {
 | 
					        if (slavio_timer_is_user(tc)) {
 | 
				
			||||||
            // start/stop user counter
 | 
					            // start/stop user counter
 | 
				
			||||||
            if ((val & 1) && !t->running) {
 | 
					            if (val & 1) {
 | 
				
			||||||
                trace_slavio_timer_mem_writel_status_start(timer_index);
 | 
					                trace_slavio_timer_mem_writel_status_start(timer_index);
 | 
				
			||||||
                ptimer_run(t->timer, 0);
 | 
					                ptimer_run(t->timer, 0);
 | 
				
			||||||
                t->running = 1;
 | 
					            } else {
 | 
				
			||||||
            } else if (!(val & 1) && t->running) {
 | 
					 | 
				
			||||||
                trace_slavio_timer_mem_writel_status_stop(timer_index);
 | 
					                trace_slavio_timer_mem_writel_status_stop(timer_index);
 | 
				
			||||||
                ptimer_stop(t->timer);
 | 
					                ptimer_stop(t->timer);
 | 
				
			||||||
                t->running = 0;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        t->run = val & 1;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case TIMER_MODE:
 | 
					    case TIMER_MODE:
 | 
				
			||||||
        if (timer_index == 0) {
 | 
					        if (timer_index == 0) {
 | 
				
			||||||
@ -284,8 +283,9 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
 | 
				
			|||||||
                    if (val & processor) { // counter -> user timer
 | 
					                    if (val & processor) { // counter -> user timer
 | 
				
			||||||
                        qemu_irq_lower(curr_timer->irq);
 | 
					                        qemu_irq_lower(curr_timer->irq);
 | 
				
			||||||
                        // counters are always running
 | 
					                        // counters are always running
 | 
				
			||||||
 | 
					                        if (!curr_timer->run) {
 | 
				
			||||||
                            ptimer_stop(curr_timer->timer);
 | 
					                            ptimer_stop(curr_timer->timer);
 | 
				
			||||||
                        curr_timer->running = 0;
 | 
					                        }
 | 
				
			||||||
                        // user timer limit is always the same
 | 
					                        // user timer limit is always the same
 | 
				
			||||||
                        curr_timer->limit = TIMER_MAX_COUNT64;
 | 
					                        curr_timer->limit = TIMER_MAX_COUNT64;
 | 
				
			||||||
                        ptimer_set_limit(curr_timer->timer,
 | 
					                        ptimer_set_limit(curr_timer->timer,
 | 
				
			||||||
@ -296,13 +296,8 @@ static void slavio_timer_mem_writel(void *opaque, hwaddr addr,
 | 
				
			|||||||
                        s->cputimer_mode |= processor;
 | 
					                        s->cputimer_mode |= processor;
 | 
				
			||||||
                        trace_slavio_timer_mem_writel_mode_user(timer_index);
 | 
					                        trace_slavio_timer_mem_writel_mode_user(timer_index);
 | 
				
			||||||
                    } else { // user timer -> counter
 | 
					                    } else { // user timer -> counter
 | 
				
			||||||
                        // stop the user timer if it is running
 | 
					 | 
				
			||||||
                        if (curr_timer->running) {
 | 
					 | 
				
			||||||
                            ptimer_stop(curr_timer->timer);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        // start the counter
 | 
					                        // start the counter
 | 
				
			||||||
                        ptimer_run(curr_timer->timer, 0);
 | 
					                        ptimer_run(curr_timer->timer, 0);
 | 
				
			||||||
                        curr_timer->running = 1;
 | 
					 | 
				
			||||||
                        // clear this processors user timer bit in config
 | 
					                        // clear this processors user timer bit in config
 | 
				
			||||||
                        // register
 | 
					                        // register
 | 
				
			||||||
                        s->cputimer_mode &= ~processor;
 | 
					                        s->cputimer_mode &= ~processor;
 | 
				
			||||||
@ -340,7 +335,7 @@ static const VMStateDescription vmstate_timer = {
 | 
				
			|||||||
        VMSTATE_UINT32(count, CPUTimerState),
 | 
					        VMSTATE_UINT32(count, CPUTimerState),
 | 
				
			||||||
        VMSTATE_UINT32(counthigh, CPUTimerState),
 | 
					        VMSTATE_UINT32(counthigh, CPUTimerState),
 | 
				
			||||||
        VMSTATE_UINT32(reached, CPUTimerState),
 | 
					        VMSTATE_UINT32(reached, CPUTimerState),
 | 
				
			||||||
        VMSTATE_UINT32(running, CPUTimerState),
 | 
					        VMSTATE_UINT32(run    , CPUTimerState),
 | 
				
			||||||
        VMSTATE_PTIMER(timer, CPUTimerState),
 | 
					        VMSTATE_PTIMER(timer, CPUTimerState),
 | 
				
			||||||
        VMSTATE_END_OF_LIST()
 | 
					        VMSTATE_END_OF_LIST()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -373,7 +368,7 @@ static void slavio_timer_reset(DeviceState *d)
 | 
				
			|||||||
            ptimer_set_limit(curr_timer->timer,
 | 
					            ptimer_set_limit(curr_timer->timer,
 | 
				
			||||||
                             LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
 | 
					                             LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
 | 
				
			||||||
            ptimer_run(curr_timer->timer, 0);
 | 
					            ptimer_run(curr_timer->timer, 0);
 | 
				
			||||||
            curr_timer->running = 1;
 | 
					            curr_timer->run = 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    s->cputimer_mode = 0;
 | 
					    s->cputimer_mode = 0;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user