git: d33a4ae8ba53 - main - x86: Properly align interrupt vectors for MSI

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 28 Sep 2023 21:18:37 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=d33a4ae8ba5343f555842e6e32321f9cd64dfd09

commit d33a4ae8ba5343f555842e6e32321f9cd64dfd09
Author:     John Hay <jhay@FreeBSD.org>
AuthorDate: 2023-09-28 21:08:08 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2023-09-28 21:08:08 +0000

    x86: Properly align interrupt vectors for MSI
    
    MSI (not MSI-X) interrupt vectors must be allocated in groups that are
    powers of 2, and the block of IDT vectors must be aligned to the size
    of the request.
    
    The code in native_apic_alloc_vectors() does an alignment check in the loop:
    
        if ((vector & (align - 1)) != 0)
            continue;
        first = vector;
    
    But it adds APIC_IO_INTS to the value it returns:
    
        return (first + APIC_IO_INTS);
    
    The problem is that APIC_IO_INTS is not a multiple of 32. It is 48:
    
    As a result, a request for 32 vectors (the max supported by MSI), was
    not always aligned.  To fix, check the alignment of
    'vector + APIC_IO_INTS' in the loop.
    
    PR:             274074
    Reviewed by:    jhb
---
 sys/x86/x86/local_apic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 17b0223f834b..b382368cc626 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -1582,7 +1582,7 @@ apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
 
 		/* Start a new run if run == 0 and vector is aligned. */
 		if (run == 0) {
-			if ((vector & (align - 1)) != 0)
+			if (((vector + APIC_IO_INTS) & (align - 1)) != 0)
 				continue;
 			first = vector;
 		}