问题现象:在ARM服务器上,构造oops异常,本应该产生panic,进入dump流程,并且系统重启,但是系统并未重启,而是出现了卡死,在串口会隔一段时间就循环打印调用栈信息。如下所示

linux-fATqUY login: [ME] Fault detect start!
[ME] Fault detect start!
[ 254.202183] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[ 254.211111] Mem abort info:
[ 254.213939] ESR = 0x96000044
[ 254.217042] Exception class = DABT (current EL), IL = 32 bits
[ 254.223054] SET = 0, FnV = 0
[ 254.226154] EA = 0, S1PTW = 0
[ 254.229335] Data abort info:
[ 254.232261] ISV = 0, ISS = 0x00000044
[ 254.236155] CM = 0, WnR = 1
[ 254.239167] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000509fb5ee
[ 254.245883] [0000000000000000] pgd=0000000000000000
[ 254.250838] Internal error: Oops: 96000044 [#1] SMP
[ 254.255785] CPU: 0 PID: 58147 Comm: gen_seri_oops/0 Kdump: loaded Tainted: 
[ 254.273985] pstate: 60000005 (nZCv daif -PAN -UAO)
[ 254.278851] pc : gen_seri_oops+0x28/0x38 [kpgen_kbox]
[ 254.283971] lr : gen_seri_oops+0x1c/0x38 [kpgen_kbox]
[ 254.289089] sp : ffff000033ea3e50
[ 254.292443] x29: ffff000033ea3e50 x28: 0000000000000000
[ 254.297831] x27: ffff000035fdbb08 x26: ffff803f713412b8
[ 254.303218] x25: ffff000000fb2370 x24: 0000000000000000
[ 254.308605] x23: ffff0000091bcb10 x22: ffff80df64dc2e80
[ 254.380350] Process gen_seri_oops/0 (pid: 58147, stack limit = 0x0000000088aed8c0)
[ 254.391639] Call trace:
[ 254.397760] gen_seri_oops+0x28/0x38 [kpgen_kbox]
[ 254.406069] kthread+0x108/0x138
[ 254.412721] ret_from_fork+0x10/0x18
[ 254.419733] Code: 95c66ac7 d2800001 52800c22 52800000 (39000022)
[ 254.429390] die event detected
[ 254.436533] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008
[ 254.448966] Mem abort info:
[ 254.455502] ESR = 0x96000004
[ 254.462278] Exception class = DABT (current EL), IL = 32 bits
[ 254.472023] SET = 0, FnV = 0
[ 254.478845] EA = 0, S1PTW = 0
[ 254.485645] Data abort info:
[ 254.492130] ISV = 0, ISS = 0x00000004
[ 254.499576] CM = 0, WnR = 0
[ 254.505933] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000509fb5ee
[ 254.515960] [0000000000000008] pgd=0000000000000000

  360.462046] watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [docker-containe:29506]
[ 360.473208] Modules linked in: pt_MASQUERADE(E) iptable_nat(E) ……
[ 360.565132] CPU: 35 PID: 29506 Comm: docker-containe Kdump: loaded Tainted: G OEL 4.19.5-1.1.29.aarch64 #1[ 360.595535] pstate: 80000005 (Nzcv daif -PAN -UAO)
[ 360.604905] pc : smp_call_function_many+0x308/0x370
[ 360.614105] lr : smp_call_function_many+0x2c4/0x370
[ 360.623278] sp : ffff00002f4739e0
[ 360.630878] x29: ffff00002f4739e0 x28: ffff000009592184
[ 360.640673] x27: ffff80bffbeb2f08 x26: 0000000000000000
[ 360.650447] x25: ffff00000818a790 x24: 0000000000000001
[ 360.660310] x23: 0000000000001000 x22: ffff000009592184
[ 360.670118] x21: ffff000009589000 x20: ffff80bffbeb2d08
[ 360.680004] x19: ffff80bffbeb2d00 x18: 000000000bf5d62e
[ 360.689922] x17: 000000bf5d62e000 x16: 000000bf5d62f000
[ 360.699700] x15: 0000000000000008 x14: 0000000000000000
[ 360.709468] x13: 0000000000000001 x12: ffff803f72c8b530
[ 360.719251] x11: 0000000000000000 x10: 0000000000000b80
[ 360.728983] x9 : 0000000000000000 x8 : ffff80bffbeb3108
[ 360.738859] x7 : 0000000000000000 x6 : 000000000000003f
[ 360.748533] x5 : 0000000000000000 x4 : fffffff7ffffffff
[ 360.758230] x3 : 0000000000000000 x2 : ffff803ffbe69638
[ 360.767909] x1 : 0000000000000003 x0 : 0000000000000000
[ 360.777504] Call trace:
[ 360.784282] smp_call_function_many+0x308/0x370
[ 360.793075] kick_all_cpus_sync+0x30/0x38
[ 360.801443] sync_icache_aliases+0x74/0x98
[ 360.809852] __sync_icache_dcache+0x94/0xc8
[ 360.818371] alloc_set_pte+0x460/0x570
[ 360.826435] filemap_map_pages+0x3e0/0x400
[ 360.834510] __handle_mm_fault+0xb78/0x10f0
[ 360.842743] handle_mm_fault+0xf4/0x1c0
[ 360.850561] do_page_fault+0x230/0x488
[ 360.858095] do_translation_fault+0x74/0x84
[ 360.865948] do_mem_abort+0x6c/0x130
[ 360.873255] do_el0_ia_bp_hardening+0x64/0xa8
[ 360.881020] el0_ia+0x18/0x1c
[ 364.514043] watchdog: BUG: soft lockup - CPU#51 stuck for 22s! [vm_io_monitor.p:10065]
下面的内容同上
[ 464.446045] watchdog: BUG: soft lockup - CPU#30 stuck for 22s! [kill:2031]
[  516.538048] watchdog: BUG: soft lockup - CPU#58 stuck for 23s! [libvirtd:29334]
[  576.358044] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [logrotate:2045]

问题原因:在进入dump流程中,dump相关的组件如kernel box出现了空指针访问,出现了oops嵌套。每次在出现oops后,进入内核异常处理流程,执行die函数,该函数中会获取锁,raw_spin_lock_irqsave($die_lock,flags),然后又会在通知链中调用kernel box的注册回调函数,在回调过程中,由于这个回调函数内部又存在空指针访问,又出现oops,又走入了异常处理流程,进入die函数,那么这是想要获取锁,就获取不到,一直在等锁。

问题来了:

1、为何每个cpu打印调用栈都是stuck 20s左右呢?

2、如果一个cpu出现了死锁,其他cpu为何会softlockup呢?

3、为啥每个cpu的调用栈都在smp_call_function_many

现在我们来看第一个问题,20s的时间刚好是softlockup的时间,那么什么是softlockup呢,其实说白了,就是抢占被长时间关闭,导致进程无法调度。系统为每个cpu core注册了一个一般的kernel线程,这个线程会定期的调用watchdog函数,这个函数在时钟中断更新时,kernel线程才会被得到运行。当kernel线程里的watchdog函数中的一个watchdog_touch_ts变量在最近20s没有被更新,那就意味这个这个线程在20s内没有被调度,很有可能就是在某个cpu core上抢占被关闭了。所以调度器没法进行调度。那么与之对应的就是hardlockup,是中断被长时间关闭导致的更严重的问题。

那么,为什么一个cpu上出现了死锁,其他的cpu也会出现softlockup呢,让我们来分析一下softlockup的调用栈,在不清楚这些calltrace函数都是干什么的时候,分析为啥其他cpu上也会出现softlockup是一件难事。经过我多次搜索,差不多理清了思路。调用栈中的两个关键函数是kick_all_cpus_sync, sync_icache_aliases,从函数名称大概能看出这些函数是用来做cpu之间的cache同步的。我们服务器上大概有64个cpu,为了保证cache的一致性,应该会有一种机制来对所有cpu进行同步 。那么如何进行同步,从一篇patch文章中搜到https://patchwork.kernel.org/patch/10325093/,可以查到一些相关信息,如下内容:

kick_all_cpus_sync() forces all CPUs to sync caches by sending broadcast
IPI. If CPU is in extended quiescent state (idle task or nohz_full
userspace), this work may be done at the exit of this state.

也就是说通过广播IPI中断,来强制让所有cpu来同步cache。具体的IPI中断的相关介绍可以参考http://www.voidcn.com/article/p-auwhbhgz-oh.html。IPI中断,是核间通信同步的一种方式。

这篇博客https://segmentfault.com/a/1190000017238912,其实与我遇到的问题很像,摘录这里的一段总结:

一方面,为了避免产生竞争,线程在刷新本地tlb的时候,会停掉抢占。这就导致一个结果:其他的线程,当然包括watchdog线程,没有办法被调度执行(soft lockup)。另外一方面,为了要求其他cpu同步地刷新tlb,当前线程会使用ipi和其他cpu同步进展,直到其他cpu也完成刷新为止。其他cpu如果迟迟不配合,那么当前线程就会死等。

我们来看一下   smp_call_function_many这个函数的最后面就是在等待。

void smp_call_function_many(const struct cpumask *mask,
smp_call_func_t func, void *info, bool wait)
{
……
if (wait) {
for_each_cpu(cpu, cfd->cpumask) {
struct call_single_data *csd; csd = per_cpu_ptr(cfd->csd, cpu);
csd_lock_wait(csd);
}
}
}

那么当cpu 0上出现了oops后,后面又出现了死锁,在刚进入oops时,做的第一件事情就是禁用中断。这个非常好理解,oops逻辑要做的事情是保存现场,它当然不希望,中断在这个时候破坏问题现场。

分析到这里,这个问题就清晰了,当其他cpu例行公事的发过来IPI中断,CPU0 出现了死锁无法响应,于是其他cpu就在死等,进而导致其他cpu上都产生了softlockup。

附录:

do_mem_abort是在arm体系架构中,当出现缺页异常,或者访问空指针后arm的中断异常处理。__handle_mm_fault这个函数是在处理大页缺页时的处理函数。具体可以参考http://www.leviathan.vip/2019/03/03/Linux%E5%86%85%E6%A0%B8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E5%86%85%E5%AD%98%E8%AF%B7%E9%A1%B5%E6%9C%BA%E5%88%B6/

内核访问空指针之后的处理流程 https://blog.csdn.net/rikeyone/article/details/80021720https://blog.csdn.net/zangdongming/article/details/38543059

嵌套OOPS导致系统卡死 每个CPU都上报softlockup的问题的更多相关文章

  1. 由于服务主机:DCOM服务进程占用过多CPU,导致系统卡死

    最近在使用电脑的时候,总是出现电脑死机,而且鼠标也是经常卡在那里不动了,开始以为是鼠标的问题,还换了个鼠标(飙泪中),这还是一个血的教训啊!!!之后打开任务管理器发现CPU占用已经达到100%,而且一 ...

  2. Memory Ordering (注意Cache带来的副作用,每个CPU都有自己的Cache,内存读写不再一定需要真的作内存访问)

    Memory Ordering   Background 很久很久很久以前,CPU忠厚老实,一条一条指令的执行我们给它的程序,规规矩矩的进行计算和内存的存取. 很久很久以前, CPU学会了Out-Of ...

  3. 与wait for a undo record相关的系统卡死

    今天下班之前同事过来找我寻求帮助,说是某客户的ORACEL数据库服务器从昨天起就开始很奇怪,一个语句执行很慢很慢,好像整个系统都卡住了.      问题1:请问最近应用系统有更新过程序吗?答:没有更新 ...

  4. Linux系统排查2——CPU负载篇

    本随笔介绍CPU负载的排查手段. 查看系统负载的工具:uptime,w,都能查看系统负载,系统平均负载是处于运行或不可打扰状态的进程的平均数, 可运行:运行态,占用CPU,或就绪态,等待CPU调度. ...

  5. 转---高并发Web服务的演变——节约系统内存和CPU

    [问底]徐汉彬:高并发Web服务的演变——节约系统内存和CPU 发表于22小时前| 4223次阅读| 来源CSDN| 22 条评论| 作者徐汉彬 问底Web服务内存CPU并发徐汉彬 摘要:现在的Web ...

  6. [转载] PHP升级导致系统负载过高问题分析

    原文:http://chuansongme.com/n/797172 背景 据XX部门兄弟反应, 其在将PHP从5.3.8 升级到5.5.13 时, 开始运行正常, 运行一段时间后, 系统负载变高,达 ...

  7. 分析 PHP升级导致系统负载过高问题(转载)

    原文:http://chuansongme.com/n/797172 背景 据XX部门兄弟反应, 其在将PHP从5.3.8 升级到5.5.13 时, 开始运行正常, 运行一段时间后, 系统负载变高,达 ...

  8. Android ScrollView嵌套GridView导致GridView只显示一行item

    Android ScrollView嵌套GridView导致GridView只显示一行item Android ScrollView在嵌套GridView时候,会导致一个问题发生:GridView只显 ...

  9. linux中/etc/fstab文件删除或修改了,导致系统无法启动

    在linux中,/etc/fstab文件是磁盘挂载的问题,若该文件不小心给修改了,或者被删除了,那么就会导致系统无法重启.因为/etc/fstab文件是记录磁盘挂载的信息,若该文件出现了问题,那么对应 ...

随机推荐

  1. Linux vi 命令 – 文本编辑器

    vi命令是linux系统字符界面下的最常用的文本编辑器. vi编辑器是所有linux的标准编辑器,用于编辑任何ASCⅡ文本,对于编辑源程序尤其有用.iv编辑器功能非常强大,可以对文本进行创建,查找,替 ...

  2. 《PHP程序员面试笔试宝典》——如何解决求职中的时间冲突问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 对求职者而言,求职季就是一个赶场季,一天少则几家.十几家企业入校招聘,多则几十家.上百家企业招兵买马.企业多,选择项自然 ...

  3. Solution -「CF 156D」Clues

    \(\mathcal{Description}\)   link.   给一个 \(n\) 个点 \(m\) 条边的无向图 \(G\).设图上有 \(k\) 个连通块,求出添加 \(k-1\) 条边使 ...

  4. Solution -「CF 908D」New Year&Arbitrary Arrangement

    \(\mathcal{Description}\)   Link.   给定 \(n,p_a,p_b\),初始有一个空串,每次操作有 \(\frac{p_a}{p_a+p_b}\) 的概率在其后添加字 ...

  5. k8s集群节点ping不通其他主机的ip

    文章目录 排查过程 本地宿主机网络检查 pod网络检查 tcpdump检查网络 检查flannel网卡 检查宿主机网卡 iptables检查 解决方法 测试环境服务出现问题,服务一直报错认证超时,检查 ...

  6. JUC并发工具类之Semaphore控制并发线程数

    首先看看关于Semaphore的UML图: 从上图看,信号量的实现原理与锁类似,是基于AQS的:有公平与非公平之分.当初始的资源数为1时就退化为排它锁了,资源总数即state的初始值,在acquire ...

  7. 异常Java

    异常 1.什么是异常 异常指程序运行过程中出现的不期而至的各种状况,如:文件找不到.网络连接失败等 异常发生在程序运行期间,它影响了正常的程序执行流程 public class Demo01 { pu ...

  8. 理解OAuth2.0协议和授权机制

    无论是自然资源还是互联网上的资源,需要控制使用权与被使用权,以保护资源的安全.合理的使用和有效的管控. 项目中,我们需要控制的是用户资源,既要保证有效用户的合理使用,又要防范非法用户的攻击.如此,如何 ...

  9. HMS Core在MWC2022展示最新开放能力,助力开发者构建精品应用

    [2022年2月28日,巴塞罗那]世界移动通信大会MWC2022在巴塞罗那开幕.HMS Core设立了3个展台(Fira Gran Via,Hall 1),向全球开发者展示HMS Core 6的全新开 ...

  10. Codeforces Round #770 (Div. 2)D

    传送门 题目大意: 交互题, n ( 4 ≤ n ≤ 1000 ) n(4\leq n\leq1000) n(4≤n≤1000)个数字组成的数列 a 1 , a 2 , - , a n ( 0 ≤ a ...