Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-04-02 Thread James Sullivan
On 03/24/2015 08:03 AM, Radim Krčmář wrote:
 2015-03-23 16:46-0600, James Sullivan:
 On 03/23/2015 03:13 PM, Radim Krčmář wrote:
 I meant if the delivery mode from data register isn't ignored with RH=1,
 and the message delivered as if lowest-priority was set there.
 (Decided by having something else than fixed or lowest-priority there.)


 Hmm, any thoughts on how I could test for that?
 
 Set the MSI data register's delivery mode to NMI/SMI/...
 The change below fails = hardware honors delivery mode.
 
 I tested it and Linux got a lot of unexpected NMIs, so the emulation in
 your latest patch looks correct.
 
 diff --git a/arch/x86/include/asm/msidef.h b/arch/x86/include/asm/msidef.h
 index 4cc48af23fef..2270e459186b 100644
 --- a/arch/x86/include/asm/msidef.h
 +++ b/arch/x86/include/asm/msidef.h
 @@ -17,6 +17,7 @@
  #define MSI_DATA_DELIVERY_MODE_SHIFT 8
  #define  MSI_DATA_DELIVERY_FIXED (0  MSI_DATA_DELIVERY_MODE_SHIFT)
  #define  MSI_DATA_DELIVERY_LOWPRI(1  MSI_DATA_DELIVERY_MODE_SHIFT)
 +#define  MSI_DATA_DELIVERY_NMI   (4  
 MSI_DATA_DELIVERY_MODE_SHIFT)
  
  #define MSI_DATA_LEVEL_SHIFT 14
  #define   MSI_DATA_LEVEL_DEASSERT(0  MSI_DATA_LEVEL_SHIFT)
 diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
 index d6ba2d660dc5..4f71737c34eb 100644
 --- a/arch/x86/kernel/apic/msi.c
 +++ b/arch/x86/kernel/apic/msi.c
 @@ -46,7 +46,7 @@ void native_compose_msi_msg(struct pci_dev *pdev,
   MSI_DATA_LEVEL_ASSERT |
   ((apic-irq_delivery_mode != dest_LowestPrio) ?
   MSI_DATA_DELIVERY_FIXED :
 - MSI_DATA_DELIVERY_LOWPRI) |
 + MSI_DATA_DELIVERY_NMI) |
   MSI_DATA_VECTOR(cfg-vector);
  }
  
 

Good to hear, thanks for testing that.

Any other tweaks you think are necessary for the patch set?
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/2] kvm: x86: Implement handling of RH=1 for MSI delivery in KVM

2015-03-28 Thread James Sullivan

On 03/17/2015 02:19 AM, Jan Kiszka wrote:
 On 2015-03-17 02:30, James Sullivan wrote:
 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() 
 Changes since v2:
 * Extend Patch 1/2 (kvm: x86: Extended struct kvm_lapic_irq with 
 msi_redir_hint for MSI delivery) with older patch to set the value
 of dest_mode in kvm_set_msi_irq() to be APIC_DEST_LOGICAL only when 
 RH=1/DM=1, and APIC_DEST_PHYSICAL otherwise. 
 (5502fedb.3030...@gmail.com)
 This was done to decouple the patch dependency and to collect all
 efforts to implement RH bit handling into one submission.
 * Patch formatting

 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/23

 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).
 
 Once the kernel side is settled, would you mind looking into equivalent
 support for QEMU's APIC as well? Just to keep it easy to switch between
 both modes without too many functional restrictions.
 
 Thanks!
 Jan
 

Just an update- I've submitted this to the QEMU side of things, see
https://lists.gnu.org/archive/html/qemu-devel/2015-03/msg05020.html

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-24 Thread James Sullivan


On 03/24/2015 08:03 AM, Radim Krčmář wrote:
 2015-03-23 16:46-0600, James Sullivan:
 On 03/23/2015 03:13 PM, Radim Krčmář wrote:
 I meant if the delivery mode from data register isn't ignored with RH=1,
 and the message delivered as if lowest-priority was set there.
 (Decided by having something else than fixed or lowest-priority there.)


 Hmm, any thoughts on how I could test for that?
 
 Set the MSI data register's delivery mode to NMI/SMI/...
 The change below fails = hardware honors delivery mode.
 
 I tested it and Linux got a lot of unexpected NMIs, so the emulation in
 your latest patch looks correct.
 
 diff --git a/arch/x86/include/asm/msidef.h b/arch/x86/include/asm/msidef.h
 index 4cc48af23fef..2270e459186b 100644
 --- a/arch/x86/include/asm/msidef.h
 +++ b/arch/x86/include/asm/msidef.h
 @@ -17,6 +17,7 @@
  #define MSI_DATA_DELIVERY_MODE_SHIFT 8
  #define  MSI_DATA_DELIVERY_FIXED (0  MSI_DATA_DELIVERY_MODE_SHIFT)
  #define  MSI_DATA_DELIVERY_LOWPRI(1  MSI_DATA_DELIVERY_MODE_SHIFT)
 +#define  MSI_DATA_DELIVERY_NMI   (4  
 MSI_DATA_DELIVERY_MODE_SHIFT)
  
  #define MSI_DATA_LEVEL_SHIFT 14
  #define   MSI_DATA_LEVEL_DEASSERT(0  MSI_DATA_LEVEL_SHIFT)
 diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
 index d6ba2d660dc5..4f71737c34eb 100644
 --- a/arch/x86/kernel/apic/msi.c
 +++ b/arch/x86/kernel/apic/msi.c
 @@ -46,7 +46,7 @@ void native_compose_msi_msg(struct pci_dev *pdev,
   MSI_DATA_LEVEL_ASSERT |
   ((apic-irq_delivery_mode != dest_LowestPrio) ?
   MSI_DATA_DELIVERY_FIXED :
 - MSI_DATA_DELIVERY_LOWPRI) |
 + MSI_DATA_DELIVERY_NMI) |
   MSI_DATA_VECTOR(cfg-vector);
  }
  
 

Great, thanks.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-23 Thread James Sullivan
On 03/23/2015 03:13 PM, Radim Krčmář wrote:
 2015-03-20 11:50-0600, James Sullivan:
 On 03/20/2015 09:22 AM, James Sullivan wrote:
 On 03/20/2015 09:15 AM, Radim Krčmář wrote:
 2015-03-19 16:51-0600, James Sullivan:
 I played around with native_compose_msi_msg and discovered the following:

 * dm=0, rh=0 = Physical Destination Mode
 * dm=0, rh=1 = Failed delivery
 * dm=1, rh=0 = Logical Destination Mode, No Redirection
 * dm=1, rh=1 = Logical Destination Mode, Redirection

 Great!  (What CPU family was that?)


 This was on Intel x86_64 (Core i5-3210m, 'Ivy Bridge').
 
 Thanks, it's possible that the behavior of chipsets changed since the
 report on Intel's forum ...
 (Lowest priority behaved differently before QPI, so it might coincide.)
 
 I'm still wondering about last sentence from that link, the
 parenthesised part to be exact,
   The reference to the APIC ID being 0xff is because 0xff is broadcast
   and lowest priority (what the RH bit really is for X86) is illegal
   with broadcast.

 Can you also check if RH=1 does something to delivery mode?

 I haven't seen any changes in the MSI Data Register for any values of RH,
 but I don't have a great sample size (one machine with one set of PCI 
 devices),
 so if anyone else can confirm that I would appreciate it.
 
 I meant if the delivery mode from data register isn't ignored with RH=1,
 and the message delivered as if lowest-priority was set there.
 (Decided by having something else than fixed or lowest-priority there.)
 

Hmm, any thoughts on how I could test for that?

 Worth noting that low prio delivery was used across the board for my PCI 
 devices
 regardless of RH=1 or 0, so it doesn't seem to be de facto the case that the 
 RH
 bit's only purpose is for lowprio delivery on x86.
 
 Yeah, afaik, it can be done with lowest priority delivery mode on ia64
 too, so I have a hard time finding RH's intended purpose.
 
Again, need to have some 
 more
 PCI devices to test against to confirm anything.
 
 It's impossible to test everything, and there is no conflict if we have
 at most one data point ;)
 

Very true :)
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-20 Thread James Sullivan
On 03/20/2015 09:15 AM, Radim Krčmář wrote:
 2015-03-19 16:51-0600, James Sullivan:
 I played around with native_compose_msi_msg and discovered the following:

 * dm=0, rh=0 = Physical Destination Mode
 * dm=0, rh=1 = Failed delivery
 * dm=1, rh=0 = Logical Destination Mode, No Redirection
 * dm=1, rh=1 = Logical Destination Mode, Redirection
 
 Great!  (What CPU family was that?)
 

This was on Intel x86_64 (Core i5-3210m, 'Ivy Bridge').

 So it seems to be the case that logical destination mode is used whenever
 DM=1, regardless of RH. Furthermore, the case where DM=0 and RH=1 is
 undefined, as was indicated in the closing response to the thread in
 https://software.intel.com/en-us/forums/topic/23 :
 
 DM=0+RH=1 might be defined to fail, but I think it's acceptable to
 treat it as undefined.  (Deliver them in KVM if it improves something.)
 

My thoughts as well.

 I'm still wondering about last sentence from that link, the
 parenthesised part to be exact,
   The reference to the APIC ID being 0xff is because 0xff is broadcast
   and lowest priority (what the RH bit really is for X86) is illegal
   with broadcast.
 
 Can you also check if RH=1 does something to delivery mode?
 
 Thanks.
 

Sure, I'll look into that as well.

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-20 Thread James Sullivan
On 03/20/2015 09:22 AM, James Sullivan wrote:
 On 03/20/2015 09:15 AM, Radim Krčmář wrote:
 2015-03-19 16:51-0600, James Sullivan:
 I played around with native_compose_msi_msg and discovered the following:

 * dm=0, rh=0 = Physical Destination Mode
 * dm=0, rh=1 = Failed delivery
 * dm=1, rh=0 = Logical Destination Mode, No Redirection
 * dm=1, rh=1 = Logical Destination Mode, Redirection

 Great!  (What CPU family was that?)

 
 This was on Intel x86_64 (Core i5-3210m, 'Ivy Bridge').
 
 So it seems to be the case that logical destination mode is used whenever
 DM=1, regardless of RH. Furthermore, the case where DM=0 and RH=1 is
 undefined, as was indicated in the closing response to the thread in
 https://software.intel.com/en-us/forums/topic/23 :

 DM=0+RH=1 might be defined to fail, but I think it's acceptable to
 treat it as undefined.  (Deliver them in KVM if it improves something.)

 
 My thoughts as well.
 
 I'm still wondering about last sentence from that link, the
 parenthesised part to be exact,
   The reference to the APIC ID being 0xff is because 0xff is broadcast
   and lowest priority (what the RH bit really is for X86) is illegal
   with broadcast.

 Can you also check if RH=1 does something to delivery mode?

 Thanks.

 
 Sure, I'll look into that as well.
 
 -James
 

I haven't seen any changes in the MSI Data Register for any values of RH,
but I don't have a great sample size (one machine with one set of PCI devices),
so if anyone else can confirm that I would appreciate it.

Worth noting that low prio delivery was used across the board for my PCI devices
regardless of RH=1 or 0, so it doesn't seem to be de facto the case that the RH
bit's only purpose is for lowprio delivery on x86. Again, need to have some more
PCI devices to test against to confirm anything.

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-19 Thread James Sullivan
On 03/19/2015 07:00 AM, Radim Krčmář wrote:
 2015-03-18 22:09-0300, Marcelo Tosatti:
 See native_compose_msi_msg:
 ((apic-irq_dest_mode == 0) ?
 MSI_ADDR_DEST_MODE_PHYSICAL :
 MSI_ADDR_DEST_MODE_LOGICAL) |
 ((apic-irq_delivery_mode != dest_LowestPrio) ?
 MSI_ADDR_REDIRECTION_CPU :
 MSI_ADDR_REDIRECTION_LOWPRI) |
 So it does configure DM = MSI_ADDR_DEST_MODE_LOGICAL
 and RH = MSI_ADDR_REDIRECTION_LOWPRI.
 ...and yet this is a good counterexample against my argument :)
 
 (It could be just to make the code nicer ... the developer might have
  known how real hardware will handle it.)
 
 What I think I'll do is revert this particular change so that dest_mode is
 set independently of RH. While I'm not entirely convinced that this is the
 intended interpretation, I do think that consistency with the existing logic
 is probably desirable for the time being. If I can get closure on the matter
 I'll re-submit that change, but for the time being I will undo it.
 Just write MSI-X table entries on real hardware (say: modify
 native_compose_msi_msg or MSI-X equivalent), with all RH/DM
 combinations, and see what behaviour is
 comes up?  
 
 I second this idea.
 (We'd also get to know how RH interacts with delivery mode.)
 

I played around with native_compose_msi_msg and discovered the following:

* dm=0, rh=0 = Physical Destination Mode
* dm=0, rh=1 = Failed delivery
* dm=1, rh=0 = Logical Destination Mode, No Redirection
* dm=1, rh=1 = Logical Destination Mode, Redirection

So it seems to be the case that logical destination mode is used whenever
DM=1, regardless of RH. Furthermore, the case where DM=0 and RH=1 is
undefined, as was indicated in the closing response to the thread in
https://software.intel.com/en-us/forums/topic/23 :

...X86 supports logical mode but does not support redirection of physical mode
interrupts. I think they should have just said RH=1 is not defined in physical
mode, but instead they are trying to tell you what the restrictions are if you
set it on.

The default config for PCI devices seems to be DM=1,RH=1.

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/2] kvm: x86: Extended struct kvm_lapic_irq with msi_redir_hint for MSI delivery

2015-03-18 Thread James Sullivan
Extended struct kvm_lapic_irq with bool msi_redir_hint, which will
be used to determine if the delivery of the MSI should target only
the lowest priority CPU in the logical group specified for delivery.
(In physical dest mode, the RH bit is not relevant). Initialized the value
of msi_redir_hint to true when RH=1 in kvm_set_msi_irq(), and initialized
to false in all other cases.

Added value of msi_redir_hint to a debug message dump of an IRQ in
apic_send_ipi().

Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
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.
Changes since v2:
* Added old patch (5502fedb.3030...@gmail.com) to set the value of
dest_mode in kvm_set_msi_irq() to be APIC_DEST_LOGICAL only when RH=1/DM=1,
and APIC_DEST_PHYSICAL otherwise. This decouples the dependency of 
this patch set on the previous submission and collects all efforts
to implement RH bit handling into one submission.
* Patch formatting
Changes since v3:
* Reverted logic for setting dest_mode to RH=1/DM=1 (see
20150318225225.ga8...@amt.cnet; this is for consistency with
the interpretation of DM and RH in native_compose_msi_msg())

 arch/x86/include/asm/kvm_host.h | 1 +
 arch/x86/kvm/ioapic.c   | 1 +
 arch/x86/kvm/irq_comm.c | 3 ++-
 arch/x86/kvm/lapic.c| 6 --
 arch/x86/kvm/x86.c  | 1 +
 5 files changed, 9 insertions(+), 3 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 72298b3..80c10af 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -106,9 +106,10 @@ static inline void kvm_set_msi_irq(struct 
kvm_kernel_irq_routing_entry *e,
irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
irq-trig_mode = (1  MSI_DATA_TRIGGER_SHIFT)  e-msi.data;
irq-delivery_mode = e-msi.data  0x700;
+   irq-msi_redir_hint = ((e-msi.address_lo
+MSI_ADDR_REDIRECTION_LOWPRI)  0);
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }
 
 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
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.3

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/2] kvm: x86: Deliver MSI IRQ to only lowest prio cpu if msi_redir_hint is true

2015-03-18 Thread James Sullivan
An MSI interrupt should only be delivered to the lowest priority CPU
when it has RH=1, regardless of the delivery mode. Modified
kvm_is_dm_lowest_prio() to check for either irq-delivery_mode == APIC_DM_LOWPRI
or irq-msi_redir_hint.

Moved kvm_is_dm_lowest_prio() into lapic.h and renamed to
kvm_lowest_prio_delivery().

Changed a check in kvm_irq_delivery_to_apic_fast() from
irq-delivery_mode == APIC_DM_LOWPRI to kvm_is_dm_lowest_prio().

Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
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().
Changes since v2:
* Patch formatting
Changes since v3:
N/A

 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 80c10af..9efff9e 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.3

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 0/2] kvm: x86: Implement handling of RH=1 for MSI delivery in KVM

2015-03-18 Thread 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() 
Changes since v2:
* Extend Patch 1/2 (kvm: x86: Extended struct kvm_lapic_irq with 
msi_redir_hint for MSI delivery) with older patch to set the value
of dest_mode in kvm_set_msi_irq() to be APIC_DEST_LOGICAL only when 
RH=1/DM=1, and APIC_DEST_PHYSICAL otherwise. 
(5502fedb.3030...@gmail.com)
This was done to decouple the patch dependency and to collect all
efforts to implement RH bit handling into one submission.
* Patch formatting
Changes since v3:
* Revert logic for setting dest_mode; irq-dest_mode is now set
independently of RH=1. (See 20150318225225.ga8...@amt.cnet).
The reason for this is to maintain consistenty with the interpretation
of MSI destination mode selection in native_compose_msi_msg().

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/23

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).

-James

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-18 Thread James Sullivan
 
 The documentation states the following:
 
 * When RH is 0, the interrupt is directed to the processor listed in the
 Destination ID field.
 
 * If RH is 0, then the DM bit is ignored and the message is sent ahead
 independent of whether the physical or logical destination mode is used.
 
 However, from the POV of a device writing to memory to generate an MSI 
 interrupt, there is no (or i can't see any) other information that 
 can be used to infer logical or physical mode for the interrupt message.
 
 Before your patch:
 
 (dm, rh) = (0, 0) = irq-dest_mode = 0
 (dm, rh) = (0, 1) = irq-dest_mode = 0
 (dm, rh) = (1, 0) = irq-dest_mode = 1
 (dm, rh) = (1, 1) = irq-dest_mode = 1
 
 After your patch:
 
 (dm, rh) = (0, 0) = irq-dest_mode = 0
 (dm, rh) = (0, 1) = irq-dest_mode = 0
 (dm, rh) = (1, 0) = irq-dest_mode = 0
 (dm, rh) = (1, 1) = irq-dest_mode = 1
 
 
 Am i missing some explicit documentation that refers 
 to (dm, rh) = (1, 0) = irq-dest_mode = 0 ?

From the IA32 manual (Vol. 3, 10.11.2):

 * When RH is 0, the interrupt is directed to the processor listed
   in the Destination ID field.
 * When RH is 1 and the physical destination mode is used, the Destination
   ID field must not be set to FFH; it must point to a processor that is
   present and enabled to receive the interrupt.
 * When RH is 1 and the logical destination mode is active in a system using
   a flat addressing model, the Destination ID field must be set so that bits
   set to 1 identify processors that are present and enabled to receive the
   interrupt.
 * If RH is set to 1 and the logical destination mode is active in a system
   using cluster addressing model, then Destination ID field must not be
   set to FFH; the processors identified with this field must be present
   and enabled to receive the interrupt.

My interpretation of this is that RH=0 indicates that the Dest. ID field
contains an APIC ID, and as such destination mode is physical. When RH=1,
depending on the value of DM, we either use physical or logical dest mode.
The result of this is that logical dest mode is set just when RH=1/DM=1,
as far as I understand.

 
 See native_compose_msi_msg:
 
 msg-address_lo =
 MSI_ADDR_BASE_LO |
 ((apic-irq_dest_mode == 0) ?
 MSI_ADDR_DEST_MODE_PHYSICAL :
 MSI_ADDR_DEST_MODE_LOGICAL) |
 ((apic-irq_delivery_mode != dest_LowestPrio) ?
 MSI_ADDR_REDIRECTION_CPU :
 MSI_ADDR_REDIRECTION_LOWPRI) |
 MSI_ADDR_DEST_ID(dest);
 
 
 So it does configure DM = MSI_ADDR_DEST_MODE_LOGICAL
 and RH = MSI_ADDR_REDIRECTION_LOWPRI.
 

...and yet this is a good counterexample against my argument :)

What I think I'll do is revert this particular change so that dest_mode is
set independently of RH. While I'm not entirely convinced that this is the
intended interpretation, I do think that consistency with the existing logic
is probably desirable for the time being. If I can get closure on the matter
I'll re-submit that change, but for the time being I will undo it.

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-17 Thread James Sullivan
N.B. This patch has been re-submitted in a larger patch, see

1426555822-3280-1-git-send-email-sullivan.jame...@gmail.com

(The new patch relies on changes made in this patch, and as such
it makes more sense to bundle them)

On 03/13/2015 09:14 AM, James Sullivan wrote:
 This patch adds a check for RH=1 in kvm_set_msi_irq. Currently the
 DM bit is the only thing used to decide irq-dest_mode (logical when DM
 set, physical when unset). Documentation indicates that the DM bit will
 be 'ignored' when the RH bit is unset, and physical destination mode is
 used in this case.
 
 Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both
 RH=1/DM=1.
 
 This patch doesn't completely handle RH=1; if RH=1 then the delivery will 
 behave
 as in low priority mode (deliver the interrupt to only the lowest priority 
 processor),
 but the delivery mode may still used to specify the semantics of the delivery 
 beyond
 its destination.
 
 I will be trying and comparing a few options to handle this fully (extension 
 of
 struct kvm_lapic_irq, introduction of MSI specific delivery functions or 
 helpers,
 etc) and hope to have some patches to show in the near future.
 
 
 Signed-off-by: James Sullivan sullivan.jame...@gmail.com
 ---
 Changes since v2:
 * Added one time warning message when RH=1
 * Documented conflict between RH=1 and delivery mode
 * Tidied code to check RH=1/DM=1 (remove bool phys, use if/else)
 Changes since v3:
 * Fixed logical error in RH=1/DM=1 check
 * Aligned quotation blocks in multiline pr_warn_once argument
 Changes since v4:
 * Put error message string on single line
 
  arch/x86/kvm/irq_comm.c | 16 ++--
  1 file changed, 14 insertions(+), 2 deletions(-)
 
 diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
 index 72298b3..f2887ea 100644
 --- a/arch/x86/kvm/irq_comm.c
 +++ b/arch/x86/kvm/irq_comm.c
 @@ -103,12 +103,24 @@ 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;
 - irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
 + /*
 +  * 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;
 + else
 + 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-level = 1;
   irq-shorthand = 0;
 - /* TODO Deal with RH bit of MSI message address */
  }
 
  int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/2] kvm: x86: Implement handling of RH=1 for MSI delivery in KVM

2015-03-17 Thread James Sullivan
On 03/17/2015 02:19 AM, Jan Kiszka wrote:
 
 Once the kernel side is settled, would you mind looking into equivalent
 support for QEMU's APIC as well? Just to keep it easy to switch between
 both modes without too many functional restrictions.
 
 Thanks!
 Jan
 

Good idea! I'm hoping to participate in GSoC working on shunting some interrupt
handling devices out of the KVM and into QEMU, so that's definitely something
I'll start to look into.

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/2] kvm: x86: Extended struct kvm_lapic_irq with msi_redir_hint for MSI delivery

2015-03-16 Thread James Sullivan
In kvm_set_msi_irq(), the RH bit is currently ignored for
determining the destination mode of the MSI delivery, and only the
DM bit is used. Corrected this so that dest_mode is APIC_DEST_LOGICAL
only when RH=1/DM=1, and APIC_DEST_PHYSICAL otherwise.

Extended struct kvm_lapic_irq with bool msi_redir_hint, which will
be used to determine if the delivery of the MSI should target only
the lowest priority CPU in the logical group specified for delivery.
(In physical dest mode, the RH bit is not relevant). Initialized the value
of msi_redir_hint to true when RH=1 in kvm_set_msi_irq(), and initialized
to false in all other cases.

Added value of msi_redir_hint to a debug message dump of an IRQ in
apic_send_ipi().

Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
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.
Changes since v2:
* Added old patch (5502fedb.3030...@gmail.com) to set the value of
dest_mode in kvm_set_msi_irq() to be APIC_DEST_LOGICAL only when RH=1/DM=1,
and APIC_DEST_PHYSICAL otherwise. This decouples the dependency of 
this patch set on the previous submission and collects all efforts
to implement RH bit handling into one submission.
* Patch formatting

 arch/x86/include/asm/kvm_host.h | 1 +
 arch/x86/kvm/ioapic.c   | 1 +
 arch/x86/kvm/irq_comm.c | 9 +++--
 arch/x86/kvm/lapic.c| 6 --
 arch/x86/kvm/x86.c  | 1 +
 5 files changed, 14 insertions(+), 4 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 72298b3..5c33cca 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,17 @@ 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;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   if ((e-msi.address_lo  MSI_ADDR_REDIRECTION_LOWPRI) 
+   (e-msi.address_lo  MSI_ADDR_DEST_MODE_LOGICAL))
+   irq-dest_mode = APIC_DEST_LOGICAL;
+   else
+   irq-dest_mode = APIC_DEST_PHYSICAL;
irq-trig_mode = (1  MSI_DATA_TRIGGER_SHIFT)  e-msi.data;
irq-delivery_mode = e-msi.data  0x700;
+   irq-msi_redir_hint = ((e-msi.address_lo
+MSI_ADDR_REDIRECTION_LOWPRI)  0);
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }
 
 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
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

[PATCH v3 2/2] kvm: x86: Deliver MSI IRQ to only lowest prio cpu if msi_redir_hint is true

2015-03-16 Thread James Sullivan
An MSI interrupt should only be delivered to the lowest priority CPU
when it has RH=1, regardless of the delivery mode. Modified
kvm_is_dm_lowest_prio() to check for either irq-delivery_mode == APIC_DM_LOWPRI
or irq-msi_redir_hint.

Moved kvm_is_dm_lowest_prio() into lapic.h and renamed to
kvm_lowest_prio_delivery().

Changed a check in kvm_irq_delivery_to_apic_fast() from
irq-delivery_mode == APIC_DM_LOWPRI to kvm_is_dm_lowest_prio().

Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
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().
Changes since v2:
* Patch formatting

 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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 0/2] kvm: x86: Implement handling of RH=1 for MSI delivery in KVM

2015-03-16 Thread 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() 
Changes since v2:
* Extend Patch 1/2 (kvm: x86: Extended struct kvm_lapic_irq with 
msi_redir_hint for MSI delivery) with older patch to set the value
of dest_mode in kvm_set_msi_irq() to be APIC_DEST_LOGICAL only when 
RH=1/DM=1, and APIC_DEST_PHYSICAL otherwise. 
(5502fedb.3030...@gmail.com)
This was done to decouple the patch dependency and to collect all
efforts to implement RH bit handling into one submission.
* Patch formatting

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/23

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).

-James

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/2] Extended struct kvm_lapic_irq with bool msi_redir_hint for MSI delivery

2015-03-16 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@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.3030...@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

--
To unsubscribe from this list: send

[PATCH v2 0/2] Implement handling of RH=1 for MSI delivery in KVM

2015-03-16 Thread 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.3030...@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/23

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] Deliver to only lowest prio cpu if msi_redir_hint is true

2015-03-16 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@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.3030...@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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/9] Removed TODO in kvm_set_msi_irq

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/irq_comm.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 36d2ca3a..f993f2f 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;
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/9] Extended kvm_lapic_irq struct with 'bool redir_hint' for MSI delivery

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/include/asm/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

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 {
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/9] Set irq-msi_redir_hint = 1 in kvm_set_msi_irq if RH=1

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/irq_comm.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index f2887ea..7e0f469 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -116,9 +116,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;
 }
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/9] Set default value for msi_redir_hint=false in kvm_pv_kick_cpu_op

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/x86.c | 1 +
 1 file changed, 1 insertion(+)

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/9] Deliver to only low-prio cpu in kvm_irq_delivery_to_apic_fast when MSI RH=1

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/lapic.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index c26afc9..c946470 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -702,7 +702,8 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct 
kvm_lapic *src,
 
bitmap = apic_logical_id(map, mda);
 
-   if (irq-delivery_mode == APIC_DM_LOWEST) {
+   if (irq-delivery_mode == APIC_DM_LOWEST ||
+   irq-msi_redir_hint) {
int l = -1;
for_each_set_bit(i, bitmap, 16) {
if (!dst[i])
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH RFC 0/9] Implement handling of RH=1 for MSI delivery in KVM

2015-03-14 Thread James Sullivan
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/23

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 9/9] Print value of msi_redir_hint in debug dump of irq in apic_send_ipi

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/lapic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index c946470..bced6d5 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -903,10 +903,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);
 }
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/9] Prevent delivery to non-lowest priority vcpus in kvm_irq_delivery_to_apic

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/irq_comm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 7e0f469..36d2ca3a 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -76,7 +76,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_is_dm_lowest_prio(irq)  !irq-msi_redir_hint) {
if (r  0)
r = 0;
r += kvm_apic_set_irq(vcpu, irq, dest_map);
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/9] Set default value for msi_redir_hint=false in apic_send_ipi

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/lapic.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index bd4e34d..c26afc9 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
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/9] Set default value for msi_redir_hint=false in ioapic_service

2015-03-14 Thread James Sullivan
Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/ioapic.c | 1 +
 1 file changed, 1 insertion(+)

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);
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v4] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-13 Thread James Sullivan
On 03/13/2015 08:39 AM, Radim Krčmář wrote:
...
 The warning message is very clever:
 - it contains the magical may qualifier and being protected only by
   RH=1 creates weird-looking code structure, but it is technically right
   1) lowest-priority delivery may be set in msi.data, which avoids our
  otherwise incorrect behavior with RH=1/DM=1
   2) RH=1/DM=0 can't deliver to multiple APICs (broadcast is forbidden),
  but real hardware may overwrite delivery mode from msi.data
 - being two lines apart adds to suspicion, yet it can be hint to those
   possible problems

 I only fear it is too clever :)


For the error message, how does:

kvm: MSI RH=1 unsupported, use low-priority delivery mode

Sit with you?

-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v4] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-13 Thread James Sullivan
Perfect, thanks for the feedback. I'll get v5 out shortly.

On 03/13/2015 09:08 AM, Radim Krčmář wrote:
 2015-03-13 08:47-0600, James Sullivan:
 On 03/13/2015 08:39 AM, Radim Krčmář wrote:
 ...
 The warning message is very clever:
 - it contains the magical may qualifier and being protected only by
   RH=1 creates weird-looking code structure, but it is technically right
   1) lowest-priority delivery may be set in msi.data, which avoids our
  otherwise incorrect behavior with RH=1/DM=1
   2) RH=1/DM=0 can't deliver to multiple APICs (broadcast is forbidden),
  but real hardware may overwrite delivery mode from msi.data
 - being two lines apart adds to suspicion, yet it can be hint to those
   possible problems

 I only fear it is too clever :)


 For the error message, how does:

  kvm: MSI RH=1 unsupported, use low-priority delivery mode

 Sit with you?
 
 I actually liked the former.
 
 New one doesn't say what is the impact of the error and the advice is
 not easy follow -- people usually have no idea what low-priority
 delivery mode is and nothing can be done outside of the guest.
 
 (I put the rant mainly for future reviewers;  the alternative I had in
  was to warn only when DM=1.)
 
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Patch v5] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-13 Thread James Sullivan
This patch adds a check for RH=1 in kvm_set_msi_irq. Currently the
DM bit is the only thing used to decide irq-dest_mode (logical when DM
set, physical when unset). Documentation indicates that the DM bit will
be 'ignored' when the RH bit is unset, and physical destination mode is
used in this case.

Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both
RH=1/DM=1.

This patch doesn't completely handle RH=1; if RH=1 then the delivery will behave
as in low priority mode (deliver the interrupt to only the lowest priority 
processor),
but the delivery mode may still used to specify the semantics of the delivery 
beyond
its destination.

I will be trying and comparing a few options to handle this fully (extension of
struct kvm_lapic_irq, introduction of MSI specific delivery functions or 
helpers,
etc) and hope to have some patches to show in the near future.


Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
Changes since v2:
* Added one time warning message when RH=1
* Documented conflict between RH=1 and delivery mode
* Tidied code to check RH=1/DM=1 (remove bool phys, use if/else)
Changes since v3:
* Fixed logical error in RH=1/DM=1 check
* Aligned quotation blocks in multiline pr_warn_once argument
Changes since v4:
* Put error message string on single line

 arch/x86/kvm/irq_comm.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..f2887ea 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,24 @@ 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;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* 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;
+   else
+   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-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Patch v3] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-12 Thread James Sullivan
(Disregard past message- submitted the wrong patch file, apologies.)

This patch adds a check for RH = 1 in kvm_set_msi_irq. Currently the
DM bit is the only thing used to decide irq-dest_mode (logical when DM
set, physical when unset). Documentation indicates that the DM bit will
be 'ignored' when the RH bit is unset, and physical destination mode is
used in this case.

Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both
RH=1/DM=1.

This patch doesn't completely handle RH=1; if RH=1 then the delivery will behave
as in low priority mode (deliver the interrupt to only the lowest priority 
processor),
but the delivery mode may still used to specify the semantics of the delivery 
beyond
its destination.

I will be trying and comparing a few options to handle this fully (extension of
struct kvm_lapic_irq, introduction of MSI specific delivery functions or 
helpers,
etc) and hope to have some patches to show in the near future.


Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
Changes since v2:
* Added one time warning message when RH=1
* Documented conflict between RH=1 and delivery mode
* Tidied code to check RH=1/DM=1 (remove bool phys, use if/else)

 arch/x86/kvm/irq_comm.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..35b4beb 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,25 @@ 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;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* 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 ^
+   MSI_ADDR_DEST_MODE_LOGICAL))
+   irq-dest_mode = APIC_DEST_LOGICAL;
+   else
+   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 may not correctly deliver MSIs 
+   with RH set.\n);
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Patch v4] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-12 Thread James Sullivan
(Correction of a rather obvious and embarrassing logical error in v3).

This patch adds a check for RH=1 in kvm_set_msi_irq. Currently the
DM bit is the only thing used to decide irq-dest_mode (logical when DM
set, physical when unset). Documentation indicates that the DM bit will
be 'ignored' when the RH bit is unset, and physical destination mode is
used in this case.

Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both
RH=1/DM=1.

This patch doesn't completely handle RH=1; if RH=1 then the delivery will behave
as in low priority mode (deliver the interrupt to only the lowest priority 
processor),
but the delivery mode may still used to specify the semantics of the delivery 
beyond
its destination.

I will be trying and comparing a few options to handle this fully (extension of
struct kvm_lapic_irq, introduction of MSI specific delivery functions or 
helpers,
etc) and hope to have some patches to show in the near future.


Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
Changes since v2:
* Added one time warning message when RH=1
* Documented conflict between RH=1 and delivery mode
* Tidied code to check RH=1/DM=1 (remove bool phys, use if/else)
Changes since v3:
* Fixed logical error in RH=1/DM=1 check
* Aligned quotation blocks in multiline pr_warn_once argument

 arch/x86/kvm/irq_comm.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..9514fed 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,24 @@ 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;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* 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;
+   else
+   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 may not correctly deliver MSIs 
+with RH set.\n);
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Patch v3] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-12 Thread James Sullivan
This patch adds a check in kvm_set_msi_irq for RH=1.

Currently the DM bit is the only thing used to decide irq-dest_mode
(logical when DM set, physical when unset). Documentation indicates that
the DM bit will be 'ignored' when the RH bit is unset, and physical destination
mode is used in this case.

Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both 
RH=1/DM=1.

This patch doesn't completely handle RH=1; if RH=1 then the delivery will behave
as in low priority mode (deliver the interrupt to only the lowest priority 
processor),
but the delivery mode is still used to specify the semantics of the delivery 
beyond
its destination. We can't just set irq-delivery_mode to APIC_DM_LOWPRI if RH=1 
since
this squashes the other delivery semantics. I've documented this in the patch.

I will be trying and comparing a few options to handle this fully (extension of
struct kvm_lapic_irq, introduction of MSI specific delivery functions or 
helpers,
etc) and hope to have some patches to show in the near future.


Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
Changes since v2:
* Added one time warning message when RH=1
* Documented conflict between RH=1 and delivery mode
* Tidied code to check RH=1/DM=1 (remove bool phys, use if/else)

 arch/x86/kvm/irq_comm.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..5975a3d 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -103,12 +103,25 @@ 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;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* 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) ^
+   (MS_ADDR_DEST_MODE_LOGICAL))
+   irq-dest_mode = APIC_DEST_LOGICAL;
+   else
+   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 may not correctly deliver MSIs 
+   to multiple APICs with RH set.\n);
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-11 Thread James Sullivan
This is a revised patch to the previous submission, adding a check for RH=1/DM=1
in kvm_set_msi_irq.

Currently the DM bit is the only thing used to decide irq-dest_mode
(logical when DM set, physical when unset). Documentation indicates that
the DM bit will be 'ignored' when the RH bit is unset, and physical destination
mode is used in this case.

Fixed this to set irq-dest_mode to APIC_DEST_LOGICAL just in case both 
RH=1/DM=1.

This patch doesn't completely handle RH=1; if RH=1 then the delivery will behave
as in low priority mode (deliver the interrupt to only the lowest priority 
processor),
but the delivery mode is still used to specify the semantics of the delivery 
beyond
its destination. We can't just set irq-delivery_mode to APIC_DM_LOWPRI if RH=1 
since
this squashes the other delivery semantics. I've documented this in the patch.

A future fix may be to implement a separate interrupt delivery function for MSI
interrupts in kvm_set_msi, which is a bit hacky but probably the only way to do 
this
without modifying the kvm_lapic_irq struct. I'll write this up and see how it 
looks,
unless there are major objections.


Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/irq_comm.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..327a4b8 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -97,18 +97,34 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct 
kvm_lapic *src,
 static inline void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
   struct kvm_lapic_irq *irq)
 {
+   bool phys;
trace_kvm_msi_set_irq(e-msi.address_lo, e-msi.data);

irq-dest_id = (e-msi.address_lo 
MSI_ADDR_DEST_ID_MASK)  MSI_ADDR_DEST_ID_SHIFT;
irq-vector = (e-msi.data 
MSI_DATA_VECTOR_MASK)  MSI_DATA_VECTOR_SHIFT;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* Set dest_mode to logical just in case both RH=1/DH=1,
+* otherwise default to physical
+*/
+   phys = ((e-msi.address_lo  (MSI_ADDR_REDIRECTION_LOWPRI |
+   MSI_ADDR_DEST_MODE_LOGICAL)) !=
+   (MSI_ADDR_REDIRECTION_LOWPRI |
+   MSI_ADDR_DEST_MODE_LOGICAL));
+   irq-dest_mode = phys ? APIC_DEST_PHYSICAL : APIC_DEST_LOGICAL;
irq-trig_mode = (1  MSI_DATA_TRIGGER_SHIFT)  e-msi.data;
irq-delivery_mode = e-msi.data  0x700;
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
+   /*
+* 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. However other delivery semantics are still
+*  specified by the delivery mode, so we can't default to
+*  APIC_DM_LOWPRI if RH=1.
+*/
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-11 Thread James Sullivan
On 03/11/2015 07:43 AM, Radim Krčmář wrote:
 2015-03-10 16:39-0600, James Sullivan:
 On 03/10/2015 08:47 AM, Radim Krčmář wrote:
 +  irq-dest_mode = phys ? 0 : (MSI_ADDR_DEST_MODE_LOGICAL);

 (Should be APIC_DEST_LOGICAL.  All works because it is a boolean and we
  only checked for APIC_DEST_PHYSICAL, which is 0.)


 Thank you, that should be as follows:
 irq-dest_mode = phys ? (APIC_DEST_PHYSICAL) : (APIC_DEST_LOGICAL);
 ?

 Yes, thanks.  (No need for parentheses around macros, we agreed to
 cover that in definition and they don't make this more readable.)


I'll tidy that up too.

 Your patch improves the situation, but removing the TODO is not
 warranted -- RH still doesn't do what it should:

 How does DM=1/RH=1 work on real hardware?
 (There seem to be interesting corner cases with irq-delivery_mode like
  APIC_DM_NMI.)

 The IA32 manual says that if DM=1/RH=1, we operate in logical destination 
 mode
 similarly to other IPIs. I don't believe this patch introduces any invalid
 settings listed in section 10-21, Vol. 3, so this shouldn't create any 
 weirdness.

 Quoting SDM Jan 2015, 10.11.1 Message Address Register Format:
   This bit [RH] indicates whether the message should be directed to the
   processor with the lowest interrupt priority among processors that can
   receive the interrupt.

 = it should behave like lowest priority delivery.
 Deliver to just one APIC -- we don't do that.

 KVM interrupt delivery functions can only specify lowest priority though
 delivery_mode and we would have to rework KVM if MSI can set something
 else in the delivery_mode (like NMI).


I see-- That will pose issues when you want some particular semantics of one
delivery mode (such as ignoring vector info in NMI) but want low-pri delivery.
Short of writing an MSI specific delivery function and calling it in 
kvm_set_msi,
I can't think of a way to get this. Do you think that's warranted?

I'll document this and resubmit this patch with the TODO for now. Thanks for the
insight.


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-10 Thread James Sullivan
On 03/10/2015 08:47 AM, Radim Krčmář wrote:
...
 +/*
 + * Set dest_mode to logical just in case both the RH and DM
 + * bits are set, otherwise default to physical.
 + */
 +phys = ((e-msi.address_lo  (MSI_ADDR_REDIRECTION_LOWPRI |
 +MSI_ADDR_DEST_MODE_LOGICAL)) !=
 +(MSI_ADDR_REDIRECTION_LOWPRI |
 +MSI_ADDR_DEST_MODE_LOGICAL));
 +irq-dest_mode = phys ? 0 : (MSI_ADDR_DEST_MODE_LOGICAL);
 
 (Should be APIC_DEST_LOGICAL.  All works because it is a boolean and we
  only checked for APIC_DEST_PHYSICAL, which is 0.)
 

Thank you, that should be as follows:

irq-dest_mode = phys ? (APIC_DEST_PHYSICAL) : (APIC_DEST_LOGICAL);

?

  irq-trig_mode = (1  MSI_DATA_TRIGGER_SHIFT)  e-msi.data;
  irq-delivery_mode = e-msi.data  0x700;
  irq-level = 1;
  irq-shorthand = 0;
 -/* TODO Deal with RH bit of MSI message address */
 
 RH bit still isn't deal with -- we do not use lowest-priority-like
 delivery in logical destination mode ...

Just want to make sure I understand this comment-
Isn't low-pri delivery mode used in kvm_irq_delivery_to_apic_fast
when irq-dest_mode  APIC_DEST_PHYSICAL (ie, logical)? (See below.)

Do you mean that this patch will interfere with this? As long as
irq-dest_mode is still APIC_DEST_LOGICAL this shouldn't change.


bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map)
{
.
if (irq-dest_mode == APIC_DEST_PHYSICAL) {
if (irq-dest_id = ARRAY_SIZE(map-phys_map))
goto out;

dst = map-phys_map[irq-dest_id];
} else {
u32 mda = irq-dest_id  (32 - map-ldr_bits);
u16 cid = apic_cluster_id(map, mda);

if (cid = ARRAY_SIZE(map-logical_map))
goto out;

dst = map-logical_map[cid];

bitmap = apic_logical_id(map, mda);

if (irq-delivery_mode == APIC_DM_LOWEST) {
int l = -1;
for_each_set_bit(i, bitmap, 16) {
if (!dst[i])
continue;
if (l  0)
l = i;
else if (kvm_apic_compare_prio(dst[i]-vcpu, 
dst[l]-vcpu)  0)
l = i;
}

bitmap = (l = 0) ? 1  l : 0;
}
}
.
}

 How does DM=1/RH=1 work on real hardware?
 (There seem to be interesting corner cases with irq-delivery_mode like
  APIC_DM_NMI.)
 

The IA32 manual says that if DM=1/RH=1, we operate in logical destination mode
similarly to other IPIs. I don't believe this patch introduces any invalid
settings listed in section 10-21, Vol. 3, so this shouldn't create any 
weirdness.

Thanks
-James
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] x86: irq_comm: Add check for RH bit in kvm_set_msi_irq

2015-03-09 Thread James Sullivan
Hi folks,

This is a small patch that implements logic to handle the RH bit
being set in the msi message address register. Currently the DM bit is
the only thing used to decide irq-dest_mode (logical when DM set,
physical when unset). Documentation indicates that the DM bit will be
ignored when the RH bit is unset, and physical destination mode is used
in this case.

Fixed this to set irq-dest_mode to logical just when both bits are set,
and physical otherwise.

Signed-off-by: James Sullivan sullivan.jame...@gmail.com
---
 arch/x86/kvm/irq_comm.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 72298b3..26bbab8 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -97,18 +97,26 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct 
kvm_lapic *src,
 static inline void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
   struct kvm_lapic_irq *irq)
 {
+   bool phys;
trace_kvm_msi_set_irq(e-msi.address_lo, e-msi.data);

irq-dest_id = (e-msi.address_lo 
MSI_ADDR_DEST_ID_MASK)  MSI_ADDR_DEST_ID_SHIFT;
irq-vector = (e-msi.data 
MSI_DATA_VECTOR_MASK)  MSI_DATA_VECTOR_SHIFT;
-   irq-dest_mode = (1  MSI_ADDR_DEST_MODE_SHIFT)  e-msi.address_lo;
+   /*
+* Set dest_mode to logical just in case both the RH and DM
+* bits are set, otherwise default to physical.
+*/
+   phys = ((e-msi.address_lo  (MSI_ADDR_REDIRECTION_LOWPRI |
+   MSI_ADDR_DEST_MODE_LOGICAL)) !=
+   (MSI_ADDR_REDIRECTION_LOWPRI |
+   MSI_ADDR_DEST_MODE_LOGICAL));
+   irq-dest_mode = phys ? 0 : (MSI_ADDR_DEST_MODE_LOGICAL);
irq-trig_mode = (1  MSI_DATA_TRIGGER_SHIFT)  e-msi.data;
irq-delivery_mode = e-msi.data  0x700;
irq-level = 1;
irq-shorthand = 0;
-   /* TODO Deal with RH bit of MSI message address */
 }

 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
-- 
2.3.1

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html