]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Fix guest single-stepping setup
authorPekka Enberg <penberg@kernel.org>
Thu, 7 Jul 2011 18:12:45 +0000 (21:12 +0300)
committerPekka Enberg <penberg@kernel.org>
Thu, 7 Jul 2011 18:12:45 +0000 (21:12 +0300)
"K. Watts" writes:

  When the singlestep is enabled the ioctl to sent out when the kvm_cpu
  is initialized (kvm-cpu.c in the for loop that gets each vcpu built).
  When the ioct goes out the CPU is sitting at the initialization vector
  of 0xf000:0xfff0 on CPU #0 and 0x000000 on the other SMP CPUs.  The
  new host kernel code that handles setting the TF was changed in 2.6.32
  and again at 2.6.38.  2.6.32 seems just flat broken, but 2.6.38 checks
  that the linear address of the RIP matches what it was when the
  KVM_GUESTDBG_SINGLESTEP flag was set.  Because the kvm-tool doesn't
  start the CPU at the initialization vector (0xfff0) (0x7c00 for the
  MBR and where ever you guys map the linux kernel to) they don't match
  and the host kernel won't set the trap flag.

  Basically the debug and singlestep ioclts need to happen after the CPU
  has been initialized.  I moved kvm_cpu__enable_singlestep to happen in
  kvm_cpu__reset_vcpu after the registers are set (EIP points to boot
  address) and the TRAP flags get set and all is good with the world.

  Singlestepping is disabled when the guest issues a CLI because the
  Linux host doesn't support features in new Intel and AMD CPUs.  We can
  sort of "shadow" the interrupt mask and still get the CPU to trap out
  at ever instruction even when the guest has disabled interrupts on the
  CPU.  I have to get the bios disk handler working completely first,
  but that may be my next task so that we can trace all the CPU
  instructions.  My current hack is to just re-enable the trap flag
  every time a VMEXIT occurs.  I get enough instructions to get me by.

This patch fixes the problem by moving the kvm_cpu__enable_singlestep() into
kvm_cpu__start().

Suggested-by: K. Watts <traetox@gmail.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/include/kvm/kvm.h
tools/kvm/kvm-cpu.c
tools/kvm/kvm-run.c

index 5cfb0d8e9b0bda6a0059bbba227dad50173a2bc2..8792af21f7dae19f9a3a9510bd2601702321a64d 100644 (file)
@@ -35,6 +35,8 @@ struct kvm {
 
        bool                    nmi_disabled;
 
+       bool                    single_step;
+
        u16                     boot_selector;
        u16                     boot_ip;
        u16                     boot_sp;
index f57d42e054520dd302686a4bffd36023a07b3a3e..2f5d23c70ab6cdd4e70ea1cf3345d2c209c35be4 100644 (file)
@@ -439,6 +439,9 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
        kvm_cpu__setup_cpuid(cpu);
        kvm_cpu__reset_vcpu(cpu);
 
+       if (cpu->kvm->single_step)
+               kvm_cpu__enable_singlestep(cpu);
+
        for (;;) {
                if (cpu->paused) {
                        kvm__notify_paused();
index 57791f5d43bce7f7fbd2349860e722c34b217548..048b6a29bb235378609a2661f7f381fce82f39ba 100644 (file)
@@ -559,6 +559,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
        kvm = kvm__init(kvm_dev, ram_size, guest_name);
 
+       kvm->single_step = single_step;
+
        ioeventfd__init();
 
        max_cpus = kvm__max_cpus(kvm);
@@ -672,9 +674,6 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
                kvm_cpus[i] = kvm_cpu__init(kvm, i);
                if (!kvm_cpus[i])
                        die("unable to initialize KVM VCPU");
-
-               if (single_step)
-                       kvm_cpu__enable_singlestep(kvm_cpus[i]);
        }
 
        kvm__init_ram(kvm);