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. 10. Vue - axios

    一.预备知识 1. JS面向对象 特点:ES5之前用构造函数方式,构造函数就是一个普通函数,它的函数名大写. 构造函数的问题:方法不会提升至构造函数内,而是每创建一个对象,就要把那个方法保存在每个对象 ...

  2. 埃氏筛法(求n以内有哪些个质数)

    核心思想:从i=2开始,划去i的倍数,即剩下i为质数(如删去2的倍数后2为质数,再删去3的倍数后3为质数,4被删除则跳过,5未被删除则记录然后删除5的倍数...以此类推) #include <b ...

  3. SpringMVC 简单限流方案设计

    一.概念 限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务.排队或等待.降级等处理. 常用的限流算法有两种:漏桶算法和令牌桶算法: ...

  4. 【linux命令 】文件特殊权限(SUID、SGID、SBIT)

    chmod 2770 /home/admins,刚看到这个命令,有点不解,后边770分别表示用户,组,其他人,前面的2不知道代表的是什么意思.百度之后发现2是代表八进制数,也是一种权限,它的三个bit ...

  5. 02-Nginx配置

    一.Nginx配置 1.创建Nginx运行使用的用户 www: / usr / sbin / groupadd www / usr / sbin / useradd -g www www 2.检查配置 ...

  6. kubernetes部署高可用redis

    本文redis通过helm搭建,提供redis高可用完整的编排,关于Helm的搭建和使用请查看文章<helm的搭建及使用>,其中前一章介绍了Helm搭建,并提供了Helm搭建Harbor的 ...

  7. python Json报错json.decoder.JSONDecodeError

    近期工作中遇到一个问题,执行json.loads(json_data)时,在json_data中加上tab空格后就报错,不加则不报错 一.json.loads(json_data) 报错json.de ...

  8. 压测 swoole_websocket_server 性能

    概述 这是关于 Swoole 入门学习的第十篇文章:压测 swoole_websocket_server 性能. 第九篇:Swoole Redis 连接池的实现 第八篇:Swoole MySQL 连接 ...

  9. PAT 1012 The Best Rank 排序

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  10. Sql sever DateDiff 函数

    函数: DATEDIFF(datepart,startdate,enddate) 具体实例: --相差年数 结果0 SELECT DATEDIFF(yy,'2008-12-29','2008-12-1 ...