Limit ptimer rate to something achievable
If a guest sets very short timeouts, and asks for a timer to be reloaded on timeout, QEMU can go to 100%CPU utilisation and become unresponsive, as it is spending all its time generating timeout interrupts. On real hardware this doesn't matter, as the interrupts are just coalesced, and the effect is to have the interrupt asserted all the time. This patch is a band-aid, that prevents timeouts less than 10 microseconds from being set. 10 microseconds is a limit that was determined empirically on a variety of machines as the shortest that allowed QEMU to pick up a control-a c sequence to get at the monitor. Reported-by: Anna Lyons <anna.lyons@nicta.com.au> Signed-off-by: Peter Chubb <peter.chubb@nicta.com.au> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
							parent
							
								
									dfe47e7029
								
							
						
					
					
						commit
						cf36b31db2
					
				
							
								
								
									
										13
									
								
								hw/ptimer.c
								
								
								
								
							
							
						
						
									
										13
									
								
								hw/ptimer.c
								
								
								
								
							| 
						 | 
				
			
			@ -180,6 +180,19 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
 | 
			
		|||
   count = limit.  */
 | 
			
		||||
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
 | 
			
		||||
{
 | 
			
		||||
    /*
 | 
			
		||||
     * Artificially limit timeout rate to something
 | 
			
		||||
     * achievable under QEMU.  Otherwise, QEMU spends all
 | 
			
		||||
     * its time generating timer interrupts, and there
 | 
			
		||||
     * is no forward progress.
 | 
			
		||||
     * About ten microseconds is the fastest that really works
 | 
			
		||||
     * on the current generation of host machines.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    if (limit * s->period < 10000 && s->period) {
 | 
			
		||||
        limit = 10000 / s->period;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->limit = limit;
 | 
			
		||||
    if (reload)
 | 
			
		||||
        s->delta = limit;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue