0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux汇编启动relocate重定向分析

麦辣鸡腿堡 来源:嵌入式Linux充电站 作者:Vincent 2023-10-08 11:32 次阅读

relocate

relocate重定向,就是在开启mmu。开启mmu的操作就是将一级页表的地址以及权限写到satp寄存器中,这就算开启mmu了。

#ifdef CONFIG_MMU
    la a0, early_pg_dir //跳转到relocate前,先把第一级页表early_pg_dir的地址存入a0
    call relocate		//跳转到relocate,开启MMU
#endif

relocate有两次开启mmu的操作,第一次开启mmu使用的是setup_vm()建立的trampoline_gd_dir页表,这页表保存的是kernel的前2M内存。第二次开启MMU使用的是early_pg_dir页表,这个页表映射了整个kernel内存以及dtb的4M空间。

如果trampoline_pg_dir或者early_pg_dir这两个页表的映射没弄好的话,开启MMU的时候就会失败,所以页表的建立十分关键。页表创建后续再深究,下面分析relocate汇编代码。

  • 计算返回地址
    返回地址就是ra加上虚拟地址和物理地址之间的偏移量,这个是固定偏移量。PAGE_OFFSETkernel入口地址对应的虚拟地址,_start就是kernel入口地址的虚拟地址,PAGE_OFFSET - _start就得到它们之间的偏移,然后再和ra相加,就是返回地址。
/* Relocate return address */
	li a1, PAGE_OFFSET
	la a2, _start
	sub a1, a1, a2
	add ra, ra, a1
  • 将异常入口1f的虚拟地址写入stvec寄存器
    因为一旦开启MMU,地址都变成了虚拟地址,原来访问的都是物理地址,开启MMU时,地址发生了改变,VA != PA,从而进入异常,所以要先设置异常入口地址,此时的异常入口为1f
/* Point stvec to virtual address of intruction after satp write */
	la a2, 1f
	add a2, a2, a1
	csrw CSR_TVEC, a2
  • 提前计算切换到early_pg_dir页表要写入satp的值

再进入relocate之前,就已经把early_pg_dir赋值给a0了,所以a0是early_pg_dir。srl是逻辑右移,mmu使用的是sv39,虚拟地址39位,物理地址56位:

图片低12位是偏移量,所以PAGE_SHIFT等于12,将early_pg_dir地址右移12位存到a2。根据satp寄存器定义:

图片

MODE等于0x8代表使用sv39 mmu0x0代表不进行地址翻译,即不开启MMU。这里STAP_MODEsv39,即0x8。将early_pg_dir地址和SATP_MODE进行或运算后,即可得到写入satp寄存器的值,最后保存到a2

/* Compute satp for kernel page tables, but don't load it yet */
	srl a2, a0, PAGE_SHIFT
	li a1, SATP_MODE	//sv39 mmu
	or a2, a2, a1
  • 第一次开启MMU,使用trampoline_pg_dir页表

satp值的计算和上述是一样的。开启MMU之前,通过sfence.vma命令先刷新TLB。此时开启MMU,就会进入下面的标号为1的汇编段

la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma	
	csrw CSR_SATP, a0

进入异常1f段,重新设置异常入口为.Lsecondary_park,然后切换到early_pg_dir页表,相当于第二次开启MMU。此时,如果之前建立的early_pg_dir页表不对,则会就进入.Lsecondary_park.Lsecondary_park里面是个wfi指令,是个死循环。

完整relocate汇编代码:

relocate:
	/* Relocate return address */
	li a1, PAGE_OFFSET
	la a2, _start
	sub a1, a1, a2
	add ra, ra, a1

	/* Point stvec to virtual address of intruction after satp write */
	la a2, 1f
	add a2, a2, a1
	csrw CSR_TVEC, a2

	/* Compute satp for kernel page tables, but don't load it yet */
	srl a2, a0, PAGE_SHIFT
	li a1, SATP_MODE
	or a2, a2, a1

	/*
	 * Load trampoline page directory, which will cause us to trap to
	 * stvec if VA != PA, or simply fall through if VA == PA.  We need a
	 * full fence here because setup_vm() just wrote these PTEs and we need
	 * to ensure the new translations are in use.
	 */
	la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma
	csrw CSR_SATP, a0
.align 2
1:
	/* Set trap vector to spin forever to help debug */
	la a0, .Lsecondary_park
	csrw CSR_TVEC, a0

	/* Reload the global pointer */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * Switch to kernel page tables.  A full fence is necessary in order to
	 * avoid using the trampoline translations, which are only correct for
	 * the first superpage.  Fetching the fence is guarnteed to work
	 * because that first superpage is translated the same way.
	 */
	csrw CSR_SATP, a2
	sfence.vma

	ret
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10990

    浏览量

    206738
  • 汇编
    +关注

    关注

    2

    文章

    214

    浏览量

    25735
  • MMU
    MMU
    +关注

    关注

    0

    文章

    91

    浏览量

    17944
  • 地址表
    +关注

    关注

    0

    文章

    3

    浏览量

    799
收藏 人收藏

    评论

    相关推荐

    Linux后台程序重定向的问题

    目前有一种方法是在程序后台启动的时候,直接重定向到某个shell或telnet。方法如下:如tty命令查看目标shell为 /dev/pts/0./yourapp & > /dev
    发表于 08-22 13:54

    linux shell数据重定向(输入重定向与输出重定向)详细分析

    在了解重定向之前,我们先来看看linux 的文件描述符。linux文件描述符:可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可
    发表于 03-02 13:59

    Linux Shell系列教程之(十六) Shell输入输出重定向

      一、Shell输入输出重定向概述  在了解重定向相关知识之前,我们先来看看Linux的文件描述符。  Linux的文件描述符可以理解为linux
    发表于 09-12 15:53

    如何对Linux Bash输入输出重定向

    Linux - Bash - 输入输出重定向
    发表于 04-27 09:01

    Linux输入与输出的重定向介绍

    Linux输入与输出的重定向
    发表于 06-12 14:54

    实现printf函数的重定向

    目录重定向函数属性设置重定向函数在配置好串口之后需要在相关文件中添加以下函数以实现printf函数的重定向//注意添加头文件#include "stdio.h"#ifdef
    发表于 08-24 07:09

    MDK的重定向与printf的重定向有什么不一样?

    MDK的重定向与printf的重定向有什么不一样?
    发表于 12-01 06:05

    串口重定向是什么意思?

    串口重定向是什么意思?
    发表于 12-08 06:57

    将输出到串口的日志信息重定向到当前的telnet

    概述在嵌入式Linux系统中,有时通过远程(telnet或者ssh)登录到现场设备,想看程序的实时打印的调试信息,需要将输出到串口的调试信息重定向到当前登录的终端界面上。也可以将程序重新启动到当前
    发表于 12-16 07:13

    实现重定向printf()和scanf() 函数案例分析

    要想printf()和scanf() 函数工作,我们需要把printf()和scanf() 重新定向到串口中。重定向是指用户可以自己重写C 的库函数,当连接器检查到用户编写了与C 库函数相同
    发表于 06-23 08:26 8606次阅读
    实现<b class='flag-5'>重定向</b>printf()和scanf() 函数案例<b class='flag-5'>分析</b>

    ICMP重定向抓包分析 什么情况下路由器要向源发送ICMP重定向

    转发。 ICMP重定向抓包分析 ICMP-Wiresharek抓包-PC端抓包 1.主机A发送ARPbroadcast报文,判断目标地址非本端网络,广播寻找网关; 2.主机A收到ARP报文关于网关
    的头像 发表于 08-24 15:43 5140次阅读
    ICMP<b class='flag-5'>重定向</b>抓包<b class='flag-5'>分析</b> 什么情况下路由器要向源发送ICMP<b class='flag-5'>重定向</b>

    嵌入式Linux中printf重定向到串口

    PC机上,printf输出到显示设备,在嵌入式linux系统,一般利用printf输出调试信息,需要重定向到串口。以AT91RM9200为例,简要说明如何利用串口输出printf的打印
    发表于 11-01 17:22 24次下载
    嵌入式<b class='flag-5'>Linux</b>中printf<b class='flag-5'>重定向</b>到串口

    Keil下使用STlink重定向printf的配置

    Keil下使用STlink重定向printf的配置1. printf 重定向Keil默认下使用Micro LIB库,该库调用 fputs 实现 printf,所以需要重新定义fputs函数,以重定向
    发表于 12-27 18:43 18次下载
    Keil下使用STlink<b class='flag-5'>重定向</b>printf的配置

    Linux I/O重定向详解

    Linux I/O重定向可以定义为,更改从命令读取输入到命令发送输出的方式。你可以重定向命令的输入和输出。对于重定向符号,可以是 或者 | 。
    的头像 发表于 05-04 14:34 589次阅读

    2分钟搞懂输出重定向

    视频最后我们通过重定向把标准输出写到了文件中,但是错误输出还是留在了屏幕上。
    的头像 发表于 01-15 16:41 298次阅读