From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DFsrJ-0006Yj-ET for qemu-devel@nongnu.org; Mon, 28 Mar 2005 06:56:41 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DFsp2-0005an-2h for qemu-devel@nongnu.org; Mon, 28 Mar 2005 06:54:23 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DFsoP-00058p-E9 for qemu-devel@nongnu.org; Mon, 28 Mar 2005 06:53:41 -0500 Received: from [217.204.41.189] (helo=kula.newsnow.net) by monty-python.gnu.org with esmtp (TLSv1:DES-CBC3-SHA:168) (Exim 4.34) id 1DFsVX-00026c-CC for qemu-devel@nongnu.org; Mon, 28 Mar 2005 06:34:12 -0500 Message-ID: <4247EBB0.6090409@praguespringpeople.org> Date: Mon, 28 Mar 2005 13:34:08 +0200 From: Struan Bartlett MIME-Version: 1.0 Subject: [patch] Re: [Qemu-devel] Suggestion - trap window-close of VM References: <4246FBD8.7000403@praguespringpeople.org> In-Reply-To: <4246FBD8.7000403@praguespringpeople.org> Content-Type: multipart/mixed; boundary="------------060205090003010304010702" Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------060205090003010304010702 Content-Type: multipart/alternative; boundary="------------010108070505030301000405" --------------010108070505030301000405 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Hi, I've attached a patch against the 2005-03-26 snapshot that implements two '-on-quit' options for the emulator window: ignore-unless-halted and suspend-unless-halted, that aim to make it safe to allow naive users to (try to) close the VM window by trapping requests to shutdown and either ignoring them or forcing a save of the VM state before obeying them. Caveat: I'll come clean straight away that the patch is implemented using a nasty TARGET_i386-specific hack that detects whether the guest operating system has permanently halted by looking to see if the last instruction executed was 0xF4 and, if so, whether the IF flag is cleared. Saying that, this system appears to work reasonably well on my Pentium host running a Windows 2000 guest, but I have not tested it on any other systems. Usage: 1. If you provide naive users with a variation on the following command line, then you can let your naive users (try to) close the VM window as much as they like. Unless the guest has permanently halted, attempts to close the VM window should save the VM state to 'suspended.qemu' in the current working directory before qemu exits. The same command line will restart the VM where it left off. Then, once the guest has permanently halted, qemu will delete the suspended.qemu file so that the next launch of qemu will boot afresh: qemu -hda win2k.raw -m 64 -monitor null -loadvm suspended.qemu -on-quit suspend-unless-halted 2. Alternatively, the following command will make qemu ignore the user's request to close the emulator window unless the guest has already permanently halted: qemu -hda win2k.raw -m 64 -monitor null -on-quit ignore-unless-halted 3. If you combine this with a test of whether qemu is already running, then it should be safe to let naive users try to both launch and to close qemu as much as they like. e.g. killall -0 qemu 2>/dev/null; if [ $? == 1 ]; then qemu -hda win2k.raw -m 64 -monitor null -loadvm suspended.qemu -on-quit suspend-unless-halted; fi & 4. Finally, if your leave out the -on-quit option altogether, then qemu's behaviour should remain completely unchanged. I hope this is useful for some i386/W2K users out there. Any constructive criticism appreciated. If you know how I could improve permanent halt detection (that doesn't require in-depth knowledge of APM or ACPI) then please let me know. Struan Struan Bartlett wrote: > Ryan Rempel wrote: > >>On Mon, Nov 29, 2004 at 21:46:54 +0100, Lennert Buytenhek wrote >> >> >>>On Mon, Nov 29, 2004 at 08:43:56PM +0000, Richard Neill wrote: >>> >>> >>>>A thought that occurred to me. If one is running a virtual machine (eg >>>>copy of WinXP), then simply closing the qemu window is a really bad >>>>idea, since it will effectively crash the guest. >>>> >>>> >>>Related thought -- it would be way cool if we could make killing qemu >>>do exactly happens when you press the power button on an ACPI-capable >>>machine with any recent OS on it (auto shutdown.) >>> >>> >>I was wondering if anyone has followed up on this suggestion. I'm >>putting together a Qemu-based setup for some relatively naive users, >>and ideally I'd like to be able to deal with this in a reasonable >>elegant way (the ACPI hook sounds very elegant indeed). >> >>Alternatively, how do people deal with the problem of naive users who >>might just close the Qemu window without shutting down the guest >>properly? I'm working in a KDE environment -- perhaps there is a way >>in KDE to prevent the close button from appearing? But that wouldn't >>catch every case either (for instance, if the user were to shut down >>the host). >> > This sounds like a good idea. An alternative solution, that might be > more straightforward to implement if Qemu doesn't implement ACPI yet, > would be for the kill signal to simply cause Qemu to do the equivalent > of entering 'stop' and 'savevm ' into the monitor. > >------------------------------------------------------------------------ > >_______________________________________________ >Qemu-devel mailing list >Qemu-devel@nongnu.org >http://lists.nongnu.org/mailman/listinfo/qemu-devel > > --------------010108070505030301000405 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7bit Hi,

I've attached a patch against the 2005-03-26 snapshot that implements two '-on-quit' options for the emulator window: ignore-unless-halted and suspend-unless-halted, that aim to make it safe to allow naive users to (try to) close the VM window by trapping requests to shutdown and either ignoring them or forcing a save of the VM state before obeying them.

Caveat: I'll come clean straight away that the patch is implemented using a nasty TARGET_i386-specific hack that detects whether the guest operating system has permanently halted by looking to see if the last instruction executed was 0xF4 and, if so, whether the IF flag is cleared. Saying that, this system appears to work reasonably well on my Pentium host running a Windows 2000 guest, but I have not tested it on any other systems.

Usage:

1. If you provide naive users with a variation on the following command line, then you can let your naive users (try to) close the VM window as much as they like. Unless the guest has permanently halted, attempts to close the VM window should save the VM state to 'suspended.qemu' in the current working directory before qemu exits. The same command line will restart the VM where it left off. Then, once the guest has permanently halted, qemu will delete the suspended.qemu file so that the next launch of qemu will boot afresh:

qemu -hda win2k.raw -m 64 -monitor null -loadvm suspended.qemu -on-quit suspend-unless-halted

2. Alternatively, the following command will make qemu ignore the user's request to close the emulator window unless the guest has already permanently halted:

qemu -hda win2k.raw -m 64 -monitor null -on-quit ignore-unless-halted

3. If you combine this with a test of whether qemu is already running, then it should be safe to let naive users try to both launch and to close qemu as much as they like. e.g.

killall -0 qemu 2>/dev/null; if [ $? == 1 ]; then qemu -hda win2k.raw -m 64 -monitor null -loadvm suspended.qemu -on-quit suspend-unless-halted; fi &

4. Finally, if your leave out the -on-quit option altogether, then qemu's behaviour should remain completely unchanged.

I hope this is useful for some i386/W2K users out there. Any constructive criticism appreciated. If you know how I could improve permanent halt detection (that doesn't require in-depth knowledge of APM or ACPI) then please let me know.

Struan

Struan Bartlett wrote:
Ryan Rempel wrote:
On Mon, Nov 29, 2004 at 21:46:54 +0100, Lennert Buytenhek wrote
  
On Mon, Nov 29, 2004 at 08:43:56PM +0000, Richard Neill wrote:
    
A thought that occurred to me. If one is running a virtual machine (eg 
copy of WinXP), then simply closing the qemu window is a really bad 
idea, since it will effectively crash the guest.
      
Related thought -- it would be way cool if we could make killing qemu
do exactly happens when you press the power button on an ACPI-capable
machine with any recent OS on it (auto shutdown.)
    
I was wondering if anyone has followed up on this suggestion. I'm
putting together a Qemu-based setup for some relatively naive users,
and ideally I'd like to be able to deal with this in a reasonable
elegant way (the ACPI hook sounds very elegant indeed).

Alternatively, how do people deal with the problem of naive users who
might just close the Qemu window without shutting down the guest
properly? I'm working in a KDE environment -- perhaps there is a way
in KDE to prevent the close button from appearing? But that wouldn't
catch every case either (for instance, if the user were to shut down
the host).
This sounds like a good idea. An alternative solution, that might be more straightforward to implement if Qemu doesn't implement ACPI yet, would be for the kill signal to simply cause Qemu to do the equivalent of entering 'stop' and 'savevm <somefilepath>' into the monitor.

_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel
--------------010108070505030301000405-- --------------060205090003010304010702 Content-Type: text/plain; name="on-quit-patch-v0.1" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="on-quit-patch-v0.1" --- qemu-snapshot-2005-03-26_23/vl.c Sun Mar 13 17:59:37 2005 +++ qemu-snapshot-2005-03-26_23-on-quit/vl.c Mon Mar 28 02:06:52 2005 @@ -139,6 +139,9 @@ int graphic_height = 600; int graphic_depth = 15; int full_screen = 0; +#ifdef TARGET_I386 +int on_quit = 0; +#endif TextConsole *vga_console; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; @@ -2675,6 +2678,17 @@ qemu_get_clock(rt_clock)); } +#ifdef TARGET_I386 +int ishalted() { + uint8_t buf[16]; + uint64_t v; + + cpu_memory_rw_debug(cpu_single_env, cpu_single_env->eip-1, buf, 16, 0); + v = ldub_raw(buf); + return (v == 0xf4) && ( !(cpu_single_env->eflags & 0x200) ); +} +#endif + int main_loop(void) { int ret, timeout; @@ -2684,9 +2698,16 @@ if (vm_running) { ret = cpu_exec(env); if (shutdown_requested) { +#ifdef TARGET_I386 + if( on_quit == 0 || on_quit == 2 || ( on_quit == 1 && ishalted() ) ) { +#endif ret = EXCP_INTERRUPT; break; } +#ifdef TARGET_I386 + shutdown_requested = 0; + } +#endif if (reset_requested) { reset_requested = 0; qemu_system_reset(); @@ -2783,6 +2804,11 @@ "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n" " (default is CL-GD5446 PCI VGA)\n" #endif +#ifdef TARGET_I386 + "-on-quit [ignore-unless-halted|suspend-unless-halted]\n" + " select the behaviour when the emulator window is asked to quit\n" + " (default is none)\n" +#endif "-loadvm file start right away with a saved state (loadvm in monitor)\n" "\n" "During emulation, the following keys are useful:\n" @@ -2864,6 +2890,10 @@ QEMU_OPTION_full_screen, QEMU_OPTION_pidfile, QEMU_OPTION_no_kqemu, + +#ifdef TARGET_I386 + QEMU_OPTION_on_quit +#endif }; typedef struct QEMUOption { @@ -2932,6 +2962,9 @@ { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, { "full-screen", 0, QEMU_OPTION_full_screen }, { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, +#ifdef TARGET_I386 + { "on-quit", HAS_ARG, QEMU_OPTION_on_quit }, +#endif /* temporary options */ { "pci", 0, QEMU_OPTION_pci }, @@ -3383,6 +3416,19 @@ case QEMU_OPTION_pidfile: create_pidfile(optarg); break; +#ifdef TARGET_I386 + case QEMU_OPTION_on_quit: + if(!strcmp(optarg, "ignore-unless-halted")) { + fprintf(stderr, "%s enabled\n", optarg); + on_quit = 1; + } + else if(!strcmp(optarg, "suspend-unless-halted")) { + fprintf(stderr, "%s enabled\n", optarg); + on_quit = 2; + } + else on_quit = 0; + break; +#endif #ifdef USE_KQEMU case QEMU_OPTION_no_kqemu: kqemu_allowed = 0; @@ -3696,6 +3742,23 @@ } } main_loop(); + +#ifdef TARGET_I386 + if( on_quit == 2 ) { + char *f = "suspended.qemu"; + if( ishalted() ) { + + fprintf(stderr, "VM is halted: removing suspend file %s\n",f); + unlink(f); + /* qemu_savevm(f); */ + } + else { + fprintf(stderr, "Autosaving VM to file %s\n",f); + qemu_savevm(f); + } + } +#endif + quit_timers(); return 0; } --------------060205090003010304010702--