From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55321) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YaUJf-0006aY-Ie for qemu-devel@nongnu.org; Tue, 24 Mar 2015 15:16:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YaUJW-0001pa-8P for qemu-devel@nongnu.org; Tue, 24 Mar 2015 15:16:43 -0400 Received: from mail-pa0-x235.google.com ([2607:f8b0:400e:c03::235]:33754) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YaUJV-0001ot-Um for qemu-devel@nongnu.org; Tue, 24 Mar 2015 15:16:34 -0400 Received: by pabxg6 with SMTP id xg6so2619307pab.0 for ; Tue, 24 Mar 2015 12:16:33 -0700 (PDT) From: James Sullivan Date: Tue, 24 Mar 2015 13:13:46 -0600 Message-Id: <1427224426-9025-6-git-send-email-sullivan.james.f@gmail.com> In-Reply-To: <1427224426-9025-1-git-send-email-sullivan.james.f@gmail.com> References: <1427224426-9025-1-git-send-email-sullivan.james.f@gmail.com> Subject: [Qemu-devel] [PATCH v2 5/5] apic: Implement handling of RH=1 for MSI interrupt delivery List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, James Sullivan , mst@redhat.com Added argument to apic_get_delivery_bitmask() for msi_redir_hint, and changed calls to the function accordingly (using 0 as a default value for non-MSI interrupts). Modified the implementation of apic_get_delivery_bitmask() to account for the RH bit of an MSI IRQ. The RH bit indicates that the message should target only the lowest-priority processor among those specified by the logical destination of the IRQ. Signed-off-by: James Sullivan --- hw/intc/apic.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index f3ec2c8..f4cc1df 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -37,7 +37,8 @@ static APICCommonState *local_apics[MAX_APICS + 1]; static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICCommonState *s); static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, - uint8_t dest, uint8_t dest_mode); + uint8_t dest, uint8_t dest_mode, + uint8_t msi_redir_hint); static int apic_get_arb_pri(APICCommonState *s); /* Find first bit starting from msb */ @@ -326,7 +327,7 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, trace_apic_deliver_irq(dest, dest_mode, delivery_mode, vector_num, trigger_mode, msi_redir_hint); - apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode, msi_redir_hint); apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); } @@ -503,7 +504,8 @@ static int apic_find_dest(uint8_t dest) } static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, - uint8_t dest, uint8_t dest_mode) + uint8_t dest, uint8_t dest_mode, + uint8_t msi_redir_hint) { APICCommonState *apic_iter; int i; @@ -519,23 +521,27 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, } } else { /* XXX: cluster mode */ + int l = -1; memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); for(i = 0; i < MAX_APICS; i++) { apic_iter = local_apics[i]; - if (apic_iter) { - if (apic_iter->dest_mode == 0xf) { - if (dest & apic_iter->log_dest) - apic_set_bit(deliver_bitmask, i); - } else if (apic_iter->dest_mode == 0x0) { - if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && - (dest & apic_iter->log_dest & 0x0f)) { - apic_set_bit(deliver_bitmask, i); + if (!apic_iter) { + break; + } + if (apic_match_dest(apic_iter, dest_mode, dest)) { + if (msi_redir_hint) { + if (l < 0 || + apic_compare_prio(apic_iter, local_apics[l]) < 0) { + l = i; } + } else { + apic_set_bit(deliver_bitmask, i); } - } else { - break; } } + if (msi_redir_hint && l >= 0) { + apic_set_bit(deliver_bitmask, l); + } } } @@ -568,7 +574,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, switch (dest_shorthand) { case 0: - apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); + apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode, 0); break; case 1: memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); -- 2.3.3