https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663676&idx=1&sn=b18ab57322594ebb8e7072e635e8bd1c&chksm=810f29e1b678a0f7238e8a71fd88f14c3c71e65556d149bbe851f08f775300bc7bb6ddbb503a&mpshare=1&scene=1&srcid=07302BR8M8OSgsym8wtFHNaB&sharer_sharetime=1564482704949&sharer_shareid=6a5d5f4082de4dfaafd2e3b24b69c271&pass_ticket=%2F5q07o1VYrDuvadEaasOzg9XP3sH%2B7O3W7boz%2BUgwgRPvsLYbzZpFyYQyGgBbiiB#rd

如上链接是《宋宝华: Kernel Oops和Panic是一回事吗?》

大概介绍了在未开启panic_on_oops,内核态非中断上下文 发生 访问0地址 时,kernel只会发oops,而不会panic。

看完之后会有个疑问:缺页异常的上下文 是不是 中断上下文?

答案是否。具体解析如下:

1. 首先中断上下文是指当前HARDIRQ/NMI/softIRQ的计数不为0,code 如下:

 #define irq_count()    (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
| NMI_MASK))
#define in_interrupt() (irq_count())

  HARDIRQ 计数 在irq_enter()/irq_exit()接口中 做增减, 题外话:在irq_exit接口中通过invoke_softirq()触发软中断,一次执行时间限制在2ms或10次以内

  NMI 计数 在nmi_enter()/nmi_exit()接口中 做增减,ARM64貌似没有找到调用的地方?????

  softIRQ 计数 在__local_bh_disable_ip/__local_bh_enable接口中 做增减

2. 对于ARM64, 异常向量表如下:

 // 文件:arch/arm64/kernel/entry.S

 // 向量表------------------------------------------------------------------------------------------------
.align //对齐2^7=128
ENTRY(vectors)
ventry el1_sync_invalid // Synchronous EL1t
ventry el1_irq_invalid // IRQ EL1t
ventry el1_fiq_invalid // FIQ EL1t
ventry el1_error_invalid // Error EL1t ventry el1_sync // Synchronous EL1h 同步异常入口,缺页属于这一类
ventry el1_irq // IRQ EL1h IRQ中断入口, HARDIRQ/SOFTIRQ 计数均在此入口增减
ventry el1_fiq_invalid // FIQ EL1h FIQ入口,即NMI???? NMI计数应该在这个入口增减???
ventry el1_error_invalid // Error EL1h ventry el0_sync // Synchronous 64-bit EL0
ventry el0_irq // IRQ 64-bit EL0
ventry el0_fiq_invalid // FIQ 64-bit EL0
ventry el0_error_invalid // Error 64-bit EL0 #ifdef CONFIG_COMPAT
ventry el0_sync_compat // Synchronous 32-bit EL0
ventry el0_irq_compat // IRQ 32-bit EL0
ventry el0_fiq_invalid_compat // FIQ 32-bit EL0
ventry el0_error_invalid_compat // Error 32-bit EL0
#else
ventry el0_sync_invalid // Synchronous 32-bit EL0
ventry el0_irq_invalid // IRQ 32-bit EL0
ventry el0_fiq_invalid // FIQ 32-bit EL0
ventry el0_error_invalid // Error 32-bit EL0
#endif
END(vectors) // 同步异常:系统调用/数据abort/指令abort/未对齐/未定义/调试异常---------------------------------------------
.align
el1_sync:
kernel_entry
mrs x1, esr_el1 // read the syndrome register
lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class
cmp x24, #ESR_ELx_EC_DABT_CUR // data abort in EL1
b.eq el1_da
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el1_undef
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
b.eq el1_sp_pc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
b.eq el1_sp_pc
cmp x24, #ESR_ELx_EC_UNKNOWN // unknown exception in EL1
b.eq el1_undef
cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
b.ge el1_dbg
b el1_inv
// 数据abort
el1_da:
/*
* Data abort handling
*/
mrs x0, far_el1
enable_dbg
// re-enable interrupts if they were enabled in the aborted context
tbnz x23, #, 1f // PSR_I_BIT
enable_irq
:
mov x2, sp // struct pt_regs
// 跳往do_mem_abort->do_transation_fault->do_page_fault->do_kernel_fault->die->...
bl do_mem_abort // disable interrupts before pulling preserved data off the stack
disable_irq
kernel_exit
el1_sp_pc:
/*
* Stack or PC alignment exception handling
*/
mrs x0, far_el1
enable_dbg
mov x2, sp
b do_sp_pc_abort
el1_undef:
/*
* Undefined instruction
*/
enable_dbg
mov x0, sp
b do_undefinstr
el1_dbg:
/*
* Debug exception handling
*/
cmp x24, #ESR_ELx_EC_BRK64 // if BRK64
cinc x24, x24, eq // set bit '0'
tbz x24, #, el1_inv // EL1 only
mrs x0, far_el1
mov x2, sp // struct pt_regs
bl do_debug_exception
kernel_exit
el1_inv:
// TODO: add support for undefined instructions in kernel mode
enable_dbg
mov x0, sp
mov x1, #BAD_SYNC
mrs x2, esr_el1
b bad_mode
ENDPROC(el1_sync) // IRQ-------------------------------------------------------------------------------------------------------
.align
el1_irq:
kernel_entry
enable_dbg
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
// 中断入口调用:handle_arch_irq->handle_irq
irq_handler #ifdef CONFIG_PREEMPT
get_thread_info tsk
ldr w24, [tsk, #TI_PREEMPT] // get preempt count
cbnz w24, 1f // preempt count != 0
ldr x0, [tsk, #TI_FLAGS] // get flags
tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
// 中断返回前执行抢占
bl el1_preempt
:
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_on
#endif
kernel_exit
ENDPROC(el1_irq)

3. HARDIRQ softIRQ 计数增减 的 代码流程,即缺页异常的流程 如下图:

综上,在缺页的流程中:HARDIRQ/SOFTIRQ/NMI计数都没有增减,故in_interrupt()

内核态发生非法地址访问是否会panic的更多相关文章

  1. Linux内核情景分析之异常访问,用户堆栈的扩展

    情景假设: 在堆内存中申请了一块内存,然后释放掉该内存,然后再去访问这块内存.也就是所说的野指针访问. 当cpu产生页面错误时,会把失败的线性地址放在cr2寄存器.线性地址缺页异常的4种情况 1.如果 ...

  2. 核态获取PsLoadedModuleList地址的稳定方法

    转载: https://blog.csdn.net/celestialwy/article/details/1261407     PsLoadedModuleList是Windows加载的所有内核模 ...

  3. 用户态和内核态&操作系统

    用户态和内核态 内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序. 用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被 ...

  4. C# 读写文件从用户态切到内核态,到底是个什么流程?

    一:背景 1. 一个很好奇的问题 我们在学习 C# 的过程中,总会听到一个词叫做 内核态 ,比如说用 C# 读写文件,会涉及到代码从 用户态 到 内核态 的切换,用 HttpClient 获取远端的数 ...

  5. 获取内核当前执行模块和当前发生异常地址和线程异常Handler调用步骤

    循环每个内核模块 统计模块大小 判断触发异常的地址属于那个模块.来确定模块 获取发生异常地址 nt!_EXCEPTION_RECORD +0x000 ExceptionCode : -21391605 ...

  6. Linux用户态和内核态

    究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在于因为大部分时候我们在写程序时关注的重点和着眼的角度放在了实现的功能和代码的逻辑性上,先看一个例子: 1)例 ...

  7. linux 用户态 内核态

    http://blog.chinaunix.net/uid-1829236-id-3182279.html 究竟什么是用户态,什么是内核态,这两个基本概念以前一直理解得不是很清楚,根本原因个人觉得是在 ...

  8. Linux操作系统学习_用户态与内核态之切换过程

    因为操作系统的很多操作会消耗系统的物理资源,例如创建一个新进程时,要做很多底层的细致工作,如分配物理内存,从父进程拷贝相关信息,拷贝设置页目录.页表等,这些操作显然不能随便让任何程序都可以做,于是就产 ...

  9. 系统调用syscall---用户态切换到内核态的唯一途径

    1.应用程序有时需要内核协助完成一些处理,但是应用程序不可能执行内核代码(主要是安全性考虑), 那么,应用程序需要有一种机制告诉内核,它现在需要内核的帮助,这个机制就是系统调用. 2.系统调用的本质是 ...

随机推荐

  1. 201871010116-祁英红《面向对象程序设计(java)》第十七周学习总结

    博文正文开头格式:(2分) 项目 内容 <面向对象程序设计(java)> https://home.cnblogs.com/u/nwnu-daizh/ 这个作业的要求在哪里 https:/ ...

  2. appium元素定位之AndroidUiAutomator

    UIAutomator 元素定位是 Android 系统原生支持的定位方式,虽然与 xpath 类似,但比它更好用,并且支持元素全部的属性定位,定位原理是通过 android 自带的android u ...

  3. python django-admin.py startproject xxx 错误:from django.core import management

    1. Python安装路径以及Python安装路径\Script文件夹,已经添加到PATH环境变量中. 2. 查看django 版本正常: import django print(django.__v ...

  4. Use a Multiline Editor for String Properties 对字符串属性使用多行编辑器

    In this lesson, you will learn how to display a multiline editor for string properties. For this pur ...

  5. 使用MailKit发送带有内嵌图片的邮件且图片不显示成附件

    使用MailKit发送带有内嵌图片的邮件且图片不显示成附件 参考文章:MailKit---发送邮件 注意 在邮件客户端中是否显示内嵌图片为附件依据不同邮件有所不同,暂经测试Outlook和qq不显示为 ...

  6. Python 读取照片的信息:拍摄时间、拍摄设备、经纬度等,以及根据经纬度通过百度地图API获取位置

    通过第三方库exifread读取照片信息.exifread官网:https://pypi.org/project/ExifRead/ 一.安装exifreadpip install exifread ...

  7. Python完全平方数

    python解题源代码如下: import math """ 简述:一个整数,它加上100和加上268后都是一个完全平方数 提问:请问该数是多少? Python解题思路分 ...

  8. Python list遍历remove()时的一个小BUG

    有这样一个列表: s=list('abcdefg') 现在因为某种原因我们需要从s中踢出一些不需要的元素,方便起见这里直接以踢出所有元素的循环代替: for e in s: s.remove(e) 结 ...

  9. C#&.Net干货分享- iTextSharp导出数据源到PDF

    namespace Frame.ITextSharp{    /// <summary>    /// iTextSharp导出数据源到PDF    /// </summary> ...

  10. 利用phpqrcode二维码生成类库合成带logo的二维码并且用合成的二维码生成海报(二)

    前期准备 引入phpqrcode类库(下载地址:https://download.csdn.net/download/weixin_37557729/11891240:支持彩色二维码的下载地址:htt ...