LINUX.ORG.RU

История изменений

Исправление Deleted, (текущая версия) :

Говнокостыльный патч для stable-2.1 (slow down time in qemu guest)

Исправление Deleted, :

Сначала я попробовать менять scale, как предложил mix_mix, но это приводило к зависанию при загрузке ядра в гостевой системе. Потом методом тыка я пришёл к этому:

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 7f9a074..31826ca 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -7,6 +7,8 @@
 
 /* timers */
 
+#define SLOWDOWN 2
+
 #define SCALE_MS 1000000
 #define SCALE_US 1000
 #define SCALE_NS 1
diff --git a/qemu-timer.c b/qemu-timer.c
index 00a5d35..2933473 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -550,13 +550,13 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
 
     switch (type) {
     case QEMU_CLOCK_REALTIME:
-        return get_clock();
+        return get_clock() / SLOWDOWN;
     default:
     case QEMU_CLOCK_VIRTUAL:
         if (use_icount) {
-            return cpu_get_icount();
+            return cpu_get_icount() / SLOWDOWN;
         } else {
-            return cpu_get_clock();
+            return cpu_get_clock() / SLOWDOWN;
         }
     case QEMU_CLOCK_HOST:
         now = get_clock_realtime();
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f9fcbca..3ce6499 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -448,13 +448,13 @@ typedef struct model_features_t {
  * when KVM is enabled.
  */
 static uint32_t kvm_default_features[FEATURE_WORDS] = {
-    [FEAT_KVM] = (1 << KVM_FEATURE_CLOCKSOURCE) |
+    [FEAT_KVM] = /*(1 << KVM_FEATURE_CLOCKSOURCE) |*/
         (1 << KVM_FEATURE_NOP_IO_DELAY) |
-        (1 << KVM_FEATURE_CLOCKSOURCE2) |
+        /*(1 << KVM_FEATURE_CLOCKSOURCE2) |*/
         (1 << KVM_FEATURE_ASYNC_PF) |
         (1 << KVM_FEATURE_STEAL_TIME) |
-        (1 << KVM_FEATURE_PV_EOI) |
-        (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT),
+        (1 << KVM_FEATURE_PV_EOI) /*|
+        (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)*/,
     [FEAT_1_ECX] = CPUID_EXT_X2APIC,
 };
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ddedc73..3918cef 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -131,7 +131,7 @@ static const struct kvm_para_features {
     int cap;
     int feature;
 } para_features[] = {
-    { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+    /*{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },*/
     { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
     { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
     { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
На самом деле я не знаю как именно это работает. На данный момент постестил, что время успешно замедляется для:

  • ping localhost (пакеты отправляются с большей паузой)
  • date (время идёт в два раза медленнее =))
  • watch -n1

Если не комментировать константы, связанные с KVM, то это работает только с выключенным KVM. Со включенным KVM видимо гостевая система работает с таймерами и прочим как-то в обход qemu.

Обратный отсчёт в isolinux со включенным KVM всегда работает правильно, даже с закомментированными KVM_FEATURE_CLOCKSOURCE*.

Ещё один момент: из-за деления результата qemu_clock_get_ns() пополам, скорее всего логика обработки истёкших таймеров в qemu срабатывает два раза (один раз - вхолостую). Возможно также «замедлились» таймеры qemu, которые не должны были замедляться, например связанные с таймаутами доступа к внешним сетевым ресурсам и т.п.

В общем сейчас это страшный костыль =).

Исходная версия Deleted, :

Говнокостыльный патч для stable-2.1

Сначала я попробовать менять scale, как предложил mix_mix, но это приводило к зависанию при загрузке ядра в гостевой системе. Потом методом тыка я пришёл к этому:

diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 7f9a074..31826ca 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -7,6 +7,8 @@
 
 /* timers */
 
+#define SLOWDOWN 2
+
 #define SCALE_MS 1000000
 #define SCALE_US 1000
 #define SCALE_NS 1
diff --git a/qemu-timer.c b/qemu-timer.c
index 00a5d35..2933473 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -550,13 +550,13 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
 
     switch (type) {
     case QEMU_CLOCK_REALTIME:
-        return get_clock();
+        return get_clock() / SLOWDOWN;
     default:
     case QEMU_CLOCK_VIRTUAL:
         if (use_icount) {
-            return cpu_get_icount();
+            return cpu_get_icount() / SLOWDOWN;
         } else {
-            return cpu_get_clock();
+            return cpu_get_clock() / SLOWDOWN;
         }
     case QEMU_CLOCK_HOST:
         now = get_clock_realtime();
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index f9fcbca..3ce6499 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -448,13 +448,13 @@ typedef struct model_features_t {
  * when KVM is enabled.
  */
 static uint32_t kvm_default_features[FEATURE_WORDS] = {
-    [FEAT_KVM] = (1 << KVM_FEATURE_CLOCKSOURCE) |
+    [FEAT_KVM] = /*(1 << KVM_FEATURE_CLOCKSOURCE) |*/
         (1 << KVM_FEATURE_NOP_IO_DELAY) |
-        (1 << KVM_FEATURE_CLOCKSOURCE2) |
+        /*(1 << KVM_FEATURE_CLOCKSOURCE2) |*/
         (1 << KVM_FEATURE_ASYNC_PF) |
         (1 << KVM_FEATURE_STEAL_TIME) |
-        (1 << KVM_FEATURE_PV_EOI) |
-        (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT),
+        (1 << KVM_FEATURE_PV_EOI) /*|
+        (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT)*/,
     [FEAT_1_ECX] = CPUID_EXT_X2APIC,
 };
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ddedc73..3918cef 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -131,7 +131,7 @@ static const struct kvm_para_features {
     int cap;
     int feature;
 } para_features[] = {
-    { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+    /*{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },*/
     { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
     { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
     { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
На самом деле я не знаю как именно это работает. На данный момент постестил, что время успешно замедляется для:

  • ping localhost (пакеты отправляются с большей паузой)
  • date (время идёт в два раза медленнее =))
  • watch -n1

Если не комментировать константы, связанные с KVM, то это работает только в выключенным KVM. Со включенным KVM видимо гостевая система работает с таймерами и прочим как-то в обход qemu.

Обратный отсчёт в isolinux со включенным KVM всегда работает правильно, даже с закомментированными KVM_FEATURE_CLOCKSOURCE*.

Ещё один момент: из-за деления результата qemu_clock_get_ns() пополам, скорее всего логика обработки истёкших таймеров в qemu срабатывает два раза (один раз - вхолостую). Возможно также «замедлились» таймеры qemu, которые не должны были замедляться, например связанные с таймаутами доступа к внешним сетевым ресурсам и т.п.

В общем сейчас это страшный костыль =).