关于arm的异常向量表

以前, armv6 如 (arm9, arm11等) 有7种异常模式。 分别为:

User 用户模式, 应用程序运行于该模式。

Svc (Supervisor) 超级模式, bootloader及内核运行于该模式。 系统调用通过swi陷入内核态, 切换到Svc模式。

Sys (System) 系统模式, 一种特权模式, 貌似有些特殊场景会用, 比如中断嵌套等场景, 后续研究。

Abort  异常模式, 分为预取指令异常(prefetch abort)及数据异常(data abort)等, 有些会导致真实的崩溃, 有些linux拿来用于缺页异常和按需换页(demand paging)等用途。

Undef 未定义指令异常, 根据arm指令执行的流水线,  最早分为三条流水线, 取指,  译码, 执行, 未定义异常就是发生在译码阶段。

IRQ - 中断请求, interrupt request,  实在的外设中断, 核间中断等。

FIQ - 快速中断请求, fast interrupt request,  需要快速处理的中断可用该中断实现。


armv7, armv8 如cortex a7, a15, a53等芯片, 多了两种异常模式,

Hyp (Hypervisor) 虚拟化用途, 具体需要学习...

Mon (Monitor) 监视者模式, 不知道咋翻译... 主要用于trustzone方案上,  利用SMC(Secure Monitor Call)这条指令 可以 陷入 monitor模式,  切换运行模式, 到secure mode, 配置cp15某个协处理器寄存器, 可运行于安全的执行环境中。


 

前面介绍了arm的异常模式, 即cpu运行过程中发生的异常事件。 会打断cpu目前正在做的事, 转而进行异常处理。

具体异常行为该如何处理, 可由软件进行处理。 故以下介绍下软件行为。

 

bootrom, uboot, linux 都有定义异常向量表, 根据arm规范, 

Exception

Offset from vector base

Mode on entry

A bit on entry

F bit on entry

I bit on entry

Reset

0x00

Supervisor

Disabled

Disabled

Disabled

Undefined instruction

0x04

Undefined

Unchanged

Unchanged

Disabled

Software interrupt

0x08

Supervisor

Unchanged

Unchanged

Disabled

Prefetch Abort

0x0C

Abort

Disabled

Unchanged

Disabled

Data Abort

0x10

Abort

Disabled

Unchanged

Disabled

Reserved

0x14

Reserved

-

-

-

IRQ

0x18

IRQ

Disabled

Unchanged

Disabled

FIQ

0x1C

FIQ

Disabled

Disabled

Disabled

 

以上为随便搜索的ARM1136的异常向量表, arm32的芯片应该差不多。(aarch64/armv7/8? 引入了exception level, 即异常等级的概念, 差别较大。)

bootrom, uboot 都含有start.S, 查看开头几行。

 17 /*                                                                                                                                                                  
 18  *************************************************************************                                                                                          
 19  *                                                                                                                                                                  
 20  * Startup Code (reset vector)                                                                                                                                      
 21  *                                                                                                                                                                  
 22  * do important init only if we don't start from memory!                                                                                                            
 23  * setup Memory and board specific bits prior to relocation.                                                                                                        
 24  * relocate armboot to ram                                                                                                                                          
 25  * setup stack                                                                                                                                                      
 26  *                                                                                                                                                                  
 27  *************************************************************************                                                                                          
 28  */                                                                                                                                                                 
 29                                                                                                                                                                     
 30 ›   .globl› reset                                                                                                                                                   
 31                                                                                                                                                                     
 32 reset:                                                                                                                                                              
 33 ›   /*                                                                                                                                                              
 34 ›    * set the cpu to SVC32 mode                                                                                                                                    
 35 ›    */                                                                                                                                                             
 36 ›   mrs›r0,cpsr                                                                                                                                                     
 37 ›   bic›r0,r0,#0x1f                                                                                                                                                 
 38 ›   orr›r0,r0,#0xd3                                                                                                                                                 
 39 ›   msr›cpsr,r0                                                                                                                                                     
 40                                                                                                                                                                     
 41 ›   /* the mask ROM code should have PLL and others stable */                                                                                                       
 42 #ifndef CONFIG_SKIP_LOWLEVEL_INIT                                                                                                                                   
 43 ›   bl  cpu_init_crit                                                                                                                                               
 44 #endif                                                     

以上为uboot/arch/arm/cpu/arm1136/start.S

嗯, 只有reset向量的代码了, 即只包含复位/启动代码了||...


异常向量表放其他地方去了...

不过想来也是uboot/linux代码越来越庞大, 光arm片子就从arm7 ~ armv8 cortex a53啥的一坨... 挺多arm片子的异常向量表的代码都是一样的。 所以根据可复用的设计理念, 异常向量表被移到公用的地方去了。

 

继续找, 在uboot/arch/arm/lib里面找到了

vim uboot/arch/arm/lib/vector.S

 17 /*                                                                                                                                                                  
 18  * A macro to allow insertion of an ARM exception vector either                                                                                                     
 19  * for the non-boot0 case or by a boot0-header.                                                                                                                     
 20  */                                                                                                                                                                 
 21         .macro ARM_VECTORS                                                                                                                                          
 22 #ifdef CONFIG_ARCH_K3                                                                                                                                               
 23 ›   ldr     pc, _reset                                                                                                                                              
 24 #else                                                                                                                                                               
 25 ›   b›  reset                                                                                                                                                       
 26 #endif                                                                                                                                                              
 27 ›   ldr›pc, _undefined_instruction                                                                                                                                  
 28 ›   ldr›pc, _software_interrupt                                                                                                                                     
 29 ›   ldr›pc, _prefetch_abort                                                                                                                                         
 30 ›   ldr›pc, _data_abort                                                                                                                                             
 31 ›   ldr›pc, _not_used                                                                                                                                               
 32 ›   ldr›pc, _irq                                                                                                                                                    
 33 ›   ldr›pc, _fiq                                                                                                                                                    
 34 ›   .endm                                           

对照arm官方的定义, 就匹配上了,  如此当芯片发生硬件异常时(如reset, abort, interrupt等), 我们就能做异步/及时的处理了。

具体异常处理后面继续讨论。

看下该目录下的makefile

 10 ifdef CONFIG_CPU_V7M                                                                                                                                                
 11 obj-y›  += vectors_m.o crt0.o                                                                                                                                       
 12 else ifdef CONFIG_ARM64                                                                                                                                             
 13 obj-y›  += crt0_64.o                                                                                                                                                
 14 else                                                                                                                                                                
 15 obj-y›  += vectors.o crt0.o                                                                                                                                         
 16 endif           

可以看到, armv7, arm64和arm32是不一样的。

贴一下vectors_m.S的异常向量表,

 36    .section  .vectors                                                                                                                                               
 37 ENTRY(_start)                                                                                                                                                       
 38 ›   .long›  CONFIG_SYS_INIT_SP_ADDR››   @ 0 - Reset stack pointer                                                                                                   
 39 ›   .long›  reset›  ›   ›   ›   @ 1 - Reset                                                                                                                         
 40 ›   .long›  __invalid_entry››   ›   @ 2 - NMI                                                                                                                       
 41 ›   .long›  __hard_fault_entry› ›   @ 3 - HardFault                                                                                                                 
 42 ›   .long›  __mm_fault_entry›   ›   @ 4 - MemManage                                                                                                                 
 43 ›   .long›  __bus_fault_entry›  ›   @ 5 - BusFault                                                                                                                  
 44 ›   .long›  __usage_fault_entry››   @ 6 - UsageFault                                                                                                                
 45 ›   .long›  __invalid_entry››   ›   @ 7 - Reserved                                                                                                                  
 46 ›   .long›  __invalid_entry››   ›   @ 8 - Reserved                                                                                                                  
 47 ›   .long›  __invalid_entry››   ›   @ 9 - Reserved                                                                                                                  
 48 ›   .long›  __invalid_entry››   ›   @ 10 - Reserved                                                                                                                 
 49 ›   .long›  __invalid_entry››   ›   @ 11 - SVCall                                                                                                                   
 50 ›   .long›  __invalid_entry››   ›   @ 12 - Debug Monitor                                                                                                            
 51 ›   .long›  __invalid_entry››   ›   @ 13 - Reserved                                                                                                                 
 52 ›   .long›  __invalid_entry››   ›   @ 14 - PendSV                                                                                                                   
 53 ›   .long›  __invalid_entry››   ›   @ 15 - SysTick                                                                                                                  
 54 ›   .rept›  255 - 16                                                                                                                                                
 55 ›   .long›  __invalid_entry››   ›   @ 16..255 - External Interrupts                                                                                                 
 56 ›   .endr                                                          

挺多不认识了...  后面再研究...

哦,makefile里面还有个crt0.S, crt0_64.S的代码, 

全称C RunTime startup Code, 关于初始化C语言程序运行环境的。 比如bss段的初始化, 堆栈区域的定义等等。


ok,  这里有个疑问, bootrom, uboot, linux都有异常向量表的代码, 都有啥区别呢?

嗯, 没错, 都是给自己用的。

比如bootrom 代码控制启动方式,  是sd卡启动, 还是emmc启动, 还是nor flash启动, 甚至串口/usb启动。。。

如果内部发生异常, 走的就是bootrom的异常向量表... 所以bootrom启动时有程序异常... 那就片子起不来咯...

* 关于irq/fiq 中断, 通常情况下bootrom, uboot都不怎么用, 通常都采用轮训方式去实现功能, 不采用中断。

当然想用也是可以的^^。


ok, 关于linux的异常向量表, 

linux没有start.S, 开头是start_kernel

进去找找, 找到了

start_kernel->setup_arch->paging_init->devicemaps_init->early_trap_init

823 void __init early_trap_init(void *vectors_base)                                                                                                                     
824 {                                                                                                                                                                   
825 #ifndef CONFIG_CPU_V7M                                                                                                                                              
826 ›   unsigned long vectors = (unsigned long)vectors_base;                                                                                                            
827 ›   extern char __stubs_start[], __stubs_end[];                                                                                                                     
828 ›   extern char __vectors_start[], __vectors_end[];                                                                                                                 
829 ›   unsigned i;                                                                                                                                                     
830                                                                                                                                                                     
831 ›   vectors_page = vectors_base;                                                                                                                                    
832                                                                                                                                                                     
833 ›   /*                                                                                                                                                              
834 ›    * Poison the vectors page with an undefined instruction.  This                                                                                                 
835 ›    * instruction is chosen to be undefined for both ARM and Thumb                                                                                                 
836 ›    * ISAs.  The Thumb version is an undefined instruction with a                                                                                                  
837 ›    * branch back to the undefined instruction.                                                                                                                    
838 ›    */                                                                                                                                                             
839 ›   for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)                                                                                                                   
840 ›   ›   ((u32 *)vectors_base)[i] = 0xe7fddef1;                                                                                                                      
841                                                                                                                                                                     
842 ›   /*                                                                                                                                                              
843 ›    * Copy the vectors, stubs and kuser helpers (in entry-armv.S)                                                                                                  
844 ›    * into the vector page, mapped at 0xffff0000, and ensure these                                                                                                 
845 ›    * are visible to the instruction stream.                                                                                                                       
846 ›    */                                                                                                                                                             
847 ›   memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);                                                                                      
848 ›   memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);                                                                                   
849                                                                                                                                                                     
850 ›   kuser_init(vectors_base);                                                                                                                                       
851                                                                                                                                                                     
852 ›   flush_icache_range(vectors, vectors + PAGE_SIZE * 2);                                                                                                           
853 #else /* ifndef CONFIG_CPU_V7M */                                                                                                                                   
854 ›   /*                                                                                                                                                              
855 ›    * on V7-M there is no need to copy the vector table to a dedicated                                                                                             
856 ›    * memory area. The address is configurable and so a table in the kernel                                                                                        
857 ›    * image can be used.                                                                                                                                           
858 ›    */                                                                                                                                                             
859 #endif                                                                                                                                                              
860 }            

ok, 整个函数都贴了, 也没几行,  主要就是把__vectors_start到__vectors_end的异常向量表拷贝到vectors地址。

vectors地址是哪里, 分两种情况, 有mmu和没开mmu

没mmu, 所以是物理实际地址, 

720 #define vectors_base()› (vectors_high() ? 0xffff0000 : 0)

根据宏定义, 有两个, 0x0 或者0xffff0000,

 45 #if __LINUX_ARM_ARCH__ >= 4                                                                                                                                         
 46 #define vectors_high()› (get_cr() & CR_V)                                                                                                                           
 47 #else                                                                                                                                                               
 48 #define vectors_high()› (0)                                                                                                                                         
 49 #endif           

 70 static inline unsigned long get_cr(void)                                                                                                                            
 71 {                                                                                                                                                                   
 72 ›   unsigned long val;                                                                                                                                              
 73 ›   asm("mrc p15, 0, %0, c1, c0, 0› @ get CR" : "=r" (val) : : "cc");                                                                                               
 74 ›   return val;                                                                                                                                                     
 75 }         

有个cp15协处理寄存器可以配置, 告诉arm核心 用默认的0还是高位地址0xffff0000作为异常向量表开始地址。

 

如果有mmu, 那cpu看到的就是mmu映射的虚拟内存...即分配0x0, 0xffff0000这两个地方内存来使用,  具体实际物理内存在哪里,

那就要看mmu的 映射表如何配置的了....

          /*
1322 ›    * Allocate the vector page early. 
1323 ›    */
1324 ›   vectors = early_alloc(PAGE_SIZE * 2);        

1326 ›   early_trap_init(vectors); 

这部分 找到些博客:

https://www.cnblogs.com/arnoldlu/p/8060121.html

后面找时间研究下。

 


找下具体的异常向量表代码, __vectors_start,

trap.c同级目录下, 

kernel/arch/arm/kernel/entry-armv.S

1217 .L__vectors_start:                                                                                                                             
1218 ›   W(b)›   vector_rst                                                                                                                         
1219 ›   W(b)›   vector_und                                                                                                                         
1220 ›   W(ldr)› pc, .L__vectors_start + 0x1000                                                                                                     
1221 ›   W(b)›   vector_pabt                                                                                                                        
1222 ›   W(b)›   vector_dabt                                                                                                                        
1223 ›   W(b)›   vector_addrexcptn                                                                                                                  
1224 ›   W(b)›   vector_irq                                                                                                                         
1225 ›   W(b)›   vector_fiq       

是的, 和bootrom, uboot类似。

其中1220行, __vectors_start + 0x1000, 对比trap.c中的代码,

memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);

这部分__stubs_start的代码是干什么的, 继续探究以下:

1024 /*                                                                                                                                                                 
1025  * Vector stubs.                                                                                                                                                   
1026  *                                                                                                                                                                 
1027  * This code is copied to 0xffff1000 so we can use branches in the                                                                                                 
1028  * vectors, rather than ldr's.  Note that this code must not exceed                                                                                                
1029  * a page size.                                                                                                                                                    
1030  *                                                                                                                                                                 
1031  * Common stub entry macro:                                                                                                                                        
1032  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC                                                                                                       
1033  *                                                                                                                                                                 
1034  * SP points to a minimal amount of processor-private memory, the address                                                                                          
1035  * of which is copied into r0 for the mode specific abort handler.  
......
1076 ›   .section .stubs, "ax", %progbits                                                                                                                               
1077 ›   @ This must be the first word                                                                                                                                  
1078 ›   .word›  vector_swi      

__stubs_start没找到..., 但感觉就是vector_swi处。

即软件中断处理模块。后续介绍系统调用等会提及swi。

 

关于irq handler暂时没看明白怎么跳转的, 后续研究。


linux有哪些内容是用异常向量表来实现的呢??

1. 虚拟内存/按需换页

    操作系统的设计思路,  每个进程的映射空间都是0-4G空间(不考虑arm64)。其中3G-4G是内核空间,进程无法直接访问(需要通过系统调用等)

    每个进程使用独立的虚拟内存空间, 互不干扰。

    虚拟内存和物理内存间的映射关系由mmu进行, mmu参考页表进行转换。

    故可以理解, 每个进程都有独立的页表, 存放在内核 内存的某个地方,  当前cpu需要执行哪个进程, 需要加载当前进程页表的基地址。是的,  在操作系统切换进程时, 需要将需要执行的进程页表基地址 写入 cp15 某个寄存器中。如此该cpu就能进行正确的内存寻址。

    每个cpu核心硬件资源上都有对应的逻辑计算器, 算术计算器, 寄存器(以前是37个), 协处理器, 协处理器专用寄存器。

所以每个cpu跑 某个线程 都需要加载 对应的进程页表。 如果2个cpu跑同一个进程的不同线程, 他们使用的页表就是一样的。且能访问同一片内存区域。所以多线程需要进行关键数据区的同步/保护。


ok,  废话很多, 其实虚拟内存本身和异常模式没有关系... 有关系的是内存的加载方式。

Linux操作系统采用类似晚绑定的机制。用户运行程序, 该程序是在文件系统中, 即磁盘上。 程序开始运行时, 操作系统(加载器, loader)并不会把所有代码/依赖库全一股脑加载到内存中。而是分配好虚拟内存, 即相应页表映射。 只有当程序开始运行时, 发现

诶, main, funcA, funcB 都不在内存中, 此时就会发生pre-fetch abort, 即预取指令异常; 如果是访问某个全局变量, 如果数据不在内存, 则会发生data abort, 即数据异常。 Linux操作系统碰到此类异常, 会尝试去把相应数据从磁盘/flash加载到内存。然后程序就能继续执行了。 常见的如do_pagefault, demand_page等函数。

这里只提到了内存加载, 那如果物理内存不够用了, 该进程又在后台, 那么可以理解的,  操作系统应该会去释放这部分内存。

代码段及RO Data这些没关系, 都是只读的, 内核把这部分内存释放给别人用就可以了。 但是可读可写的全局变量等 该如何处理呢? 肯定不能简单得释放, 释放了下次重新加载值就不对了。。。也不能回写到磁盘, 这是全局变量, 不是文件系统的文件....

这部分需要研究下,  但根据我的理解,  无外乎两种方式,

1). RW的数据就不释放了, 程序销毁前一旦加载就常驻内存了。。。

2). 利用linux的swap交换分区技术。 swap交换分区 也叫虚拟内存.... 跟虚拟内存地址不一样,  这是利用磁盘扩充内存容量。。。将后台,  不活跃的程序交换到swap分区。(Linux中mount下看看, 一般都会分一个...)


2. 中断处理....

   bootrom, uboot不怎么用中断... 但是linux操作系统肯定是必须要用中断的啦....

3. swi, software interrupt, 软件中断, 

   linux使用swi作为系统调用的入口, 用户态进程调用open, read, write, ioctl, close等系统调用时, 需要陷入内核态。

用户态运行在 user模式, 内核态运行在svc模式。

  查看glibc的系统调用实现, glibc-2.30/sysdeps/unix/sysv/linux/arm/sysdep.h

338 #if defined(__thumb__)                                                                                                                                              
339 /* We can not expose the use of r7 to the compiler.  GCC (as                                                                                                        
340    of 4.5) uses r7 as the hard frame pointer for Thumb - although                                                                                                   
341    for Thumb-2 it isn't obviously a better choice than r11.                                                                                                         
342    And GCC does not support asms that conflict with the frame                                                                                                       
343    pointer.                                                                                                                                                         
344                                                                                                                                                                     
345    This would be easier if syscall numbers never exceeded 255,                                                                                                      
346    but they do.  For the moment the LOAD_ARGS_7 is sacrificed.                                                                                                      
347    We can't use push/pop inside the asm because that breaks                                                                                                         
348    unwinding (i.e. thread cancellation) for this frame.  We can't                                                                                                   
349    locally save and restore r7, because we do not know if this                                                                                                      
350    function uses r7 or if it is our caller's r7; if it is our caller's,                                                                                             
351    then unwinding will fail higher up the stack.  So we move the                                                                                                    
352    syscall out of line and provide its own unwind information.  */                                                                                                  
353 # undef INTERNAL_SYSCALL_RAW                                                                                                                                        
354 # define INTERNAL_SYSCALL_RAW(name, err, nr, args...)›  ›   \                                                                                                       
355   ({›   ›   ›   ›   ›   ›   ›   ›   \                                                                                                                               
356       register int _a1 asm ("a1");› ›   ›   ›   \                                                                                                                   
357       int _nametmp = name;› ›   ›   ›   ›   \                                                                                                                       
358       LOAD_ARGS_##nr (args)››   ›   ›   ›   \                                                                                                                       
359       register int _name asm ("ip") = _nametmp;››   ›   \                                                                                                           
360       asm volatile ("bl      __libc_do_syscall"››   ›   \                                                                                                           
361                     : "=r" (_a1)›   ›   ›   ›   \                                                                                                                   
362                     : "r" (_name) ASM_ARGS_##nr››   ›   \                                                                                                           
363                     : "memory", "lr");› ›   ›   ›   \                                                                                                               
364       _a1; })                                                                                                                                                       
365 #else /* ARM */                                                                                                                                                     
366 # undef INTERNAL_SYSCALL_RAW                                                                                                                                        
367 # define INTERNAL_SYSCALL_RAW(name, err, nr, args...)›  ›   \                                                                                                       
368   ({›   ›   ›   ›   ›   ›   ›   ›   \                                                                                                                               
369        register int _a1 asm ("r0"), _nr asm ("r7");››   \                                                                                                           
370        LOAD_ARGS_##nr (args)›   ›   ›   ›   ›   \                                                                                                                   
371        _nr = name;› ›   ›   ›   ›   ›   \                                                                                                                           
372        asm volatile ("swi›  0x0›@ syscall " #name›  \                                                                                                               
373 ›   ›        : "=r" (_a1)›  ›   ›   ›   \                                                                                                                           
374 ›   ›        : "r" (_nr) ASM_ARGS_##nr› ›   ›   \                                                                                                                   
375 ›   ›        : "memory");›  ›   ›   ›   \                                                                                                                           
376        _a1; })                                                                                                                                                      
377 #endif 

可以看到, arm的系统调用使用swi 0x0 陷入内核, 后面跟的寄存器保存相关参数。 (read, write, ioctl都有各自不同参数)

查看kernel/arch/arm/kernel/entry-common.S

210 ›   /* saved_psr and saved_pc are now dead */                                                                                                                       
211                                                                                                                                                                     
212 ›   uaccess_disable tbl                                                                                                                                             
213                                                                                                                                                                     
214 ›   adr›tbl, sys_call_table››   @ load syscall table pointer                                                                                                        
215                                                                                                                                                                     
216 #if defined(CONFIG_OABI_COMPAT)                                                                                                                                     
217 ›   /*                                                                                                                                                              
218 ›    * If the swi argument is zero, this is an EABI call and we do nothing.                                                                                         
219 ›    *                                                                                                                                                              
220 ›    * If this is an old ABI call, get the syscall number into scno and                                                                                             
221 ›    * get the old ABI syscall table address.                                                                                                                       
222 ›    */                                                                                                                                                             
223 ›   bics›   r10, r10, #0xff000000                                                                                                                                   
224 ›   eorne›  scno, r10, #__NR_OABI_SYSCALL_BASE                                                                                                                      
225 ›   ldrne›  tbl, =sys_oabi_call_table                                                                                                                               
226 #elif !defined(CONFIG_AEABI)                                                                                                                                        
227 ›   bic›scno, scno, #0xff000000››   @ mask off SWI op-code                                                                                                          
228 ›   eor›scno, scno, #__NR_SYSCALL_BASE› @ check OS number                                                                                                           
229 #endif                                                                                                                                                              
230 ›   get_thread_info tsk                                                                                                                                             
231 ›   /*                                                                                                                                                              
232 ›    * Reload the registers that may have been corrupted on entry to                                                                                                
233 ›    * the syscall assembly (by tracing or context tracking.)                                                                                                       
234 ›    */                                                                                                                                                             
235  TRACE(›ldmia›  sp, {r0 - r3}›  ›   )                                                                                                                               
236                                                                                                                                                                     
237 local_restart:                                                                                                                                                      
238 ›   ldr›r10, [tsk, #TI_FLAGS]›  ›   @ check for syscall tracing                                                                                                     
239 ›   stmdb›  sp!, {r4, r5}›  ›   ›   @ push fifth and sixth args                                                                                                     
240                                                                                                                                                                     
241 ›   tst›r10, #_TIF_SYSCALL_WORK››   @ are we tracing syscalls?                                                                                                      
242 ›   bne›__sys_trace                                                                                                                                                 
243                                                                                                                                                                     
244 ›   cmp›scno, #NR_syscalls› ›   @ check upper syscall limit                                                                                                         
245 ›   badr›   lr, ret_fast_syscall›   ›   @ return address                                                                                                            
246 ›   ldrcc›  pc, [tbl, scno, lsl #2]››   @ call sys_* routine     

有些只了解个大概, 后续再深究...

 

 

 

 

你可能感兴趣的:(Linux,ARM)