port qemu-kvm's on_vcpu code
run_on_cpu allows to execute work on a given CPUState context. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
		
							parent
							
								
									1fbb22e5f8
								
							
						
					
					
						commit
						e82bcec25f
					
				| @ -821,6 +821,7 @@ void cpu_watchpoint_remove_all(CPUState *env, int mask); | ||||
| 
 | ||||
| void cpu_single_step(CPUState *env, int enabled); | ||||
| void cpu_reset(CPUState *s); | ||||
| void run_on_cpu(CPUState *env, void (*func)(void *data), void *data); | ||||
| 
 | ||||
| #define CPU_LOG_TB_OUT_ASM (1 << 0) | ||||
| #define CPU_LOG_TB_IN_ASM  (1 << 1) | ||||
|  | ||||
| @ -132,6 +132,7 @@ typedef struct icount_decr_u16 { | ||||
| 
 | ||||
| struct kvm_run; | ||||
| struct KVMState; | ||||
| struct qemu_work_item; | ||||
| 
 | ||||
| typedef struct CPUBreakpoint { | ||||
|     target_ulong pc; | ||||
| @ -204,6 +205,7 @@ typedef struct CPUWatchpoint { | ||||
|     uint32_t created;                                                   \ | ||||
|     struct QemuThread *thread;                                          \ | ||||
|     struct QemuCond *halt_cond;                                         \ | ||||
|     struct qemu_work_item *queued_work_first, *queued_work_last;        \ | ||||
|     const char *cpu_model_str;                                          \ | ||||
|     struct KVMState *kvm_state;                                         \ | ||||
|     struct kvm_run *kvm_run;                                            \ | ||||
|  | ||||
							
								
								
									
										53
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								cpus.c
									
									
									
									
									
								
							| @ -115,6 +115,8 @@ static int cpu_has_work(CPUState *env) | ||||
| { | ||||
|     if (env->stop) | ||||
|         return 1; | ||||
|     if (env->queued_work_first) | ||||
|         return 1; | ||||
|     if (env->stopped || !vm_running) | ||||
|         return 0; | ||||
|     if (!env->halted) | ||||
| @ -252,6 +254,11 @@ int qemu_cpu_self(void *env) | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) | ||||
| { | ||||
|     func(data); | ||||
| } | ||||
| 
 | ||||
| void resume_all_vcpus(void) | ||||
| { | ||||
| } | ||||
| @ -304,6 +311,7 @@ static QemuCond qemu_cpu_cond; | ||||
| /* system init */ | ||||
| static QemuCond qemu_system_cond; | ||||
| static QemuCond qemu_pause_cond; | ||||
| static QemuCond qemu_work_cond; | ||||
| 
 | ||||
| static void tcg_block_io_signals(void); | ||||
| static void kvm_block_io_signals(CPUState *env); | ||||
| @ -334,6 +342,50 @@ void qemu_main_loop_start(void) | ||||
|     qemu_cond_broadcast(&qemu_system_cond); | ||||
| } | ||||
| 
 | ||||
| void run_on_cpu(CPUState *env, void (*func)(void *data), void *data) | ||||
| { | ||||
|     struct qemu_work_item wi; | ||||
| 
 | ||||
|     if (qemu_cpu_self(env)) { | ||||
|         func(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     wi.func = func; | ||||
|     wi.data = data; | ||||
|     if (!env->queued_work_first) | ||||
|         env->queued_work_first = &wi; | ||||
|     else | ||||
|         env->queued_work_last->next = &wi; | ||||
|     env->queued_work_last = &wi; | ||||
|     wi.next = NULL; | ||||
|     wi.done = false; | ||||
| 
 | ||||
|     qemu_cpu_kick(env); | ||||
|     while (!wi.done) { | ||||
|         CPUState *self_env = cpu_single_env; | ||||
| 
 | ||||
|         qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex); | ||||
|         cpu_single_env = self_env; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void flush_queued_work(CPUState *env) | ||||
| { | ||||
|     struct qemu_work_item *wi; | ||||
| 
 | ||||
|     if (!env->queued_work_first) | ||||
|         return; | ||||
| 
 | ||||
|     while ((wi = env->queued_work_first)) { | ||||
|         env->queued_work_first = wi->next; | ||||
|         wi->func(wi->data); | ||||
|         wi->done = true; | ||||
|     } | ||||
|     env->queued_work_last = NULL; | ||||
|     qemu_cond_broadcast(&qemu_work_cond); | ||||
| } | ||||
| 
 | ||||
| static void qemu_wait_io_event_common(CPUState *env) | ||||
| { | ||||
|     if (env->stop) { | ||||
| @ -341,6 +393,7 @@ static void qemu_wait_io_event_common(CPUState *env) | ||||
|         env->stopped = 1; | ||||
|         qemu_cond_signal(&qemu_pause_cond); | ||||
|     } | ||||
|     flush_queued_work(env); | ||||
| } | ||||
| 
 | ||||
| static void qemu_wait_io_event(CPUState *env) | ||||
|  | ||||
| @ -249,6 +249,14 @@ void qemu_notify_event(void); | ||||
| void qemu_cpu_kick(void *env); | ||||
| int qemu_cpu_self(void *env); | ||||
| 
 | ||||
| /* work queue */ | ||||
| struct qemu_work_item { | ||||
|     struct qemu_work_item *next; | ||||
|     void (*func)(void *data); | ||||
|     void *data; | ||||
|     int done; | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_USER_ONLY | ||||
| #define qemu_init_vcpu(env) do { } while (0) | ||||
| #else | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Marcelo Tosatti
						Marcelo Tosatti