kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Radim Krčmář" <rkrcmar@redhat.com>
To: Eduardo Habkost <ehabkost@redhat.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	peterx@redhat.com, Andrew Jones <drjones@redhat.com>,
	kvm@vger.kernel.org
Subject: Re: kvm_pv_unhalt and kernel_irqchip=off
Date: Wed, 10 Aug 2016 22:58:31 +0200	[thread overview]
Message-ID: <20160810205830.GB27257@potion> (raw)
In-Reply-To: <20160810190412.GA8001@potion>

2016-08-10 21:04+0200, Radim Krčmář:
>> Related question: is there any kvm-unit-test test for
>> kvm_pv_unhalt?
> 
> Not that I know of, thanks for the request.

I attached a simple test below.  It will likely need some modifications
after the bug is fixed in QEMU and/or KVM.

For a fix in KVM, I used the solution from another feature that doesn't
work with irqchip=off, x2APIC.
Jokes aside, we can fix them both because SET_CPUID cannot be called
after CREATE_IRQCHIP.  I'll do so tomorrow.

---8<---
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index ee7f180237b1..f33c680e5dbf 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -402,6 +402,11 @@ static inline void safe_halt(void)
 	asm volatile("sti; hlt");
 }
 
+static inline void cpu_relax(void)
+{
+	asm volatile ("rep; nop");
+}
+
 static inline u32 read_pkru(void)
 {
     unsigned int eax, edx;
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 356d879a986b..6a3bbc86df68 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -45,6 +45,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
                $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
                $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \
                $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \
+               $(TEST_DIR)/pv_unhalt.flat \
 
 ifdef API
 tests-common += api/api-sample
diff --git a/x86/pv_unhalt.c b/x86/pv_unhalt.c
new file mode 100644
index 000000000000..d717e309eab0
--- /dev/null
+++ b/x86/pv_unhalt.c
@@ -0,0 +1,73 @@
+#include "libcflat.h"
+#include "vm.h"
+#include "desc.h"
+#include "smp.h"
+
+/* Intel and AMD hypercalls should be interchangeable. */
+#define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
+
+#define KVM_HC_KICK_CPU			5
+
+#define KVM_CPUID_FEATURES	0x40000001
+#define KVM_FEATURE_PV_UNHALT	(1 << 7)
+
+static volatile bool pv_unhalt_works;
+
+static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
+				  unsigned long p2)
+{
+	long ret;
+	asm volatile(KVM_HYPERCALL
+		     : "=a"(ret)
+		     : "a"(nr), "b"(p1), "c"(p2)
+		     : "memory");
+	return ret;
+}
+
+static void halt(void * nothing)
+{
+	asm volatile("cli; hlt; sti" ::: "memory");
+
+	pv_unhalt_works = true;
+}
+
+static void test_pv_unhalt(void)
+{
+	unsigned long delay;
+
+	if (cpu_count() < 2) {
+		report_skip("pv unhalt");
+		return;
+	}
+
+	/* XXX: KVM_CPUID_FEATURES can have a different base offset */
+	if (!(cpuid(KVM_CPUID_FEATURES).a & KVM_FEATURE_PV_UNHALT)) {
+		/* TODO: use argv to decide whether the presence of pv_unhalt
+		 * is a skip or pass? */
+		report("pv unhalt", 1);
+		return;
+	}
+
+	on_cpu_async(1, halt, 0);
+	/* we need a small delay because CPU1 can't notify that it halted */
+	for (delay = 1<<28; delay; delay--)
+		cpu_relax();
+
+	kvm_hypercall2(KVM_HC_KICK_CPU, 0, 1);
+
+	/* TODO: sane delay loops (ignoring pv_unhalt_works is fine) */
+	for (delay = 1<<28; delay && !pv_unhalt_works; delay--)
+		cpu_relax();
+
+	report("pv unhalt", pv_unhalt_works);
+}
+
+int main(int ac, char **av)
+{
+	setup_vm();
+	smp_init();
+
+	test_pv_unhalt();
+
+	return report_summary();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 60747cfca94e..6fe688d01357 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -197,3 +197,13 @@ extra_params = -cpu kvm64,hv_synic -device hyperv-testdev
 file = hyperv_stimer.flat
 smp = 2
 extra_params = -cpu kvm64,hv_time,hv_synic,hv_stimer -device hyperv-testdev
+
+[pv_unhalt]
+file = pv_unhalt.flat
+smp = 2
+extra_params = -cpu kvm64,+kvm_pv_unhalt
+
+[pv_unhalt_irqchip_off]
+file = pv_unhalt.flat
+smp = 2
+extra_params = -cpu kvm64,+kvm_pv_unhalt -machine kernel_irqchip=off

  reply	other threads:[~2016-08-10 20:59 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-10 18:27 kvm_pv_unhalt and kernel_irqchip=off Eduardo Habkost
2016-08-10 19:04 ` Radim Krčmář
2016-08-10 20:58   ` Radim Krčmář [this message]
2016-08-12 18:37   ` GET_SUPPORTED_CPUID and irqchip (was Re: kvm_pv_unhalt and kernel_irqchip=off) Eduardo Habkost
2016-08-13 12:43     ` Radim Krčmář
2016-08-15 13:03       ` Eduardo Habkost
2016-08-15 13:21         ` Paolo Bonzini
2016-08-15 17:50         ` Radim Krčmář
2016-08-15 18:00           ` Eduardo Habkost
2016-08-15 18:32             ` Radim Krčmář

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160810205830.GB27257@potion \
    --to=rkrcmar@redhat.com \
    --cc=drjones@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).