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
next prev parent 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).