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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.