[Bug 274074] native_apic_alloc_vectors() does not properly align vectors when 32 are requested

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 25 Sep 2023 07:42:02 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274074

            Bug ID: 274074
           Summary: native_apic_alloc_vectors() does not properly align
                    vectors when 32 are requested
           Product: Base System
           Version: Unspecified
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: john@sanren.ac.za

Created attachment 245210
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=245210&action=edit
Fix to align the msi vector properly

MSI interrupt vectors needs to be aligned to the size of the request and have
to be in powers of 2.

The code in native_apic_alloc_vectors() does an alignment check in the loop:

    if ((vector & (align - 1)) != 0)
        continue;
    first = vector;

But when 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:

#define NRSVIDT         32
#define IDT_IO_INTS     NRSVIDT
#define APIC_IO_INTS    (IDT_IO_INTS + 16)

My fix is to include it during the alignment check:

--- /sys/x86/x86/local_apic.c.org       2023-04-07 02:34:45.000000000 +0200
+++ /sys/x86/x86/local_apic.c   2023-09-24 21:10:04.785720000 +0200
@@ -1657,7 +1657,7 @@

                /* 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;
                }

The patch is against 13.2, but the code in current looks the same.

Without the patch, pci_alloc_msi() with a count of 32 would return without an
error and allocate 32 vectors, but in my case with a base vector of 0x50 and
that was configured on the card. But the card would then ignore the bottom 5
bits and generate interrupt vectors from 0x40 to 0x5f.

-- 
You are receiving this mail because:
You are the assignee for the bug.