Generate double and triple faults, by Bernhard Kauer.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2563 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									a80274c31b
								
							
						
					
					
						commit
						678dde1323
					
				|  | @ -360,6 +360,8 @@ int cpu_exec(CPUState *env1) | |||
|                                  env->exception_is_int,  | ||||
|                                  env->error_code,  | ||||
|                                  env->exception_next_eip, 0); | ||||
|                     /* successfully delivered */ | ||||
|                     env->old_exception = -1; | ||||
| #elif defined(TARGET_PPC) | ||||
|                     do_interrupt(env); | ||||
| #elif defined(TARGET_MIPS) | ||||
|  |  | |||
|  | @ -515,6 +515,7 @@ typedef struct CPUX86State { | |||
|     uint32_t smbase; | ||||
|     int interrupt_request;  | ||||
|     int user_mode_only; /* user mode only simulation */ | ||||
|     int old_exception;  /* exception in flight */ | ||||
| 
 | ||||
|     CPU_COMMON | ||||
| 
 | ||||
|  |  | |||
|  | @ -1192,6 +1192,40 @@ void do_interrupt(int intno, int is_int, int error_code, | |||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Check nested exceptions and change to double or triple fault if | ||||
|  * needed. It should only be called, if this is not an interrupt. | ||||
|  * Returns the new exception number. | ||||
|  */ | ||||
| int check_exception(int intno, int *error_code) | ||||
| { | ||||
|     char first_contributory = env->old_exception == 0 || | ||||
|                               (env->old_exception >= 10 && | ||||
|                                env->old_exception <= 13); | ||||
|     char second_contributory = intno == 0 || | ||||
|                                (intno >= 10 && intno <= 13); | ||||
| 
 | ||||
|     if (loglevel & CPU_LOG_INT) | ||||
|         fprintf(logfile, "check_exception old: %x new %x\n", | ||||
|                 env->old_exception, intno); | ||||
| 
 | ||||
|     if (env->old_exception == EXCP08_DBLE) | ||||
|         cpu_abort(env, "triple fault"); | ||||
| 
 | ||||
|     if ((first_contributory && second_contributory) | ||||
|         || (env->old_exception == EXCP0E_PAGE && | ||||
|             (second_contributory || (intno == EXCP0E_PAGE)))) { | ||||
|         intno = EXCP08_DBLE; | ||||
|         *error_code = 0; | ||||
|     } | ||||
| 
 | ||||
|     if (second_contributory || (intno == EXCP0E_PAGE) || | ||||
|         (intno == EXCP08_DBLE)) | ||||
|         env->old_exception = intno; | ||||
| 
 | ||||
|     return intno; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Signal an interruption. It is executed in the main CPU loop. | ||||
|  * is_int is TRUE if coming from the int instruction. next_eip is the | ||||
|  | @ -1201,6 +1235,9 @@ void do_interrupt(int intno, int is_int, int error_code, | |||
| void raise_interrupt(int intno, int is_int, int error_code,  | ||||
|                      int next_eip_addend) | ||||
| { | ||||
|     if (!is_int) | ||||
|         intno = check_exception(intno, &error_code); | ||||
| 
 | ||||
|     env->exception_index = intno; | ||||
|     env->error_code = error_code; | ||||
|     env->exception_is_int = is_int; | ||||
|  | @ -1211,6 +1248,8 @@ void raise_interrupt(int intno, int is_int, int error_code, | |||
| /* same as raise_exception_err, but do not restore global registers */ | ||||
| static void raise_exception_err_norestore(int exception_index, int error_code) | ||||
| { | ||||
|     exception_index = check_exception(exception_index, &error_code); | ||||
| 
 | ||||
|     env->exception_index = exception_index; | ||||
|     env->error_code = error_code; | ||||
|     env->exception_is_int = 0; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 ths
						ths