cpus: make pause_all_cpus() play with SMP on single threaded TCG
pause_all_cpus() is sometimes called from a VCPU thread (e.g. s390x during special reset). It cannot deal with multiple VCPUs per Thread (single threaded TCG) yet. Booting an s390x guest with -smp 2 and single threaded TCG from disk currently fails. The DIAG 308 will issue a pause_all_cpus() and wait forever for the CPUs to actually stop. But it is waiting for itself. So let's stop all VCPUs belonging to the current thread. Factor out stopping of a VCPU. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20171129191215.11323-1-david@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									09df29b665
								
							
						
					
					
						commit
						ebd05fea9b
					
				
							
								
								
									
										32
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								cpus.c
									
									
									
									
									
								
							| @ -1057,13 +1057,22 @@ static void qemu_tcg_destroy_vcpu(CPUState *cpu) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static void qemu_cpu_stop(CPUState *cpu, bool exit) | ||||
| { | ||||
|     g_assert(qemu_cpu_is_self(cpu)); | ||||
|     cpu->stop = false; | ||||
|     cpu->stopped = true; | ||||
|     if (exit) { | ||||
|         cpu_exit(cpu); | ||||
|     } | ||||
|     qemu_cond_broadcast(&qemu_pause_cond); | ||||
| } | ||||
| 
 | ||||
| static void qemu_wait_io_event_common(CPUState *cpu) | ||||
| { | ||||
|     atomic_mb_set(&cpu->thread_kicked, false); | ||||
|     if (cpu->stop) { | ||||
|         cpu->stop = false; | ||||
|         cpu->stopped = true; | ||||
|         qemu_cond_broadcast(&qemu_pause_cond); | ||||
|         qemu_cpu_stop(cpu, false); | ||||
|     } | ||||
|     process_queued_cpu_work(cpu); | ||||
| } | ||||
| @ -1610,12 +1619,12 @@ void pause_all_vcpus(void) | ||||
| 
 | ||||
|     qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false); | ||||
|     CPU_FOREACH(cpu) { | ||||
|         cpu->stop = true; | ||||
|         qemu_cpu_kick(cpu); | ||||
|     } | ||||
| 
 | ||||
|     if (qemu_in_vcpu_thread()) { | ||||
|         cpu_stop_current(); | ||||
|         if (qemu_cpu_is_self(cpu)) { | ||||
|             qemu_cpu_stop(cpu, true); | ||||
|         } else { | ||||
|             cpu->stop = true; | ||||
|             qemu_cpu_kick(cpu); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     while (!all_vcpus_paused()) { | ||||
| @ -1799,10 +1808,7 @@ void qemu_init_vcpu(CPUState *cpu) | ||||
| void cpu_stop_current(void) | ||||
| { | ||||
|     if (current_cpu) { | ||||
|         current_cpu->stop = false; | ||||
|         current_cpu->stopped = true; | ||||
|         cpu_exit(current_cpu); | ||||
|         qemu_cond_broadcast(&qemu_pause_cond); | ||||
|         qemu_cpu_stop(current_cpu, true); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 David Hildenbrand
						David Hildenbrand