@ -97,6 +97,14 @@ static void patch_bugcheck_data(WinDumpHeader64 *h, Error **errp)
error_setg ( errp , " win-dump: failed to read bugcheck data " ) ;
return ;
}
/*
* If BugcheckCode wasn ' t saved , we consider guest OS as alive .
*/
if ( ! h - > BugcheckCode ) {
h - > BugcheckCode = LIVE_SYSTEM_DUMP ;
}
}
/*
@ -177,12 +185,139 @@ try_again:
h - > KdDebuggerDataBlock = KdDebuggerDataBlock ;
}
struct saved_context {
WinContext ctx ;
uint64_t addr ;
} ;
static void patch_and_save_context ( WinDumpHeader64 * h ,
struct saved_context * saved_ctx ,
Error * * errp )
{
uint64_t KiProcessorBlock ;
uint16_t OffsetPrcbContext ;
CPUState * cpu ;
int i = 0 ;
if ( cpu_memory_rw_debug ( first_cpu ,
h - > KdDebuggerDataBlock + KDBG_KI_PROCESSOR_BLOCK_OFFSET64 ,
( uint8_t * ) & KiProcessorBlock , sizeof ( KiProcessorBlock ) , 0 ) ) {
error_setg ( errp , " win-dump: failed to read KiProcessorBlock " ) ;
return ;
}
if ( cpu_memory_rw_debug ( first_cpu ,
h - > KdDebuggerDataBlock + KDBG_OFFSET_PRCB_CONTEXT_OFFSET64 ,
( uint8_t * ) & OffsetPrcbContext , sizeof ( OffsetPrcbContext ) , 0 ) ) {
error_setg ( errp , " win-dump: failed to read OffsetPrcbContext " ) ;
return ;
}
CPU_FOREACH ( cpu ) {
X86CPU * x86_cpu = X86_CPU ( cpu ) ;
CPUX86State * env = & x86_cpu - > env ;
uint64_t Prcb ;
uint64_t Context ;
WinContext ctx ;
if ( cpu_memory_rw_debug ( first_cpu ,
KiProcessorBlock + i * sizeof ( uint64_t ) ,
( uint8_t * ) & Prcb , sizeof ( Prcb ) , 0 ) ) {
error_setg ( errp , " win-dump: failed to read "
" CPU #%d PRCB location " , i ) ;
return ;
}
if ( cpu_memory_rw_debug ( first_cpu ,
Prcb + OffsetPrcbContext ,
( uint8_t * ) & Context , sizeof ( Context ) , 0 ) ) {
error_setg ( errp , " win-dump: failed to read "
" CPU #%d ContextFrame location " , i ) ;
return ;
}
saved_ctx [ i ] . addr = Context ;
ctx = ( WinContext ) {
. ContextFlags = WIN_CTX_ALL ,
. MxCsr = env - > mxcsr ,
. SegEs = env - > segs [ 0 ] . selector ,
. SegCs = env - > segs [ 1 ] . selector ,
. SegSs = env - > segs [ 2 ] . selector ,
. SegDs = env - > segs [ 3 ] . selector ,
. SegFs = env - > segs [ 4 ] . selector ,
. SegGs = env - > segs [ 5 ] . selector ,
. EFlags = cpu_compute_eflags ( env ) ,
. Dr0 = env - > dr [ 0 ] ,
. Dr1 = env - > dr [ 1 ] ,
. Dr2 = env - > dr [ 2 ] ,
. Dr3 = env - > dr [ 3 ] ,
. Dr6 = env - > dr [ 6 ] ,
. Dr7 = env - > dr [ 7 ] ,
. Rax = env - > regs [ R_EAX ] ,
. Rbx = env - > regs [ R_EBX ] ,
. Rcx = env - > regs [ R_ECX ] ,
. Rdx = env - > regs [ R_EDX ] ,
. Rsp = env - > regs [ R_ESP ] ,
. Rbp = env - > regs [ R_EBP ] ,
. Rsi = env - > regs [ R_ESI ] ,
. Rdi = env - > regs [ R_EDI ] ,
. R8 = env - > regs [ 8 ] ,
. R9 = env - > regs [ 9 ] ,
. R10 = env - > regs [ 10 ] ,
. R11 = env - > regs [ 11 ] ,
. R12 = env - > regs [ 12 ] ,
. R13 = env - > regs [ 13 ] ,
. R14 = env - > regs [ 14 ] ,
. R15 = env - > regs [ 15 ] ,
. Rip = env - > eip ,
. FltSave = {
. MxCsr = env - > mxcsr ,
} ,
} ;
if ( cpu_memory_rw_debug ( first_cpu , Context ,
( uint8_t * ) & saved_ctx [ i ] . ctx , sizeof ( WinContext ) , 0 ) ) {
error_setg ( errp , " win-dump: failed to save CPU #%d context " , i ) ;
return ;
}
if ( cpu_memory_rw_debug ( first_cpu , Context ,
( uint8_t * ) & ctx , sizeof ( WinContext ) , 1 ) ) {
error_setg ( errp , " win-dump: failed to write CPU #%d context " , i ) ;
return ;
}
i + + ;
}
}
static void restore_context ( WinDumpHeader64 * h ,
struct saved_context * saved_ctx )
{
int i ;
Error * err = NULL ;
for ( i = 0 ; i < h - > NumberProcessors ; i + + ) {
if ( cpu_memory_rw_debug ( first_cpu , saved_ctx [ i ] . addr ,
( uint8_t * ) & saved_ctx [ i ] . ctx , sizeof ( WinContext ) , 1 ) ) {
error_setg ( & err , " win-dump: failed to restore CPU #%d context " , i ) ;
warn_report_err ( err ) ;
}
}
}
void create_win_dump ( DumpState * s , Error * * errp )
{
WinDumpHeader64 * h = ( WinDumpHeader64 * ) ( s - > guest_note +
VMCOREINFO_ELF_NOTE_HDR_SIZE ) ;
X86CPU * first_x86_cpu = X86_CPU ( first_cpu ) ;
uint64_t saved_cr3 = first_x86_cpu - > env . cr [ 3 ] ;
struct saved_context * saved_ctx = NULL ;
Error * local_err = NULL ;
if ( s - > guest_note_size ! = sizeof ( WinDumpHeader64 ) +
@ -212,20 +347,37 @@ void create_win_dump(DumpState *s, Error **errp)
patch_header ( h ) ;
saved_ctx = g_new ( struct saved_context , h - > NumberProcessors ) ;
/*
* Always patch context because there is no way
* to determine if the system - saved context is valid
*/
patch_and_save_context ( h , saved_ctx , & local_err ) ;
if ( local_err ) {
error_propagate ( errp , local_err ) ;
goto out_free ;
}
s - > total_size = h - > RequiredDumpSpace ;
s - > written_size = qemu_write_full ( s - > fd , h , sizeof ( * h ) ) ;
if ( s - > written_size ! = sizeof ( * h ) ) {
error_setg ( errp , QERR_IO_ERROR ) ;
goto out_cr3 ;
goto out_restore ;
}
write_runs ( s , h , & local_err ) ;
if ( local_err ) {
error_propagate ( errp , local_err ) ;
goto out_cr3 ;
goto out_restore ;
}
out_restore :
restore_context ( h , saved_ctx ) ;
out_free :
g_free ( saved_ctx ) ;
out_cr3 :
first_x86_cpu - > env . cr [ 3 ] = saved_cr3 ;