From: Jan Kiszka <jan.kiszka@web.de>
To: Gleb Natapov <gleb@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>
Cc: kvm <kvm@vger.kernel.org>, Paolo Bonzini <pbonzini@redhat.com>
Subject: [PATCH v2] KVM: x86: Convert INIT and SIPI signals into synchronously handled requests
Date: Mon, 04 Mar 2013 22:41:43 +0100 [thread overview]
Message-ID: <51351517.3090600@web.de> (raw)
From: Jan Kiszka <jan.kiszka@siemens.com>
A VCPU sending INIT or SIPI to some other VCPU races for setting the
remote VCPU's mp_state. When we were unlucky, KVM_MP_STATE_INIT_RECEIVED
was overwritten by kvm_emulate_halt and, thus, got lost.
Fix this by raising requests on the sender side that will then be
handled synchronously over the target VCPU context.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
Changes in v2:
- check transition to INIT_RECEIVED in vcpu_enter_guest
- removed return value of kvm_check_init_and_sipi - caller has to
check for relevant transition afterward
- add write barrier after setting sipi_vector
arch/x86/kvm/lapic.c | 11 ++++++-----
arch/x86/kvm/x86.c | 15 +++++++++++++++
include/linux/kvm_host.h | 2 ++
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 02b51dd..7986c9f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -731,8 +731,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
case APIC_DM_INIT:
if (!trig_mode || level) {
result = 1;
- vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
- kvm_make_request(KVM_REQ_EVENT, vcpu);
+ kvm_make_request(KVM_REQ_INIT, vcpu);
kvm_vcpu_kick(vcpu);
} else {
apic_debug("Ignoring de-assert INIT to vcpu %d\n",
@@ -743,11 +742,13 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
case APIC_DM_STARTUP:
apic_debug("SIPI to vcpu %d vector 0x%02x\n",
vcpu->vcpu_id, vector);
- if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+ if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED ||
+ test_bit(KVM_REQ_INIT, &vcpu->requests)) {
result = 1;
vcpu->arch.sipi_vector = vector;
- vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
- kvm_make_request(KVM_REQ_EVENT, vcpu);
+ /* make sure sipi_vector is visible for the receiver */
+ smp_wmb();
+ kvm_make_request(KVM_REQ_SIPI, vcpu);
kvm_vcpu_kick(vcpu);
}
break;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d0cf737..0be04b9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5641,6 +5641,15 @@ static void update_eoi_exitmap(struct kvm_vcpu *vcpu)
kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
}
+static void kvm_check_init_and_sipi(struct kvm_vcpu *vcpu)
+{
+ if (kvm_check_request(KVM_REQ_INIT, vcpu))
+ vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+ if (kvm_check_request(KVM_REQ_SIPI, vcpu) &&
+ vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+ vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED;
+}
+
static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
{
int r;
@@ -5649,6 +5658,11 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
bool req_immediate_exit = 0;
if (vcpu->requests) {
+ kvm_check_init_and_sipi(vcpu);
+ if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
+ r = 1;
+ goto out;
+ }
if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu))
kvm_mmu_unload(vcpu);
if (kvm_check_request(KVM_REQ_MIGRATE_TIMER, vcpu))
@@ -6977,6 +6991,7 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
+ kvm_check_init_and_sipi(vcpu);
return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
!vcpu->arch.apf.halted)
|| !list_empty_careful(&vcpu->async_pf.done)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 722cae7..1a191c9 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -124,6 +124,8 @@ static inline bool is_error_page(struct page *page)
#define KVM_REQ_MCLOCK_INPROGRESS 20
#define KVM_REQ_EPR_EXIT 21
#define KVM_REQ_EOIBITMAP 22
+#define KVM_REQ_INIT 23
+#define KVM_REQ_SIPI 24
#define KVM_USERSPACE_IRQ_SOURCE_ID 0
#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
--
1.7.3.4
next reply other threads:[~2013-03-04 21:41 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-03-04 21:41 Jan Kiszka [this message]
2013-03-04 23:00 ` [PATCH v2] KVM: x86: Convert INIT and SIPI signals into synchronously handled requests Jan Kiszka
2013-03-05 7:57 ` Gleb Natapov
2013-03-05 8:24 ` Jan Kiszka
2013-03-05 8:46 ` Gleb Natapov
2013-03-05 9:12 ` Jan Kiszka
2013-03-05 9:37 ` Gleb Natapov
2013-03-05 10:50 ` Paolo Bonzini
2013-03-05 13:25 ` Jan Kiszka
2013-03-05 13:33 ` Gleb Natapov
2013-03-05 13:28 ` Gleb Natapov
2013-03-05 23:16 ` Marcelo Tosatti
2013-03-06 0:01 ` Marcelo Tosatti
2013-03-06 0:06 ` Marcelo Tosatti
2013-03-06 6:12 ` Paolo Bonzini
2013-03-06 7:57 ` Jan Kiszka
2013-03-06 21:30 ` Marcelo Tosatti
2013-03-06 21:39 ` Jan Kiszka
2013-03-06 21:50 ` Marcelo Tosatti
2013-03-06 21:58 ` Jan Kiszka
2013-03-06 21:19 ` Marcelo Tosatti
2013-03-06 22:43 ` Paolo Bonzini
2013-03-06 23:04 ` Marcelo Tosatti
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=51351517.3090600@web.de \
--to=jan.kiszka@web.de \
--cc=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=mtosatti@redhat.com \
--cc=pbonzini@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