replay: save/load initial state
This patch implements initial vmstate creation or loading at the start of record/replay. It is needed for rewinding the execution in the replay mode. v4 changes: - snapshots are not created by default anymore v3 changes: - added rrsnapshot option Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru> Message-Id: <20170124071746.4572.61449.stgit@PASHA-ISP> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									ac8c19ba74
								
							
						
					
					
						commit
						9c2037d0a4
					
				| @ -196,6 +196,22 @@ is recorded to the log. In replay phase the queue is matched with | ||||
| events read from the log. Therefore block devices requests are processed | ||||
| deterministically. | ||||
| 
 | ||||
| Snapshotting | ||||
| ------------ | ||||
| 
 | ||||
| New VM snapshots may be created in replay mode. They can be used later | ||||
| to recover the desired VM state. All VM states created in replay mode | ||||
| are associated with the moment of time in the replay scenario. | ||||
| After recovering the VM state replay will start from that position. | ||||
| 
 | ||||
| Default starting snapshot name may be specified with icount field | ||||
| rrsnapshot as follows: | ||||
|  -icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name | ||||
| 
 | ||||
| This snapshot is created at start of recording and restored at start | ||||
| of replaying. It also can be loaded while replaying to roll back | ||||
| the execution. | ||||
| 
 | ||||
| Network devices | ||||
| --------------- | ||||
| 
 | ||||
|  | ||||
| @ -43,6 +43,9 @@ typedef struct ReplayNetState ReplayNetState; | ||||
| 
 | ||||
| extern ReplayMode replay_mode; | ||||
| 
 | ||||
| /* Name of the initial VM snapshot */ | ||||
| extern char *replay_snapshot; | ||||
| 
 | ||||
| /* Replay process control functions */ | ||||
| 
 | ||||
| /*! Enables recording or saving event log with specified parameters */ | ||||
| @ -149,4 +152,10 @@ void replay_unregister_net(ReplayNetState *rns); | ||||
| void replay_net_packet_event(ReplayNetState *rns, unsigned flags, | ||||
|                              const struct iovec *iov, int iovcnt); | ||||
| 
 | ||||
| /* VM state operations */ | ||||
| 
 | ||||
| /*! Called at the start of execution.
 | ||||
|     Loads or saves initial vmstate depending on execution mode. */ | ||||
| void replay_vmstate_init(void); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -3400,12 +3400,12 @@ re-inject them. | ||||
| ETEXI | ||||
| 
 | ||||
| DEF("icount", HAS_ARG, QEMU_OPTION_icount, \ | ||||
|     "-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>]\n" \ | ||||
|     "-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>,rrsnapshot=<snapshot>]\n" \ | ||||
|     "                enable virtual instruction counter with 2^N clock ticks per\n" \ | ||||
|     "                instruction, enable aligning the host and virtual clocks\n" \ | ||||
|     "                or disable real time cpu sleeping\n", QEMU_ARCH_ALL) | ||||
| STEXI | ||||
| @item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename}] | ||||
| @item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename},rrsnapshot=@var{snapshot}] | ||||
| @findex -icount | ||||
| Enable virtual instruction counter.  The virtual cpu will execute one | ||||
| instruction every 2^@var{N} ns of virtual time.  If @code{auto} is specified | ||||
| @ -3438,6 +3438,10 @@ when the shift value is high (how high depends on the host machine). | ||||
| When @option{rr} option is specified deterministic record/replay is enabled. | ||||
| Replay log is written into @var{filename} file in record mode and | ||||
| read from this file in replay mode. | ||||
| 
 | ||||
| Option rrsnapshot is used to create new vm snapshot named @var{snapshot} | ||||
| at the start of execution recording. In replay mode this option is used | ||||
| to load the initial VM state. | ||||
| ETEXI | ||||
| 
 | ||||
| DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \ | ||||
|  | ||||
| @ -59,3 +59,20 @@ void replay_vmstate_register(void) | ||||
| { | ||||
|     vmstate_register(NULL, 0, &vmstate_replay, &replay_state); | ||||
| } | ||||
| 
 | ||||
| void replay_vmstate_init(void) | ||||
| { | ||||
|     if (replay_snapshot) { | ||||
|         if (replay_mode == REPLAY_MODE_RECORD) { | ||||
|             if (save_vmstate(cur_mon, replay_snapshot) != 0) { | ||||
|                 error_report("Could not create snapshot for icount record"); | ||||
|                 exit(1); | ||||
|             } | ||||
|         } else if (replay_mode == REPLAY_MODE_PLAY) { | ||||
|             if (load_vmstate(replay_snapshot) != 0) { | ||||
|                 error_report("Could not load snapshot for icount replay"); | ||||
|                 exit(1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -26,6 +26,7 @@ | ||||
| #define HEADER_SIZE                 (sizeof(uint32_t) + sizeof(uint64_t)) | ||||
| 
 | ||||
| ReplayMode replay_mode = REPLAY_MODE_NONE; | ||||
| char *replay_snapshot; | ||||
| 
 | ||||
| /* Name of replay file  */ | ||||
| static char *replay_filename; | ||||
| @ -292,6 +293,7 @@ void replay_configure(QemuOpts *opts) | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     replay_snapshot = g_strdup(qemu_opt_get(opts, "rrsnapshot")); | ||||
|     replay_vmstate_register(); | ||||
|     replay_enable(fname, mode); | ||||
| 
 | ||||
| @ -346,6 +348,9 @@ void replay_finish(void) | ||||
|         replay_filename = NULL; | ||||
|     } | ||||
| 
 | ||||
|     g_free(replay_snapshot); | ||||
|     replay_snapshot = NULL; | ||||
| 
 | ||||
|     replay_finish_events(); | ||||
|     replay_mutex_destroy(); | ||||
| } | ||||
|  | ||||
							
								
								
									
										7
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								vl.c
									
									
									
									
									
								
							| @ -465,6 +465,9 @@ static QemuOptsList qemu_icount_opts = { | ||||
|         }, { | ||||
|             .name = "rrfile", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, { | ||||
|             .name = "rrsnapshot", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, | ||||
|         { /* end of list */ } | ||||
|     }, | ||||
| @ -4634,7 +4637,9 @@ int main(int argc, char **argv, char **envp) | ||||
|     replay_checkpoint(CHECKPOINT_RESET); | ||||
|     qemu_system_reset(VMRESET_SILENT); | ||||
|     register_global_state(); | ||||
|     if (loadvm) { | ||||
|     if (replay_mode != REPLAY_MODE_NONE) { | ||||
|         replay_vmstate_init(); | ||||
|     } else if (loadvm) { | ||||
|         if (load_vmstate(loadvm) < 0) { | ||||
|             autostart = 0; | ||||
|         } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Pavel Dovgalyuk
						Pavel Dovgalyuk