From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53927) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnwNV-00015M-SF for qemu-devel@nongnu.org; Thu, 30 Apr 2015 17:52:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YnwNU-0002iO-MS for qemu-devel@nongnu.org; Thu, 30 Apr 2015 17:52:17 -0400 Received: from mail-pa0-x235.google.com ([2607:f8b0:400e:c03::235]:33188) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnwNU-0002iC-Aa for qemu-devel@nongnu.org; Thu, 30 Apr 2015 17:52:16 -0400 Received: by pacwv17 with SMTP id wv17so72210340pac.0 for ; Thu, 30 Apr 2015 14:52:15 -0700 (PDT) From: James Sullivan Date: Thu, 30 Apr 2015 15:49:16 -0600 Message-Id: <1430430556-21869-5-git-send-email-sullivan.james.f@gmail.com> In-Reply-To: <1430430556-21869-1-git-send-email-sullivan.james.f@gmail.com> References: <1430430556-21869-1-git-send-email-sullivan.james.f@gmail.com> Subject: [Qemu-devel] [PATCH v3 4/4] apic: Handle RH=1 and lowpri delivery mode in apic_get_delivery_bitmask() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, James Sullivan , jan.kiszka@siemens.com Added arguments to apic_get_delivery_bitmask() for msi_redir_hint and for delivery_mode, changing calls to the function accordingly (using 0 as a default value for msi_redir_hint for non-MSI interrupts). Modified the implementation of apic_get_delivery_bitmask() such that if msi_redir_hint == 1 or delivery_mode == APIC_DM_LOWPRI, only the lowest priority APIC will have its bitmask entry set (tie-breaking is arbitrary). Delivery of APIC_DM_LOWPRI in apic_bus_deliver() is then identical to APIC_DM_FIXED. Removed function apic_ffs_bit() which was only called to support interim LOWPRI delivery. Signed-off-by: James Sullivan --- Changes in v3: * Added extra argument to apic_get_delivery_bitmask() for delivery_mode * Perform lowpri arbitration in apic_get_delivery_bitmask() for RH=1 and for APIC_DM_LOWPRI, saving the cost of the LAPIC iteration in v2 * Deliver APIC_DM_LOWPRI identically to APIC_DM_FIXED (since the bitmask now accounts for arbitration implicitly) * Removed apic_ffs_bit() (no longer called) hw/intc/apic.c | 64 ++++++++++++++++++++++++---------------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 9dd27b2..1fe3877 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -37,7 +37,9 @@ 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 delivery_mode, + uint8_t msi_redir_hint); static int apic_get_arb_pri(APICCommonState *s); /* Find first bit starting from msb */ @@ -46,12 +48,6 @@ static int apic_fls_bit(uint32_t value) return 31 - clz32(value); } -/* Find first bit starting from lsb */ -static int apic_ffs_bit(uint32_t value) -{ - return ctz32(value); -} - static inline void apic_set_bit(uint32_t *tab, int index) { int i, mask; @@ -258,24 +254,8 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, switch (delivery_mode) { case APIC_DM_LOWPRI: - /* XXX: search for focus processor, arbitration */ - { - int i, d; - d = -1; - for(i = 0; i < MAX_APIC_WORDS; i++) { - if (deliver_bitmask[i]) { - d = i * 32 + apic_ffs_bit(deliver_bitmask[i]); - break; - } - } - if (d >= 0) { - apic_iter = local_apics[d]; - if (apic_iter) { - apic_set_irq(apic_iter, vector_num, trigger_mode); - } - } - } - return; + /* XXX: search for focus processor */ + break; case APIC_DM_FIXED: break; @@ -321,7 +301,8 @@ 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, delivery_mode, + msi_redir_hint); apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); } @@ -498,7 +479,9 @@ 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 delivery_mode, + uint8_t msi_redir_hint) { APICCommonState *apic_iter; int i; @@ -514,23 +497,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 || delivery_mode == APIC_DM_LOWPRI) { + if (l < 0 || + apic_compare_prio(apic_iter, local_apics[l]) < 0) { + l = i; } + } else { + apic_set_bit(deliver_bitmask, i); } - } else { - break; } } + if (l >= 0) { + apic_set_bit(deliver_bitmask, l); + } } } @@ -563,7 +550,8 @@ 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, + delivery_mode, 0); break; case 1: memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); -- 2.3.5