cpus: reorganize signal handling code
Move the KVM "eat signals" code under CONFIG_LINUX, in preparation for moving it to kvm-all.c; reraise non-MCE SIGBUS immediately, without passing it to KVM. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									20e0ff59a9
								
							
						
					
					
						commit
						a16fc07ebd
					
				
							
								
								
									
										105
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								cpus.c
									
									
									
									
									
								
							| @ -922,6 +922,10 @@ static void sigbus_reraise(void) | ||||
| 
 | ||||
| static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx) | ||||
| { | ||||
|     if (siginfo->si_code != BUS_MCEERR_AO && siginfo->si_code != BUS_MCEERR_AR) { | ||||
|         sigbus_reraise(); | ||||
|     } | ||||
| 
 | ||||
|     if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { | ||||
|         sigbus_reraise(); | ||||
|     } | ||||
| @ -939,55 +943,6 @@ static void qemu_init_sigbus(void) | ||||
|     prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0); | ||||
| } | ||||
| 
 | ||||
| static void qemu_kvm_eat_signals(CPUState *cpu) | ||||
| { | ||||
|     struct timespec ts = { 0, 0 }; | ||||
|     siginfo_t siginfo; | ||||
|     sigset_t waitset; | ||||
|     sigset_t chkset; | ||||
|     int r; | ||||
| 
 | ||||
|     sigemptyset(&waitset); | ||||
|     sigaddset(&waitset, SIG_IPI); | ||||
|     sigaddset(&waitset, SIGBUS); | ||||
| 
 | ||||
|     do { | ||||
|         r = sigtimedwait(&waitset, &siginfo, &ts); | ||||
|         if (r == -1 && !(errno == EAGAIN || errno == EINTR)) { | ||||
|             perror("sigtimedwait"); | ||||
|             exit(1); | ||||
|         } | ||||
| 
 | ||||
|         switch (r) { | ||||
|         case SIGBUS: | ||||
|             if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) { | ||||
|                 sigbus_reraise(); | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         r = sigpending(&chkset); | ||||
|         if (r == -1) { | ||||
|             perror("sigpending"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); | ||||
| } | ||||
| 
 | ||||
| #else /* !CONFIG_LINUX */ | ||||
| 
 | ||||
| static void qemu_init_sigbus(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static void qemu_kvm_eat_signals(CPUState *cpu) | ||||
| { | ||||
| } | ||||
| #endif /* !CONFIG_LINUX */ | ||||
| 
 | ||||
| #ifndef _WIN32 | ||||
| static void dummy_signal(int sig) | ||||
| { | ||||
| } | ||||
| @ -1012,12 +967,58 @@ static void qemu_kvm_init_cpu_signals(CPUState *cpu) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #else /* _WIN32 */ | ||||
| static void qemu_kvm_eat_signals(CPUState *cpu) | ||||
| { | ||||
|     struct timespec ts = { 0, 0 }; | ||||
|     siginfo_t siginfo; | ||||
|     sigset_t waitset; | ||||
|     sigset_t chkset; | ||||
|     int r; | ||||
| 
 | ||||
|     sigemptyset(&waitset); | ||||
|     sigaddset(&waitset, SIG_IPI); | ||||
|     sigaddset(&waitset, SIGBUS); | ||||
| 
 | ||||
|     do { | ||||
|         r = sigtimedwait(&waitset, &siginfo, &ts); | ||||
|         if (r == -1 && !(errno == EAGAIN || errno == EINTR)) { | ||||
|             perror("sigtimedwait"); | ||||
|             exit(1); | ||||
|         } | ||||
| 
 | ||||
|         switch (r) { | ||||
|         case SIGBUS: | ||||
|             if (siginfo.si_code != BUS_MCEERR_AO && siginfo.si_code != BUS_MCEERR_AR) { | ||||
|                 sigbus_reraise(); | ||||
|             } | ||||
|             if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) { | ||||
|                 sigbus_reraise(); | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         r = sigpending(&chkset); | ||||
|         if (r == -1) { | ||||
|             perror("sigpending"); | ||||
|             exit(1); | ||||
|         } | ||||
|     } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); | ||||
| } | ||||
| #else /* !CONFIG_LINUX */ | ||||
| static void qemu_init_sigbus(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static void qemu_kvm_eat_signals(CPUState *cpu) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static void qemu_kvm_init_cpu_signals(CPUState *cpu) | ||||
| { | ||||
|     abort(); | ||||
| } | ||||
| #endif /* _WIN32 */ | ||||
| #endif /* !CONFIG_LINUX */ | ||||
| 
 | ||||
| static QemuMutex qemu_global_mutex; | ||||
| 
 | ||||
|  | ||||
| @ -284,6 +284,15 @@ void qemu_anon_ram_free(void *ptr, size_t size); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(CONFIG_LINUX) | ||||
| #ifndef BUS_MCEERR_AR | ||||
| #define BUS_MCEERR_AR 4 | ||||
| #endif | ||||
| #ifndef BUS_MCEERR_AO | ||||
| #define BUS_MCEERR_AO 5 | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__linux__) && \ | ||||
|     (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) | ||||
|    /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
 | ||||
|  | ||||
| @ -64,13 +64,6 @@ | ||||
|  * 255 kvm_msr_entry structs */ | ||||
| #define MSR_BUF_SIZE 4096 | ||||
| 
 | ||||
| #ifndef BUS_MCEERR_AR | ||||
| #define BUS_MCEERR_AR 4 | ||||
| #endif | ||||
| #ifndef BUS_MCEERR_AO | ||||
| #define BUS_MCEERR_AO 5 | ||||
| #endif | ||||
| 
 | ||||
| const KVMCapabilityInfo kvm_arch_required_capabilities[] = { | ||||
|     KVM_CAP_INFO(SET_TSS_ADDR), | ||||
|     KVM_CAP_INFO(EXT_CPUID), | ||||
| @ -469,9 +462,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) | ||||
|     ram_addr_t ram_addr; | ||||
|     hwaddr paddr; | ||||
| 
 | ||||
|     if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) { | ||||
|         return 1; | ||||
|     } | ||||
|     assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO); | ||||
| 
 | ||||
|     /* Because the MCE happened while running the VCPU, KVM could have
 | ||||
|      * injected action required MCEs too.  Action optional MCEs should | ||||
| @ -504,9 +495,7 @@ int kvm_arch_on_sigbus(int code, void *addr) | ||||
| { | ||||
|     X86CPU *cpu = X86_CPU(first_cpu); | ||||
| 
 | ||||
|     if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) { | ||||
|         return 1; | ||||
|     } | ||||
|     assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO); | ||||
| 
 | ||||
|     if (code == BUS_MCEERR_AR) { | ||||
|         hardware_memory_error(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Paolo Bonzini
						Paolo Bonzini