Re: [Qemu-devel] [PATCH] intentinoal slowing down qemu - brake

2007-03-25 Thread Miroslav Novak

I'm sending some more facts that should make clear why I think the 
functionality provided by the patch is relevant. (At least for the DOS 
emulation.)

Making emulated CPU slower
  Some old DOS games runs too fast on modern CPUs, even the qemu-emulted
ones. This patch can make these games playable.
  This was reported in http://qemu-forum.ipi.fi/viewtopic.php?t=1264

Energy saving
  MSDOS doesn't use HLT insn. Even if the dosidle can help in command 
prompt, it doesn't work in other programs such as games.
  This was reported in http://qemu-forum.ipi.fi/viewtopic.php?t=1372

The similar approach is used in dosbox by setting "CPU cycles". I think 
qemu is better than dosbox, so it makes sense to me to include such 
capability too. 

This patch doesn't try to emulate the task scheduler that was why Martin 
voted against it. I'm sorry if I wasnt't clear enough in my first post.

Mirek.



On Thu, 30 Nov 2006, Miroslav Novak wrote:

> This patch adds support for slowing down qemu and saving cpu load.
> The '-brake' command line parameter or monitor command 'brake' determines how
> long to wait in the main_loop with respect to duration of time that qemu used
> for the emulation itself.
> Thus e.g. zero value runs at full speed, 1 at 1/2 speed, 10 at 1/11 speed,
> etc.
> 
> A drawback of this approach is that the timer interrupt can be missed if
> raised too often. This happens if the loop_main divided by (1+brake) is less
> than the frequency of PIC interrupts.
> In such case the time of emulated system runs slowly.
> 
> This problem occurs mainly for Linux emulation where kernel parameter HZ is of
> several hunderds.
> For DOS emulation, where the timer interrupts are raised usualy at 18Hz, this
> approach works nice, and one can play old DOS games at reasonable speed and
> save batteries.
> 
> 
> Mirek
> 
> 




[Qemu-devel] [PATCH] slow down qemu - brake

2007-03-25 Thread Miroslav Novak

This patch adds support for slowing down Qemu and saving cpu load.
The '-brake' command line parameter or monitor command 'brake' 
determines how long to wait in the main_loop with respect to duration of 
time that qemu used for the emulation itself.
Thus e.g. zero value runs at full speed, 1 at 1/2 speed, 10 at 1/11 
speed, etc.


A drawback of this approach is that the PIC interrupt can be missed if 
PIC raises them too often. This happens if the loop_main divided by 
(1+brake) is less than the frequency of PIC interrupts.

In such case the time of emulated system runs slowly.
This problem occurs mainly for Linux emulation where kernel parameter HZ 
is usually of several hundreds.


For DOS emulation, where PIC interrupts are raised usually at 18Hz, this 
approach works nice. And one can play old DOS games at reasonable speed 
and save batteries.


Mirek

diff -aur ../../orig/qemu-0.8.2/monitor.c ./monitor.c
--- ../../orig/qemu-0.8.2/monitor.c	2006-07-22 19:23:34.0 +0200
+++ ./monitor.c	2006-11-27 18:11:34.0 +0100
@@ -276,6 +276,14 @@
 term_printf("Invalid CPU index\n");
 }
 
+static void do_brake_set(int multiplier)
+{
+if (multiplier < 0)
+term_printf("Current brake multiplier %d\n", brake_mult);
+else
+brake_mult = multiplier;
+}
+
 static void do_info_jit(void)
 {
 dump_exec_info(NULL, monitor_fprintf);
@@ -1198,6 +1206,8 @@
 #endif
  { "stopcapture", "i", do_stop_capture,
"capture index", "stop capture" },
+{ "brake", "i", do_brake_set, 
+  "multiplier", "set brake multiplier (non-negative integer), negative value prints actual setting" },
 { NULL, NULL, }, 
 };
 
diff -aur ../../orig/qemu-0.8.2/vl.c ./vl.c
--- ../../orig/qemu-0.8.2/vl.c	2006-07-22 19:23:34.0 +0200
+++ ./vl.c	2006-11-27 18:25:22.0 +0100
@@ -156,6 +156,7 @@
 #endif
 int acpi_enabled = 1;
 int fd_bootchk = 1;
+int brake_mult = 0;
 
 /***/
 /* x86 ISA bus support */
@@ -5045,8 +5046,39 @@
 
 static CPUState *cur_cpu;
 
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
+	/* Perform the carry for the later subtraction by updating y. */
+	if (x->tv_usec < y->tv_usec) {
+		int nsec = (y->tv_usec - x->tv_usec) / 100 + 1;
+		y->tv_usec -= 100 * nsec;
+		y->tv_sec += nsec;
+	}
+	if (x->tv_usec - y->tv_usec > 100) {
+		int nsec = (x->tv_usec - y->tv_usec) / 100;
+		y->tv_usec += 100 * nsec;
+		y->tv_sec -= nsec;
+	}
+
+	/* Compute the time remaining to wait.
+	 *  tv_usec is certainly positive. */
+	result->tv_sec = x->tv_sec - y->tv_sec;
+	result->tv_usec = x->tv_usec - y->tv_usec;
+
+	/* Return 1 if result is negative. */
+	return x->tv_sec < y->tv_sec;
+}
+
+
 int main_loop(void)
 {
+struct timeval tti, tti2, tti3, ttix;
+//#define BRAKE_DEBUG
+#ifdef BRAKE_DEBUG
+int64_t mti, mti1, mti2, mti3;
+int prcnt=0;
+#endif
+
 int ret, timeout;
 #ifdef CONFIG_PROFILER
 int64_t ti;
@@ -5055,6 +5087,11 @@
 
 cur_cpu = first_cpu;
 for(;;) {
+
+gettimeofday(&tti, NULL);
+#ifdef BRAKE_DEBUG
+mti = profile_getclock();
+#endif
 if (vm_running) {
 
 env = cur_cpu;
@@ -5113,6 +5150,41 @@
 #ifdef CONFIG_PROFILER
 dev_time += profile_getclock() - ti;
 #endif
+
+gettimeofday(&tti2, NULL);
+#ifdef BRAKE_DEBUG
+mti2 = profile_getclock();
+#endif
+
+{
+struct timespec ts;
+int delus, delunc=0;
+sigset_t sis, osis;
+
+timeval_subtract(&ttix, &tti2, &tti);
+delus = ttix.tv_usec*brake_mult - delunc;
+ts.tv_sec=0;
+ts.tv_nsec=delus*1000;
+
+sigfillset(&sis);
+sigprocmask(SIG_BLOCK, &sis, &osis);
+if (delus>0) while (nanosleep(&ts, &ts));
+sigprocmask(SIG_SETMASK, &osis, NULL);
+#ifdef BRAKE_DEBUG
+mti3 = profile_getclock();
+#endif
+gettimeofday(&tti3, NULL);
+
+timeval_subtract(&ttix, &tti3, &tti2);
+delunc = ttix.tv_usec-delus; 
+#ifdef BRAKE_DEBUG
+if (!((++prcnt)%128)) {
+printf("cycles %qd, \t%qd, \t%qd, \t%qd \%\n", (mti1 - mti), (mti2 - mti1), (mti3 - mti2), (100*(mti1 - mti))/(mti3-mti) );
+//printf("del[us] %d, \t%d\n", delus, delunc);
+//printf("ts[ns] = %d\n", ts.tv_nsec);
+}
+#endif
+}
 }
 cpu_disable_ticks();
 return ret;
@@ -5224,6 +5296,7 @@
 #endif
"-loadvm filestart right away with a saved state (loadvm in monitor)\n"
 	   "-vnc displaystart a VNC server on display\n"
+   "-brake multiplierenables brake system which slows down qemu `multiplier'-times\n"
"\n"
"During emulation, the following keys are useful:\n"
"ctrl-alt-f  toggle full screen\n"
@@ -5302,6 +5375,7 @@
 QEMU_OPTION_smp,
 QEMU_OPTION_vnc,
  

Re: [Qemu-devel] [PATCH] intentinoal slowing down qemu - brake

2006-12-05 Thread Miroslav Novak


I'm sending some more facts that should make clear why I think the
functionality provided by the patch is relevant. (At least for the DOS
emulation.)

Making emulated CPU slower
  Some old DOS games runs too fast on modern CPUs, even the qemu-emulted
ones. This patch can make these games playable.
  The problem was reported in http://qemu-forum.ipi.fi/viewtopic.php?t=1264

Energy saving
  MSDOS doesn't use HLT insn. Even if the dosidle can help in command
prompt, it doesn't work in other programs such as games.
  This was reported in http://qemu-forum.ipi.fi/viewtopic.php?t=1372

The similar approach is used in dosbox by setting "CPU cycles". I think
qemu is better than dosbox, so it makes sense to me to include such
capability too.

This patch doesn't try to emulate the task scheduler that was why Martin
voted against it. I'm sorry if I wasnt't clear enough in my first post.

Mirek.



On Thu, 30 Nov 2006, Miroslav Novak wrote:

> This patch adds support for slowing down qemu and saving cpu load.
> The '-brake' command line parameter or monitor command 'brake' determines how
> long to wait in the main_loop with respect to duration of time that qemu used
> for the emulation itself.
> Thus e.g. zero value runs at full speed, 1 at 1/2 speed, 10 at 1/11 speed,
> etc.
> 
> A drawback of this approach is that the timer interrupt can be missed if
> raised too often. This happens if the loop_main divided by (1+brake) is less
> than the frequency of PIC interrupts.
> In such case the time of emulated system runs slowly.
> 
> This problem occurs mainly for Linux emulation where kernel parameter HZ is of
> several hunderds.
> For DOS emulation, where the timer interrupts are raised usualy at 18Hz, this
> approach works nice, and one can play old DOS games at reasonable speed and
> save batteries.
> 
> 
> Mirek
> 
> 


___
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel


[Qemu-devel] [PATCH] intentinoal slowing down qemu - brake

2006-11-30 Thread Miroslav Novak

This patch adds support for slowing down qemu and saving cpu load.
The '-brake' command line parameter or monitor command 'brake' 
determines how long to wait in the main_loop with respect to duration of 
time that qemu used for the emulation itself.
Thus e.g. zero value runs at full speed, 1 at 1/2 speed, 10 at 1/11 
speed, etc.


A drawback of this approach is that the timer interrupt can be missed if 
raised too often. This happens if the loop_main divided by (1+brake) is 
less than the frequency of PIC interrupts.

In such case the time of emulated system runs slowly.

This problem occurs mainly for Linux emulation where kernel parameter HZ 
is of several hunderds.
For DOS emulation, where the timer interrupts are raised usualy at 18Hz, 
this approach works nice, and one can play old DOS games at reasonable 
speed and save batteries.



Mirek

diff -aur ../../orig/qemu-0.8.2/monitor.c ./monitor.c
--- ../../orig/qemu-0.8.2/monitor.c	2006-07-22 19:23:34.0 +0200
+++ ./monitor.c	2006-11-27 18:11:34.0 +0100
@@ -276,6 +276,14 @@
 term_printf("Invalid CPU index\n");
 }
 
+static void do_brake_set(int multiplier)
+{
+if (multiplier < 0)
+term_printf("Current brake multiplier %d\n", brake_mult);
+else
+brake_mult = multiplier;
+}
+
 static void do_info_jit(void)
 {
 dump_exec_info(NULL, monitor_fprintf);
@@ -1198,6 +1206,8 @@
 #endif
  { "stopcapture", "i", do_stop_capture,
"capture index", "stop capture" },
+{ "brake", "i", do_brake_set, 
+  "multiplier", "set brake multiplier (non-negative integer), negative value prints actual setting" },
 { NULL, NULL, }, 
 };
 
diff -aur ../../orig/qemu-0.8.2/vl.c ./vl.c
--- ../../orig/qemu-0.8.2/vl.c	2006-07-22 19:23:34.0 +0200
+++ ./vl.c	2006-11-27 18:25:22.0 +0100
@@ -156,6 +156,7 @@
 #endif
 int acpi_enabled = 1;
 int fd_bootchk = 1;
+int brake_mult = 0;
 
 /***/
 /* x86 ISA bus support */
@@ -5045,8 +5046,39 @@
 
 static CPUState *cur_cpu;
 
+
+int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
+	/* Perform the carry for the later subtraction by updating y. */
+	if (x->tv_usec < y->tv_usec) {
+		int nsec = (y->tv_usec - x->tv_usec) / 100 + 1;
+		y->tv_usec -= 100 * nsec;
+		y->tv_sec += nsec;
+	}
+	if (x->tv_usec - y->tv_usec > 100) {
+		int nsec = (x->tv_usec - y->tv_usec) / 100;
+		y->tv_usec += 100 * nsec;
+		y->tv_sec -= nsec;
+	}
+
+	/* Compute the time remaining to wait.
+	 *  tv_usec is certainly positive. */
+	result->tv_sec = x->tv_sec - y->tv_sec;
+	result->tv_usec = x->tv_usec - y->tv_usec;
+
+	/* Return 1 if result is negative. */
+	return x->tv_sec < y->tv_sec;
+}
+
+
 int main_loop(void)
 {
+struct timeval tti, tti2, tti3, ttix;
+//#define BRAKE_DEBUG
+#ifdef BRAKE_DEBUG
+int64_t mti, mti1, mti2, mti3;
+int prcnt=0;
+#endif
+
 int ret, timeout;
 #ifdef CONFIG_PROFILER
 int64_t ti;
@@ -5055,6 +5087,11 @@
 
 cur_cpu = first_cpu;
 for(;;) {
+
+gettimeofday(&tti, NULL);
+#ifdef BRAKE_DEBUG
+mti = profile_getclock();
+#endif
 if (vm_running) {
 
 env = cur_cpu;
@@ -5113,6 +5150,41 @@
 #ifdef CONFIG_PROFILER
 dev_time += profile_getclock() - ti;
 #endif
+
+gettimeofday(&tti2, NULL);
+#ifdef BRAKE_DEBUG
+mti2 = profile_getclock();
+#endif
+
+{
+struct timespec ts;
+int delus, delunc=0;
+sigset_t sis, osis;
+
+timeval_subtract(&ttix, &tti2, &tti);
+delus = ttix.tv_usec*brake_mult - delunc;
+ts.tv_sec=0;
+ts.tv_nsec=delus*1000;
+
+sigfillset(&sis);
+sigprocmask(SIG_BLOCK, &sis, &osis);
+if (delus>0) while (nanosleep(&ts, &ts));
+sigprocmask(SIG_SETMASK, &osis, NULL);
+#ifdef BRAKE_DEBUG
+mti3 = profile_getclock();
+#endif
+gettimeofday(&tti3, NULL);
+
+timeval_subtract(&ttix, &tti3, &tti2);
+delunc = ttix.tv_usec-delus; 
+#ifdef BRAKE_DEBUG
+if (!((++prcnt)%128)) {
+printf("cycles %qd, \t%qd, \t%qd, \t%qd \%\n", (mti1 - mti), (mti2 - mti1), (mti3 - mti2), (100*(mti1 - mti))/(mti3-mti) );
+//printf("del[us] %d, \t%d\n", delus, delunc);
+//printf("ts[ns] = %d\n", ts.tv_nsec);
+}
+#endif
+}
 }
 cpu_disable_ticks();
 return ret;
@@ -5224,6 +5296,7 @@
 #endif
"-loadvm filestart right away with a saved state (loadvm in monitor)\n"
 	   "-vnc displaystart a VNC server on display\n"
+   "-brake multiplierenables brake system which slows down qemu `multiplier'-times\n"
"\n"
"During emulation, the following keys are useful:\n"
"ctrl-alt-f  toggle full screen\n"
@@ -5302,6 +5375,7 @@
 QEMU_OPTION_smp,
 QEMU_OPTION_vnc,
 QEMU_OP