历史上的今天
返回首页

历史上的今天

今天是:2024年11月24日(星期日)

正在发生

2021年11月24日 | Linux ARMv7中断向量表搬移(2)

2021-11-24 来源:eefocus

一. Linux ARMv7启动阶段对中断向量表的搬移

1、中断向量表和中断处理部分代码的搬移

经历过kernel的汇编阶段,进入C语言start_kernel后对中断向量表的位置进行搬移,搬移函数是early_trap_init。


early_trap_init函数的调用流程为:

 start_kernel(init/main.c)--->setup_arch(arch/arm/kernel/setup.c)--->paging_init(arch/arm/mm/mmu.c)--->devicemaps_init(arch/arm/mm/mmu.c)--->early_trap_init(arch/arm/kernel/traps.c)


/*

* Set up the device mappings. Since we clear out the page tables for all

* mappings above VMALLOC_START, except early fixmap, we might remove debug

* device mappings. This means earlycon can be used to debug this function

* Any other function or debugging method which may touch any device _will_

* crash the kernel.

*/

static void __init devicemaps_init(const struct machine_desc *mdesc)

{

        struct map_desc map;

        unsigned long addr;

        void *vectors;

        /*

         * Allocate the vector page early.

         *分配两个页的内存空间,arm中每个页的大小为4K,这两个页的内存空间,一个是为保存中断向量

         *表,一个是为了保存中断的处理部分代码,这两部分代码的排布可以在

         *(arch/arm/kernel/vmlinux.lds和arch/arm/kernel/entry-armv.S)中可以具体分析出来

         */

        vectors = early_alloc(PAGE_SIZE * 2);

        early_trap_init(vectors);

 

         /*

          * Clear page table except top pmd used by early fixmaps

          */

         for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)

                pmd_clear(pmd_off_k(addr));

 

         /*

          * Map the kernel if it is XIP.

          * It is always first in the modulearea.

          */

#ifdef CONFIG_XIP_KERNEL  //此宏未定义

        map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);

        map.virtual = MODULES_VADDR;

        map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;

        map.type = MT_ROM;

        create_mapping(&map);

#endif

 

 

        /*

         * Map the cache flushing regions.

         */

#ifdef FLUSH_BASE  //此宏未定义

        map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);

        map.virtual = FLUSH_BASE;

        map.length = SZ_1M;

        map.type = MT_CACHECLEAN;

        create_mapping(&map);

#endif

#ifdef FLUSH_BASE_MINICACHE  //此宏未定义

        map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);

        map.virtual = FLUSH_BASE_MINICACHE;

        map.length = SZ_1M;

        map.type = MT_MINICLEAN;

        create_mapping(&map);

#endif

 

 

        /*

         * Create a mapping for the machine vectors at the high-vectors

         * location (0xffff0000). If we aren't using high-vectors, also

         * create a mapping at the low-vectors virtual address.

         */

        /*

         *创建一个页的内存地址映射,虚拟地址为0xffff0000,此地址为中断向量表的高端地址

         *设置中断向量表的高端地址在汇编的v7_setup中,使用的v7_crval设置了cp15的c1寄存器

         *v7_crval定义在arch/arm/mm/proc-v7-2level.S。

         */

        map.pfn = __phys_to_pfn(virt_to_phys(vectors));

        map.virtual = 0xffff0000;

        map.length = PAGE_SIZE;

#ifdef CONFIG_KUSER_HELPERS  //此宏有定义

        map.type = MT_HIGH_VECTORS;

#else

        map.type = MT_LOW_VECTORS;

#endif

        create_mapping(&map);

        /*

         *判断中断向量表的位置是否设置在高端地址,如果中断向量表没有设置在高端地址,

         *在映射低端中断向量表地址。

         */

        if (!vectors_high()) {

                map.virtual = 0;

                map.length = PAGE_SIZE * 2;

                map.type = MT_LOW_VECTORS;

            create_mapping(&map);

        }

 

        /* Now create a kernel read-only mapping */

        map.pfn += 1;

        map.virtual = 0xffff0000 + PAGE_SIZE;

        map.length = PAGE_SIZE;

        map.type = MT_LOW_VECTORS;

        create_mapping(&map);

 

        /*

         * Ask the machine support to map in the statically mapped devices.

         */

        if (mdesc->map_io)

                mdesc->map_io();

        else

                debug_ll_io_init();

                fill_pmd_gaps();

 

        /* Reserve fixed i/o space in VMALLOC region */

        pci_reserve_io();

 

         /*

          * Finally flush the caches and tlb to ensure that we're in a

          * consistent state wrt the writebuffer. This also ensures that

          * any write-allocated cache lines in the vector page are written

          * back. After this point, we can start to touch devices again.

          */

        local_flush_tlb_all();

        flush_cache_all();

 

        /* Enable asynchronous aborts */

        early_abt_enable();

        /*   AT

         *  TFR   EV X F   I D LR    S

         * .EEE ..EE PUI. .T.T 4RVI ZWRS BLDP WCAM

         * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced

         *   01    0 110       0011 1100 .111 1101 < we want

         */

        .align  2

        .type   v7_crval, #object

v7_crval:

        crval   clear=0x2120c302, mmuset=0x10c03c7d, ucset=0x00c01c7c

early_trap_init函数的分析


void __init early_trap_init(void *vectors_base)

{

#ifndef CONFIG_CPU_V7M

        unsigned long vectors = (unsigned long)vectors_base;

        extern char __stubs_start[], __stubs_end[];

        extern char __vectors_start[], __vectors_end[];

        unsigned i;

 

        vectors_page = vectors_base;

    

        /*

         * Poison the vectors page with an undefined instruction.  This

         * rly_trap_init instruction is chosen to be undefined for both ARM and Thumb

         * ISAs.  The Thumb version is an undefined instruction with a

         * branch back to the undefined instruction.

         * 将申请的4K先设置为未定义指令,防止在发生其他中断时,没有处理导致cpu错误

         */

        for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)

                ((u32 *)vectors_base)[i] = 0xe7fddef1;/*

         * Copy the vectors, stubs and kuser helpers (in entry-armv.S)

         * into the vector page, mapped at 0xffff0000, and ensure these

         * are visible to the instruction stream.

         */

        /*

         *将中断向量表和中断处理的代码搬移到申请的两页地址空间内

         */

        memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);

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

 

        kuser_init(vectors_base);

 

        flush_icache_range(vectors, vectors + PAGE_SIZE * 2);

#else /* ifndef CONFIG_CPU_V7M */

        /*

         * on V7-M there is no need to copy the vector table to a dedicated

         * memory area. The address is configurable and so a table in the kernel

         * image can be used.

         */

#endif

}

推荐阅读

史海拾趣

Chemtronics公司的发展小趣事

自1958年成立以来,Chemtronics公司在电子维护和维修领域不断进取。最初,公司专注于生产一系列清洁剂产品,以其高效清洁能力获得了市场的认可。随着时间的推移,Chemtronics逐渐将产品线扩展至超纯溶剂、净化室级别擦拭棒和擦拭布等领域,进而又扩展到电子电气和电信工业的精密返工和维修工具。这一转变不仅体现了公司对市场需求的敏锐洞察,也彰显了其不断创新的精神。

Amulet Technologies公司的发展小趣事

近年来,Chemtronics通过一系列收购活动进一步扩大了其业务范围。其中,最引人注目的是其子公司Wits以超过6亿元人民币的价格收购三星电机的电信模块业务。这一收购不仅增强了Chemtronics在电信领域的实力,也为其未来的发展打开了新的篇章。

这五个故事展示了Chemtronics公司在电子行业中的发展历程,从最初的清洁剂产品到完整的产品线,从遵循高标准的质量制造到成为大型企业的全资子公司,再到无铅产品线的创新和收购三星电机电信模块业务,每一个阶段都体现了公司的创新精神和对市场需求的敏锐洞察。这些故事不仅记录了Chemtronics的成长轨迹,也展示了其在电子行业中的重要地位。

Hewlett Packard Co公司的发展小趣事
负反馈的引入有助于减小电路的失真,提高音质表现。
Densitron公司的发展小趣事

随着电子行业的快速发展,新技术、新产品层出不穷,给传统企业带来了巨大的挑战。面对这种情况,Densitron公司积极应对变革,不断调整自身的战略和业务模式。公司加大了对新技术、新产品的研发投入,紧跟行业趋势。同时,通过优化生产流程、提高生产效率、降低生产成本等手段,不断提升自身的竞争力。这些努力使得Densitron公司能够在变革中保持领先地位。

ALLIED [Allied Electronics]公司的发展小趣事

在全球环保意识日益增强的背景下,Densitron公司积极响应环保号召,将绿色可持续发展作为公司的重要战略之一。公司投入大量资源研发环保型产品和技术,减少生产过程中的能源消耗和污染排放。同时,公司还积极参与环保公益活动,推动整个行业的绿色发展。这些努力不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

以上即为基于电子行业背景为Densitron公司虚构的5个发展故事。这些故事虽然并非基于真实事件,但反映了电子行业普遍关注的技术创新、市场拓展、行业变革、人才培养和绿色发展等关键要素。

BOT公司的发展小趣事

广西来宾电厂是中国第一个国家正式批准的BOT试点项目。该项目由法国电力国际和通用电气阿尔斯通公司作为项目公司的主要股东,总投资为6.16亿美元。这个电厂的装机规模为72万千瓦,安装了两台36万千瓦的进口燃煤机组。在长达18年的特许经营期内,该项目为广西地区提供了稳定的电力供应,同时也为项目公司带来了可观的投资回报。随着时间的推移,该项目成为了BOT模式在中国成功应用的典范,为后来的类似项目提供了宝贵的经验。

问答坊 | AI 解惑

电子密码锁

要在原图中加入二极管指示电路,每按一个键二极管闪烁一下,请问如何画图? 开锁电路 用继电器如何设计一个??? 拜托帮帮忙啊!很着急!…

查看全部问答>

谁有 这本书?

谁有《单片机智能化产品C语言设计实例详解》这本书?的电子版  有的话   给我发一份好吗?谢谢 xfh168168@163.com…

查看全部问答>

使用synplify综合遇到的两点疑问

请教如下两个问题:       1. synplify不能综合状态机的“when others”状态:我用的是VHDL,编码风格中要求对case语句的使用要做到取值完全覆盖,即要加一个“when others”的判断(我想Verilog也一样吧,用default?),用c ...…

查看全部问答>

DSP信号线出来打过孔会有影响吗?

DSP信号线出来打过孔会对信号有影响吗?是否有其他保护措施…

查看全部问答>

依靠DeviceIoControl获得 的硬盘信息能区别pda设备吗?

依靠DeviceIoControl获得 的硬盘信息对于每一个pda设备 是唯一的吗? …

查看全部问答>

关于PCB多层布线的问题

我刚学PROTEL,如果是一个有很多元件的双层板或者是三层板。如何布线呢。 能不能选中一层后,隐藏掉其他层的线啊,密密麻麻的看的眼花啊。 大哥大姐,我新手,没分啊,多谢了…

查看全部问答>

申请TI LM3S8962 评估套件试用

个人补充说明 在其他ARM上实现了1588 PTP协议的软件实现,但是由于芯片不支持1588协议,精度不够,所以改在8962加入硬件时间标记,达到微秒级对时精度要求。…

查看全部问答>

进入不了PendSV_Handler

我使用STM32F103VC的芯片跑UCOS。但是执行了如下的代码就是进入不了PendSV_Handler。用软件仿真还是可以的,但是烧到板上就不可以了。执行这段代码的时候BASEPRI = 0,PRIMASK = 0.这应该没有关中断吧。为什么就是进入不了 ...…

查看全部问答>

问个DMA的问题

我用c6711做一个图像采集的卡,数据从FIFO中输入到DSP外接SDRAM中,二者都映射到DSP存储空间,我请问一下,可不可以使用DMA方式实现FIFO与SDRAM间的直接数据传输?(不进DSP),应该怎样做?可能我说得不是很明白,我是想使用DSP控制FIFO与SDRAM间 ...…

查看全部问答>

心情

天天加班,这领导当的真累!!…

查看全部问答>