Bug 265639 - PF panic on armv7/BBB with 13.1-R
Summary: PF panic on armv7/BBB with 13.1-R
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: arm (show other bugs)
Version: 13.1-RELEASE
Hardware: arm Any
: --- Affects Many People
Assignee: Mateusz Guzik
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-08-05 07:31 UTC by Poul-Henning Kamp
Modified: 2022-08-16 10:14 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Poul-Henning Kamp freebsd_committer freebsd_triage 2022-08-05 07:31:04 UTC
Beagle-Bone-Black, 13-1 GENERICSD release image panics in PF:

    login: Fatal kernel mode data abort: 'Alignment Fault' on read
    trapframe: 0xd71a7930
    FSR=00000001, FAR=c3328224, spsr=60000013
    r0 =d71a7a48, r1 =27244242, r2 =bf798103, r3 =c3328224
    r4 =d1494200, r5 =d14db000, r6 =27244265, r7 =00000000
    r8 =c092c92c, r9 =d71a7b68, r10=00000001, r11=d71a79d8
    r12=d7297918, ssp=d71a79c0, slr=d724a5e8, pc =d7282800

    panic: Fatal abort
    cpuid = 0
    time = 1659683836
    KDB: stack backtrace:
    #0 0xc0355b70 at kdb_backtrace+0x48
    #1 0xc02fcb50 at vpanic+0x170
    #2 0xc02fc9e0 at vpanic+0
    #3 0xc061bc14 at abort_align+0
    #4 0xc061bc70 at abort_align+0x5c
    #5 0xc061b8e4 at abort_handler+0x480
    #6 0xc05fac68 at exception_exit+0
    #7 0xd7282800 at pf_syncookie_validate+0x3c
    #8 0xd724a5e8 at $a.110+0x20
    #9 0xd726c868 at $a.166+0x34
    #10 0xc0441f68 at pfil_run_hooks+0xa0
    #11 0xc046e808 at ip_input+0x694
    #12 0xc0440c70 at netisr_dispatch_src+0xf8
    #13 0xc043863c at ether_demux+0x1a4
    #14 0xc0439cd0 at ether_nh_input+0x480
    #15 0xc0440c70 at netisr_dispatch_src+0xf8
    #16 0xc0438b08 at ether_input+0x50
    #17 0xc0cfbee4 at $a.6+0x5a0

pf.conf available on request
Comment 1 Ed Maste freebsd_committer freebsd_triage 2022-08-05 18:50:29 UTC
Can you correlate the faulting PC with the source line?
Comment 2 Mark Johnston freebsd_committer freebsd_triage 2022-08-05 20:08:43 UTC
In my non-invariants copy of pf_syncookie_validate(), the instr at offset 0x3c is ldrexd  r4, [r3], which loads a 64-bit value from the address in r3, which according to the register dump below is not 8-byte aligned.

That's part of the atomic_add_64() implementation.  But, on arm uint64_t has 8-byte alignment, so I don't quite see how the misalignment can arise.
Comment 3 Mateusz Guzik freebsd_committer freebsd_triage 2022-08-16 09:35:34 UTC
The issue stems from VNET allocations only being aligned to 4.

how about this:

diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index 4f242b07f169..3a0d40a31b6a 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -377,7 +377,11 @@ vnet_data_alloc(int size)
        void *s;
 
        s = NULL;
+#if __LP32__
+       size = roundup2(size, 2 * sizeof(void *));
+#else
        size = roundup2(size, sizeof(void *));
+#endif
        sx_xlock(&vnet_data_free_lock);
        TAILQ_FOREACH(df, &vnet_data_free_head, vnd_link) {
                if (df->vnd_len < size)
@@ -409,7 +413,11 @@ vnet_data_free(void *start_arg, int size)
        uintptr_t start;
        uintptr_t end;
 
+#if __LP32__
+       size = roundup2(size, 2 * sizeof(void *));
+#else
        size = roundup2(size, sizeof(void *));
+#endif
        start = (uintptr_t)start_arg;
        end = start + size;
        /*
Comment 4 Mateusz Guzik freebsd_committer freebsd_triage 2022-08-16 10:02:41 UTC
heh, wow. there is no __LP32__ macro, someone(tm) will have to add one.

In the meantime the point is to validate everything works fine after the size is rounded up to a multiply of 8.
Comment 5 Mateusz Guzik freebsd_committer freebsd_triage 2022-08-16 10:14:15 UTC
This should do the trick:

diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index 4f242b07f169..da1fd0f36785 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -377,7 +377,17 @@ vnet_data_alloc(int size)
        void *s;
 
        s = NULL;
+#ifdef __ILP32__
+       /*
+        * Note that the area allocated here might hold fields
+        * modified with 64-bit atomics. Accomodate it by rounding
+        * the size up to a multiple of 64-bit to ensure the
+        * expected alignment.
+        */
+       size = roundup2(size, 2 * sizeof(void *));
+#else
        size = roundup2(size, sizeof(void *));
+#endif
        sx_xlock(&vnet_data_free_lock);
        TAILQ_FOREACH(df, &vnet_data_free_head, vnd_link) {
                if (df->vnd_len < size)
@@ -409,7 +419,11 @@ vnet_data_free(void *start_arg, int size)
        uintptr_t start;
        uintptr_t end;
 
+#ifdef __ILP32__
+       size = roundup2(size, 2 * sizeof(void *));
+#else
        size = roundup2(size, sizeof(void *));
+#endif
        start = (uintptr_t)start_arg;
        end = start + size;
        /*