"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>
bool nmi_disabled;
+ bool single_step;
+
u16 boot_selector;
u16 boot_ip;
u16 boot_sp;
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();
kvm = kvm__init(kvm_dev, ram_size, guest_name);
+ kvm->single_step = single_step;
+
ioeventfd__init();
max_cpus = kvm__max_cpus(kvm);
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);