[PATCH] revert fpsimd change: run kernel mode NEON with softirqs disabled

From: g00657492
Date: Mon Aug 29 2022 - 04:07:32 EST


From: gaoxingwang <gaoxingwang1@xxxxxxxxxx>

After the call stack reaches the __local_bh_enable_ip function to start
a soft interrupt, the system crashes.

Call trace:
virtqueue_add_outbuf+0x3d0/0x7e0 [virtio_ring]
xmit_skb+0x174/0x280 [virtio_net]
start_xmit+0xa4/0x2a0 [virtio_net]
xmit_one.constprop.0+0xc0/0x1d0
dev_hard_start_xmit+0x54/0xd4
sch_direct_xmit+0xe4/0x5a0
__dev_queue_xmit+0x200/0xad0
dev_queue_xmit+0x1c/0x30
ip6_finish_output2+0x23c/0x6d0
__ip6_finish_output.part.0+0xb8/0x1b0
ip6_finish_output+0xec/0x12c
ip6_output+0x78/0x170
xfrm_output_resume+0x1ec/0x1fc
xfrm_output+0xac/0x3c0
__xfrm6_output+0x118/0x270
xfrm6_output+0x54/0xfc
ip6_xmit+0x2dc/0x5a4
inet6_csk_xmit+0x9c/0xfc
__tcp_transmit_skb+0x47c/0x79c
tcp_write_xmit+0x258/0x690
tcp_tsq_write+0x60/0xd0
tcp_tsq_handler+0xfc/0x150
tcp_tasklet_func+0xf4/0x164
tasklet_action_common.constprop.0+0x194/0x1b4
tasklet_action+0x30/0x3c
__do_softirq+0x130/0x358
do_softirq.part.0+0x84/0xa0
__local_bh_enable_ip+0xa4/0xb0
kernel_neon_end+0x30/0x50
sha1_ce_finup+0x324/0x378 [sha1_ce]
crypto_shash_finup+0x34/0xc0
hmac_finup+0x48/0xe0
crypto_shash_finup+0x34/0xc0
shash_digest_unaligned+0x74/0x90
crypto_shash_digest+0x4c/0x9c
shash_ahash_digest+0xdc/0x104
shash_async_digest+0x28/0x3c
crypto_ahash_digest+0x48/0xcc
ah6_output+0x2f0/0x3b0 [ah6]
xfrm_output_one+0x25c/0x4d4
xfrm_output_resume+0x6c/0x1fc
xfrm_output+0xac/0x3c0
__xfrm6_output+0x118/0x270
xfrm6_output+0x54/0xfc
ip6_xmit+0x2dc/0x5a4
inet6_csk_xmit+0x9c/0xfc
__tcp_transmit_skb+0x47c/0x79c
tcp_write_xmit+0x258/0x690
__tcp_push_pending_frames+0x44/0x104
tcp_push+0xe8/0x140
tcp_sendmsg_locked+0xb98/0xca0
tcp_sendmsg+0x40/0x70
inet6_sendmsg+0x4c/0x80
sock_sendmsg+0x48/0x70
__sys_sendto+0x120/0x14c
__arm64_sys_sendto+0x30/0x40
el0_svc_common.constprop.0+0x7c/0x1bc
do_el0_svc+0x2c/0x94
el0_svc+0x20/0x30
el0_sync_handler+0xb0/0xb4
el0_sync+0x160/0x180

Try to revert commit 13150149aa6d that added local_bh_enable in crypto to avoid
scheduling soft interrupts frequently when using ipsec in a non-preemptible kernel.
It works for some cases, but still have one faild, which is
tcp4-multi-diffport11.I don't know how to figure it.
Call trace like this:

[ 4490.908551] watchdog: BUG: soft lockup - CPU#3 stuck for 22s!
[ns-tcpserver:179956]
[ 4490.909804] Modules linked in: ah6 nfsv3 xfrm4_tunnel tunnel4 ipcomp
xfrm_ipcomp sctp aes_ce_ccm ccm esp6 ah4 rpcsec_gss_krb5 nfsv4
dns_resolver nfs fscache authenc echainiv esp4 sm4_generic libsm4
twofish_generic twofish_common camellia_generic serpent_generic
blowfish_generic blowfish_common cast5_generic cast_common des_generic
libdes sm3_generic rmd160 sha512_generic sha512_arm64 af_key rpcrdma
rdma_cm iw_cm ib_cm ib_core nfsd auth_rpcgss nfs_acl lockd grace nfs_ssc
nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet
nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_tables
ebtable_nat ebtable_broute ip6table_nat ip6table_mangle ip6table_raw
ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6
nf_defrag_ipv4 libcrc32c iptable_mangle iptable_raw iptable_security
ip_set rfkill nfnetlink ebtable_filter ebtables ip6table_filter
ip6_tables iptable_filter ip_tables kbox(O) sysmonitor(O) kboxdriver(O)
sunrpc vfat sg fat sch_fq_codel fuse
[ 4490.909938] ksecurec(O) ext4 mbcache jbd2 sd_mod t10_pi
virtio_gpu ghash_ce virtio_scsi virtio_console virtio_dma_buf
sha2_ce virtio_net net_failover failover sha256_arm64 sha1_ce
virtio_pci virtio_mmio virtio_ring virtio dm_mirror dm_region_hash
dm_log dm_mod aes_neon_bs aes_neon_blk aes_ce_blk crypto_simd cryptd
aes_ce_cipher
[ 4490.909989] Sample time: 4490524888320 ns(HZ: 250)
[ 4490.909990] Sample stat:
[ 4490.909995] curr: user: 217254140760, nice: 293968560, sys:
536817552400, idle: 3322823533580, iowait: 76154397960, irq:
26827662860, softirq: 308879528700, st: 0
[ 4490.909998] deta: user: 217254140760, nice: 293968560, sys:
536817552400, idle: 3322823533580, iowait: 76154397960, irq:
26827662860, softirq: 308879528700, st: 0
[ 4490.909999] Sample softirq:
[ 4490.910002] TIMER: 101755
[ 4490.910004] NET_TX: 9
[ 4490.910006] NET_RX: 10877748
[ 4490.910008] TASKLET: 10808
[ 4490.910009] SCHED: 455852
[ 4490.910011] HRTIMER: 111
[ 4490.910012] RCU: 551796
[ 4490.910013] Sample irqstat:
[ 4490.910017] irq 1: delta 155028, curr: 155028, IPI
[ 4490.910019] irq 2: delta 12421, curr: 12421, IPI
[ 4490.910024] irq 12: delta 1145220, curr: 1145220,
arch_timer
[ 4490.910055] irq 79: delta 4344, curr: 4344,
virtio2-input.0
[ 4490.910058] irq 80: delta 40040, curr: 40040,
virtio2-output.0
[ 4490.910061] irq 82: delta 3404649, curr: 3404649,
virtio3-input.0
[ 4490.910064] irq 83: delta 4149166, curr: 4149166,
virtio3-output.0
[ 4490.910068] irq 88: delta 3, curr: 3,
virtio0-virtqueues
[ 4490.910072] irq 94: delta 7262, curr: 7262,
virtio1-control
[ 4490.910076] irq 97: delta 344611, curr: 344611,
virtio6-input.0
[ 4490.910082] CPU: 3 PID: 179956 Comm: ns-tcpserver Kdump: loaded
Tainted: G O
5.10.0-60.18.0.50.h459.eulerosv2r11.aarch64 #1
[ 4490.910084] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0
02/06/2015
[ 4490.910088] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO BTYPE=--)
[ 4490.910100] pc : dev_shutdown+0x538/0x6a0
[ 4490.910102] lr : sch_direct_xmit+0x184/0x5a0
[ 4490.910104] sp : ffff800102ff2d90
[ 4490.910106] x29: ffff800102ff2d90 x28: ffff0000370533e8
[ 4490.910109] x27: 0000000000000026 x26: ffff0000370533c0
[ 4490.910113] x25: ffff0000f4f59000 x24: 0000000000000001
[ 4490.910116] x23: 0000000000000003 x22: ffff0000f4f92200
[ 4490.910120] x21: ffff0000c09a70ac x20: ffff0000370534c0
[ 4490.910123] x19: ffff0000c09a7000 x18: 0000000000002081
[ 4490.910126] x17: 0000000008020208 x16: ffff8001000bd7b0
[ 4490.910129] x15: ffff80008145b960 x14: ffff000000281800
[ 4490.910133] x13: ffff0000d1fd5710 x12: ffff80008145b260
[ 4490.910136] x11: ffff80008145b360 x10: ffff8000811263e0
[ 4490.910140] x9 : ffff800100b25604 x8 : 0000000000000000
[ 4490.910143] x7 : 0000000000000010 x6 : ffff0000c0cbcd00
[ 4490.910146] x5 : ffff0000f4f922c0 x4 : 0000000000000000
[ 4490.910149] x3 : ffff0000f4f922c0 x2 : 0000000000000001
[ 4490.910153] x1 : 0000000000000000 x0 : ffff8001013f1008
[ 4490.910157] Call trace:
[ 4490.910164] dev_shutdown+0x538/0x6a0
[ 4490.910167] __dev_queue_xmit+0x200/0xac0
[ 4490.910170] dev_queue_xmit+0x1c/0x30
[ 4490.910174] ip_finish_output2+0x248/0x550
[ 4490.910176] __ip_finish_output+0x16c/0x1c4
[ 4490.910178] ip_finish_output+0x3c/0xdc
[ 4490.910180] ip_output+0xb8/0x144
[ 4490.910184] xfrm_output_resume+0x1ec/0x1fc
[ 4490.910186] xfrm_output+0xac/0x3c0
[ 4490.910189] xfrm4_output+0x64/0x130
[ 4490.910192] __ip_queue_xmit+0x168/0x3d0
[ 4490.910194] ip_queue_xmit+0x1c/0x30
[ 4490.910197] __tcp_transmit_skb+0x498/0x770
[ 4490.910200] __tcp_retransmit_skb+0x1bc/0x58c
[ 4490.910202] tcp_retransmit_skb+0x2c/0xf0
[ 4490.910204] tcp_xmit_retransmit_queue.part.0+0x154/0x2b0
[ 4490.910207] tcp_xmit_retransmit_queue+0x24/0x30
[ 4490.910209] tcp_xmit_recovery+0x40/0x8c
[ 4490.910212] tcp_ack+0x3cc/0x720
[ 4490.910214] tcp_rcv_established+0x1c8/0x77c
[ 4490.910217] tcp_v4_do_rcv+0x184/0x2a0
[ 4490.910219] tcp_v4_rcv+0xcac/0x10f0
[ 4490.910221] ip_protocol_deliver_rcu+0xf4/0x200
[ 4490.910224] ip_local_deliver_finish+0x58/0x70
[ 4490.910225] ip_local_deliver+0x68/0x120
[ 4490.910228] xfrm4_rcv_encap_finish2+0x28/0x34
[ 4490.910231] xfrm_trans_reinject+0xb8/0xf0
[ 4490.910235] tasklet_action_common.constprop.0+0x194/0x1b4
[ 4490.910237] tasklet_action+0x30/0x3c
[ 4490.910240] __do_softirq+0x130/0x358
[ 4490.910242] do_softirq.part.0+0x84/0xa0
[ 4490.910244] __local_bh_enable_ip+0xa4/0xb0
[ 4490.910254] ipt_do_table+0x350/0x4d0 [ip_tables]
[ 4490.910257] ipt_mangle_out+0x50/0xe0 [iptable_mangle]
[ 4490.910260] iptable_mangle_hook+0x48/0x54 [iptable_mangle]
[ 4490.910263] nf_hook_slow+0x54/0xf0
[ 4490.910266] __ip_local_out+0xf8/0x140
[ 4490.910268] __ip_queue_xmit+0x140/0x3d0
[ 4490.910270] ip_queue_xmit+0x1c/0x30
[ 4490.910273] __tcp_transmit_skb+0x498/0x770
[ 4490.910275] tcp_write_xmit+0x284/0x6f0
[ 4490.910278] __tcp_push_pending_frames+0x44/0x104
[ 4490.910280] tcp_push+0xe8/0x140
[ 4490.910282] tcp_sendmsg_locked+0xba8/0xd40
[ 4490.910284] tcp_sendmsg+0x40/0x70
[ 4490.910287] inet_sendmsg+0x4c/0x80
[ 4490.910290] sock_sendmsg+0x48/0x70
[ 4490.910293] __sys_sendto+0x120/0x14c
[ 4490.910295] __arm64_sys_sendto+0x30/0x40
[ 4490.910298] el0_svc_common.constprop.0+0x7c/0x1bc
[ 4490.910300] do_el0_svc+0x2c/0x94
[ 4490.910304] el0_svc+0x20/0x30
[ 4490.910307] el0_sync_handler+0xb0/0xb4
[ 4490.910309] el0_sync+0x160/0x180

Signed-off-by: gaoxingwang <gaoxingwang1@xxxxxxxxxx>
---
arch/arm64/crypto/aes-modes.S | 2 +-
arch/arm64/crypto/sha1-ce-core.S | 2 +-
arch/arm64/crypto/sha2-ce-core.S | 2 +-
arch/arm64/crypto/sha3-ce-core.S | 4 ++--
arch/arm64/crypto/sha512-ce-core.S | 2 +-
arch/arm64/include/asm/assembler.h | 28 +++++++---------------------
arch/arm64/kernel/asm-offsets.c | 2 --
arch/arm64/kernel/fpsimd.c | 4 ++--
8 files changed, 15 insertions(+), 31 deletions(-)

diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S
index 503d9b317..ab570aa86 100644
--- a/arch/arm64/crypto/aes-modes.S
+++ b/arch/arm64/crypto/aes-modes.S
@@ -641,7 +641,7 @@ AES_FUNC_START(aes_mac_update)
cbz w5, .Lmacout
encrypt_block v0, w2, x1, x7, w8
st1 {v0.16b}, [x4] /* return dg */
- cond_yield .Lmacout, x7, x8
+ cond_yield .Lmacout, x7
b .Lmacloop4x
.Lmac1x:
add w3, w3, #4
diff --git a/arch/arm64/crypto/sha1-ce-core.S b/arch/arm64/crypto/sha1-ce-core.S
index 889ca0f89..8c02bbc26 100644
--- a/arch/arm64/crypto/sha1-ce-core.S
+++ b/arch/arm64/crypto/sha1-ce-core.S
@@ -121,7 +121,7 @@ CPU_LE( rev32 v11.16b, v11.16b )
add dgav.4s, dgav.4s, dg0v.4s

cbz w2, 2f
- cond_yield 3f, x5, x6
+ cond_yield 3f, x5
b 0b

/*
diff --git a/arch/arm64/crypto/sha2-ce-core.S b/arch/arm64/crypto/sha2-ce-core.S
index 491179922..6cdea7d56 100644
--- a/arch/arm64/crypto/sha2-ce-core.S
+++ b/arch/arm64/crypto/sha2-ce-core.S
@@ -129,7 +129,7 @@ CPU_LE( rev32 v19.16b, v19.16b )

/* handled all input blocks? */
cbz w2, 2f
- cond_yield 3f, x5, x6
+ cond_yield 3f, x5
b 0b

/*
diff --git a/arch/arm64/crypto/sha3-ce-core.S b/arch/arm64/crypto/sha3-ce-core.S
index 9c77313f5..6f5208414 100644
--- a/arch/arm64/crypto/sha3-ce-core.S
+++ b/arch/arm64/crypto/sha3-ce-core.S
@@ -184,11 +184,11 @@ SYM_FUNC_START(sha3_ce_transform)
eor v0.16b, v0.16b, v31.16b

cbnz w8, 3b
- cond_yield 4f, x8, x9
+ cond_yield 3f, x8
cbnz w2, 0b

/* save state */
-4: st1 { v0.1d- v3.1d}, [x0], #32
+3: st1 { v0.1d- v3.1d}, [x0], #32
st1 { v4.1d- v7.1d}, [x0], #32
st1 { v8.1d-v11.1d}, [x0], #32
st1 {v12.1d-v15.1d}, [x0], #32
diff --git a/arch/arm64/crypto/sha512-ce-core.S b/arch/arm64/crypto/sha512-ce-core.S
index b6a3a36e1..d6e7f6c95 100644
--- a/arch/arm64/crypto/sha512-ce-core.S
+++ b/arch/arm64/crypto/sha512-ce-core.S
@@ -195,7 +195,7 @@ CPU_LE( rev64 v19.16b, v19.16b )
add v10.2d, v10.2d, v2.2d
add v11.2d, v11.2d, v3.2d

- cond_yield 3f, x4, x5
+ cond_yield 3f, x4
/* handled all input blocks? */
cbnz w2, 0b

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index ef5e60d6d..c447dbbde 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -15,7 +15,6 @@
#include <asm-generic/export.h>

#include <asm/asm-offsets.h>
-#include <asm/alternative.h>
#include <asm/cpufeature.h>
#include <asm/cputype.h>
#include <asm/debug-monitors.h>
@@ -692,32 +691,19 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
.endm

/*
- * Check whether preempt/bh-disabled asm code should yield as soon as
- * it is able. This is the case if we are currently running in task
- * context, and either a softirq is pending, or the TIF_NEED_RESCHED
- * flag is set and re-enabling preemption a single time would result in
- * a preempt count of zero. (Note that the TIF_NEED_RESCHED flag is
- * stored negated in the top word of the thread_info::preempt_count
- * field)
+ * Check whether preempt-disabled code should yield as soon as it
+ * is able. This is the case if re-enabling preemption a single
+ * time results in a preempt count of zero, and the TIF_NEED_RESCHED
+ * flag is set. (Note that the latter is stored negated in the)
+ * top word of the thread_info::preempt_count field)
*/
- .macro cond_yield, lbl:req, tmp:req, tmp2:req
+ .macro cond_yield, lbl:req, tmp:req
+#ifdef CONFIG_PREEMPTION
get_current_task \tmp
ldr \tmp, [\tmp, #TSK_TI_PREEMPT]
- /*
- * If we are serving a softirq, there is no point in yielding: the
- * softirq will not be preempted no matter what we do, so we should
- * run to completion as quickly as we can.
- */
- tbnz \tmp, #SOFTIRQ_SHIFT, .Lnoyield_\@
-#ifdef CONFIG_PREEMPTION
sub \tmp, \tmp, #PREEMPT_DISABLE_OFFSET
cbz \tmp, \lbl
#endif
- adr_l \tmp, irq_stat + IRQ_CPUSTAT_SOFTIRQ_PENDING
- this_cpu_offset \tmp2
- ldr w\tmp, [\tmp, \tmp2]
- cbnz w\tmp, \lbl // yield on pending softirq in task context
-.Lnoyield_\@:
.endm

/*
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 5f59e24c9..3ddfe6703 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -93,8 +93,6 @@ int main(void)
DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
BLANK();
DEFINE(PREEMPT_DISABLE_OFFSET, PREEMPT_DISABLE_OFFSET);
- DEFINE(SOFTIRQ_SHIFT, SOFTIRQ_SHIFT);
- DEFINE(IRQ_CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
BLANK();
#ifdef CONFIG_COMPAT
DEFINE(COMPAT_TVAL_TV_SEC, offsetof(struct old_timeval32, tv_sec));
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 5335a6bd1..a9bbfb800 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -180,7 +180,7 @@ static void __get_cpu_fpsimd_context(void)
*/
static void get_cpu_fpsimd_context(void)
{
- local_bh_disable();
+ preempt_disable();
__get_cpu_fpsimd_context();
}

@@ -201,7 +201,7 @@ static void __put_cpu_fpsimd_context(void)
static void put_cpu_fpsimd_context(void)
{
__put_cpu_fpsimd_context();
- local_bh_enable();
+ preempt_enable();
}

static bool have_cpu_fpsimd_context(void)
--
2.27.0