All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM
@ 2015-03-16 17:28 James Sullivan
  2015-03-16 17:28 ` [PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery James Sullivan
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: James Sullivan @ 2015-03-16 17:28 UTC (permalink / raw)
  To: kvm; +Cc: gleb, pbonzini, rkrcmar, James Sullivan

Changes Since v1:
    * Reworked patches into two commits:
        1) [Patch v2 1/2] Extended struct kvm_lapic_irq with bool
            msi_redir_hint
            * Initialize msi_redir_hint = true in kvm_set_msi_irq when RH=1
            * Initialize msi_redir_hint = false otherwise
            * Added value of msi_redir_hint to debug message dump of IRQ in
                apic_send_ipi
        2) [Patch v2 2/2] Deliver to only lowest prio CPU if msi_redir_hint 
           is true 
            * Move kvm_is_dm_lowest_prio() -> lapic.h, rename to
                kvm_lowest_prio_delivery, set condition to
                (APIC_DM_LOWPRI || msi_redir_hint)
            * Change check in kvm_irq_delivery_to_apic_fast() for
                APIC_DM_LOWPRI or msi_redir_hint to a check for
                kvm_is_dm_lowest_prio() 

(The patch relies on the changes made in a prior patch that adds a check
for the RH bit in kvm_set_msi_irq(); see <5502FEDB.3030606@gmail.com>)

This series of patches extends the KVM interrupt delivery mechanism
to correctly account for the MSI Redirection Hint bit. The RH bit is 
used in logical destination mode to indicate that the delivery of the
interrupt shall only be to the lowest priority candidate LAPIC.

Currently, there is no handling of the MSI RH bit in the KVM interrupt
delivery mechanism. This patch implements the following logic:

* DM=0, RH=*  : Physical destination mode. Interrupt is delivered to
                    the LAPIC with the matching APIC ID. (Subject to
                    the usual restrictions, i.e. no broadcast dest)
* DM=1, RH=0  : Logical destination mode without redirection. Interrupt
                    is delivered to all LAPICs in the logical group 
                    specified by the IRQ's destination map and delivery
                    mode.
* DM=1, RH=1  : Logical destination mode with redirection. Interrupt
                    is delivered only to the lowest priority LAPIC in the 
                    logical group specified by the dest map and the
                    delivery mode. Delivery semantics are otherwise
                    specified by the delivery_mode of the IRQ, which
                    is unchanged.

In other words, the RH bit is ignored in physical destination mode, and
when it is set in logical destination mode causes delivery to only apply
to the lowest priority processor in the logical group. The IA32 manual
is in slight contradiction with itself on this matter, but this patch
agrees with this interpretation of the RH bit:

    https://software.intel.com/en-us/forums/topic/288883

This patch has passed some rudimentary tests using an SMP QEMU guest and
virtio sourced MSIs, but I haven't done experiments with passing through 
PCI hardware (intend to start working on this).

Let me know your thoughts.

-James


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery
  2015-03-16 17:28 [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM James Sullivan
@ 2015-03-16 17:28 ` James Sullivan
  2015-03-16 17:29 ` [PATCH v2 2/2] Deliver to only lowest prio cpu if msi_redir_hint is true James Sullivan
  2015-03-16 19:34 ` [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM Radim Krčmář
  2 siblings, 0 replies; 4+ messages in thread
From: James Sullivan @ 2015-03-16 17:28 UTC (permalink / raw)
  To: kvm; +Cc: gleb, pbonzini, rkrcmar, James Sullivan

Signed-off-by: James Sullivan <sullivan.james.f@gmail.com>
---

The following changes are added in this patch:
    * Initialize msi_redir_hint = true in kvm_set_msi_irq when RH=1
    * Initialize msi_redir_hint = false otherwise
    * Added value of msi_redir_hint to debug message dump of IRQ in
        apic_send_ipi
Changes since v1:
    * Squashed a number of smaller commits into this one commit,
        which adds and initializes the msi_redir_hint variable
        and extends existing debug messages to display its value.

This patch relies on a past submission that adds a check to
kvm_set_msi_irq() for RH=1, setting APIC_DEST_LOGICAL only when
RH=1/DM=1 and otherwise defaulting to APIC_DEST_PHYSICAL.
(See <5502FEDB.3030606@gmail.com>)

 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/ioapic.c           |  1 +
 arch/x86/kvm/irq_comm.c         | 11 ++---------
 arch/x86/kvm/lapic.c            |  6 ++++--
 arch/x86/kvm/x86.c              |  1 +
 5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a236e39..77feaf4 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -685,6 +685,7 @@ struct kvm_lapic_irq {
 	u32 trig_mode;
 	u32 shorthand;
 	u32 dest_id;
+	bool msi_redir_hint;
 };
 
 struct kvm_x86_ops {
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
index b1947e0..61f0874 100644
--- a/arch/x86/kvm/ioapic.c
+++ b/arch/x86/kvm/ioapic.c
@@ -347,6 +347,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
 	irqe.delivery_mode = entry->fields.delivery_mode << 8;
 	irqe.level = 1;
 	irqe.shorthand = 0;
+	irqe.msi_redir_hint = false;
 
 	if (irqe.trig_mode == IOAPIC_EDGE_TRIG)
 		ioapic->irr &= ~(1 << irq);
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index f2887ea..5c33cca 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,6 @@ static inline void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
 			MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
 	irq->vector = (e->msi.data &
 			MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
-	/*
-	 * TODO Deal with RH bit of MSI message address
-	 *  IF RH=1, then MSI delivers only to the processor with the
-	 *  lowest interrupt priority among processors that can receive
-	 *  the interrupt.
-	 */
 	if ((e->msi.address_lo & MSI_ADDR_REDIRECTION_LOWPRI) &&
 			(e->msi.address_lo & MSI_ADDR_DEST_MODE_LOGICAL))
 		irq->dest_mode = APIC_DEST_LOGICAL;
@@ -116,9 +110,8 @@ static inline void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
 		irq->dest_mode = APIC_DEST_PHYSICAL;
 	irq->trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data;
 	irq->delivery_mode = e->msi.data & 0x700;
-	if (e->msi.address_lo & MSI_ADDR_REDIRECTION_LOWPRI)
-		pr_warn_once(
-			"kvm: MSIs may not be correctly delivered with RH set.\n");
+	irq->msi_redir_hint = ((e->msi.address_lo
+		& MSI_ADDR_REDIRECTION_LOWPRI) > 0);
 	irq->level = 1;
 	irq->shorthand = 0;
 }
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index bd4e34d..a15c444 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -892,6 +892,7 @@ static void apic_send_ipi(struct kvm_lapic *apic)
 	irq.level = icr_low & APIC_INT_ASSERT;
 	irq.trig_mode = icr_low & APIC_INT_LEVELTRIG;
 	irq.shorthand = icr_low & APIC_SHORT_MASK;
+	irq.msi_redir_hint = false;
 	if (apic_x2apic_mode(apic))
 		irq.dest_id = icr_high;
 	else
@@ -901,10 +902,11 @@ static void apic_send_ipi(struct kvm_lapic *apic)
 
 	apic_debug("icr_high 0x%x, icr_low 0x%x, "
 		   "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
-		   "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x\n",
+		   "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x, "
+		   "msi_redir_hint 0x%x\n",
 		   icr_high, icr_low, irq.shorthand, irq.dest_id,
 		   irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode,
-		   irq.vector);
+		   irq.vector, irq.msi_redir_hint);
 
 	kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq, NULL);
 }
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bd7a70b..03e9b09 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -5902,6 +5902,7 @@ static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
 	lapic_irq.shorthand = 0;
 	lapic_irq.dest_mode = 0;
 	lapic_irq.dest_id = apicid;
+	lapic_irq.msi_redir_hint = false;
 
 	lapic_irq.delivery_mode = APIC_DM_REMRD;
 	kvm_irq_delivery_to_apic(kvm, 0, &lapic_irq, NULL);
-- 
2.3.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] Deliver to only lowest prio cpu if msi_redir_hint is true
  2015-03-16 17:28 [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM James Sullivan
  2015-03-16 17:28 ` [PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery James Sullivan
@ 2015-03-16 17:29 ` James Sullivan
  2015-03-16 19:34 ` [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM Radim Krčmář
  2 siblings, 0 replies; 4+ messages in thread
From: James Sullivan @ 2015-03-16 17:29 UTC (permalink / raw)
  To: kvm; +Cc: gleb, pbonzini, rkrcmar, James Sullivan

Signed-off-by: James Sullivan <sullivan.james.f@gmail.com>
---

The following changes are added in this patch:
    * Move kvm_is_dm_lowest_prio() -> lapic.h, rename to
        kvm_lowest_prio_delivery, set condition to
        (APIC_DM_LOWPRI || msi_redir_hint)
    * Change check in kvm_irq_delivery_to_apic_fast() for
        APIC_DM_LOWPRI or msi_redir_hint to a check for
        kvm_is_dm_lowest_prio() 
Changes since v1:
    * Squashed a number of smaller commits into this one commit,
        which implements MSI delivery to only the lowest-priority
        CPU whenever RH=1 using the above helper
        kvm_lowest_prio_delivery().

This patch relies on a past submission that adds a check to
kvm_set_msi_irq() for RH=1, setting APIC_DEST_LOGICAL only when
RH=1/DM=1 and otherwise defaulting to APIC_DEST_PHYSICAL.
(See <5502FEDB.3030606@gmail.com>)

 arch/x86/kvm/irq_comm.c | 11 ++++-------
 arch/x86/kvm/lapic.c    |  3 +--
 arch/x86/kvm/lapic.h    |  6 ++++++
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 5c33cca..69cdaab 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -31,6 +31,8 @@
 
 #include "ioapic.h"
 
+#include "lapic.h"
+
 static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
 			   struct kvm *kvm, int irq_source_id, int level,
 			   bool line_status)
@@ -48,11 +50,6 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
 				line_status);
 }
 
-inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
-{
-	return irq->delivery_mode == APIC_DM_LOWEST;
-}
-
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 		struct kvm_lapic_irq *irq, unsigned long *dest_map)
 {
@@ -60,7 +57,7 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 	struct kvm_vcpu *vcpu, *lowest = NULL;
 
 	if (irq->dest_mode == 0 && irq->dest_id == 0xff &&
-			kvm_is_dm_lowest_prio(irq)) {
+			kvm_lowest_prio_delivery(irq)) {
 		printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
 		irq->delivery_mode = APIC_DM_FIXED;
 	}
@@ -76,7 +73,7 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
 					irq->dest_id, irq->dest_mode))
 			continue;
 
-		if (!kvm_is_dm_lowest_prio(irq)) {
+		if (!kvm_lowest_prio_delivery(irq)) {
 			if (r < 0)
 				r = 0;
 			r += kvm_apic_set_irq(vcpu, irq, dest_map);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index a15c444..f8b21d5 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -701,8 +701,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 		dst = map->logical_map[cid];
 
 		bitmap = apic_logical_id(map, mda);
-
-		if (irq->delivery_mode == APIC_DM_LOWEST) {
+		if (kvm_lowest_prio_delivery(irq)) {
 			int l = -1;
 			for_each_set_bit(i, &bitmap, 16) {
 				if (!dst[i])
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 0bc6c65..ed7e2fa 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -168,6 +168,12 @@ static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
 	return vcpu->arch.apic->pending_events;
 }
 
+static inline bool kvm_lowest_prio_delivery(struct kvm_lapic_irq *irq)
+{
+	return (irq->delivery_mode == APIC_DM_LOWEST ||
+			irq->msi_redir_hint);
+}
+
 bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
 
 void wait_lapic_expire(struct kvm_vcpu *vcpu);
-- 
2.3.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM
  2015-03-16 17:28 [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM James Sullivan
  2015-03-16 17:28 ` [PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery James Sullivan
  2015-03-16 17:29 ` [PATCH v2 2/2] Deliver to only lowest prio cpu if msi_redir_hint is true James Sullivan
@ 2015-03-16 19:34 ` Radim Krčmář
  2 siblings, 0 replies; 4+ messages in thread
From: Radim Krčmář @ 2015-03-16 19:34 UTC (permalink / raw)
  To: James Sullivan; +Cc: kvm, gleb, pbonzini

2015-03-16 11:28-0600, James Sullivan:
> Changes Since v1:
>     * Reworked patches into two commits:
>         1) [Patch v2 1/2] Extended struct kvm_lapic_irq with bool
>             msi_redir_hint
>             * Initialize msi_redir_hint = true in kvm_set_msi_irq when RH=1
>             * Initialize msi_redir_hint = false otherwise
>             * Added value of msi_redir_hint to debug message dump of IRQ in
>                 apic_send_ipi
>         2) [Patch v2 2/2] Deliver to only lowest prio CPU if msi_redir_hint 
>            is true 
>             * Move kvm_is_dm_lowest_prio() -> lapic.h, rename to
>                 kvm_lowest_prio_delivery, set condition to
>                 (APIC_DM_LOWPRI || msi_redir_hint)
>             * Change check in kvm_irq_delivery_to_apic_fast() for
>                 APIC_DM_LOWPRI or msi_redir_hint to a check for
>                 kvm_is_dm_lowest_prio() 

Functionality is good, but patch style is not up to par.
(Documentation/SubmittingPatches)

Subjects should begin with "kvm: " (or in CAPS), followed by "x86:",
`git log $file` is a good reference.
(Proper tags protect your ancestors from getting cursed if you decide to
 Cc: linux-kernel@vger.kernel.org.)

Commit messages are really useful ... ideally they contain
 - purpose of the patch (probably won't fit in a subject)
 - design decisions
 - excerpts from documentation

If it is hard to come up with a commit message, it's likely not a good
patch -- right now, you could basically paste the cover letter if you
did the following:
 - do the renaming and moving in a first patch
 - do stuff from [1/2] in a second patch + check for irq->msi_redir_hint
   in kvm_lowest_prio_delivery()

> (The patch relies on the changes made in a prior patch that adds a check
> for the RH bit in kvm_set_msi_irq(); see <5502FEDB.3030606@gmail.com>)

I failed to spot that this patch has suboptimal Subject in my earlier
review, sorry.

I see two options now
 1) ask the maintainer to fix it when applying the patch
 2) resend; you can include the patch in this series
    (send a reply to the original one, to make it clear.)

I like option (2) better -- you'll drop the patch-dependency and you
might also change something else if you decide to.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-03-16 19:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-16 17:28 [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM James Sullivan
2015-03-16 17:28 ` [PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery James Sullivan
2015-03-16 17:29 ` [PATCH v2 2/2] Deliver to only lowest prio cpu if msi_redir_hint is true James Sullivan
2015-03-16 19:34 ` [PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM Radim Krčmář

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.