启动第一个应用进程

start_kernel ...... arch_call_rest_init() rest_init(); pid = kernel_thread(kernel_init, NULL, CLONE_FS); static int __ref kernel_init(void *unused) { int ret; kernel_init_freeable(); /* need to finish

挂载根文件系统

根文件系统是控制权从linux内核转移到用户空间的一个桥梁,文件系统的挂载需要提供挂载点,linux内核在初始化时汇初始化一个虚拟的“/”目录用于根文件系统的挂载。 start_kernel vfs_caches_init() mnt_init() init_rootfs() init_mount_tree() vfs_kern_mount(&rootfs_fs_type, 0, \"roo

异常初始化

异常处理概述 略 异常入口 start_kernel trap_init(); void __init trap_init(void) { /* * Set sup0 scratch register to 0, indicating to exception vector * that we are presently executing in the kernel */ csr_write(C

虚拟地址空间与物理地址空间完整映射

setup bootmem 物理内存都添加到系统之后,会调用setup_bootmem对整个物理内存进行整理,主要的工作就是remove掉一些no-map区域(不归内核管理),同时保留一些关键区域,如内核镜像区,dtb中reserved的内存节点。 上图中,浅绿色的就是reserved部分,不能被分配使用,而剩下的部分就可以通过调用上小章节中的函数去使用内存了。 void __init setup

使能MMU

① 多核情况使能MMU .Lsecondary_start: #ifdef CONFIG_SMP /* Set trap vector to spin forever to help debug */ la a3, .Lsecondary_park csrw CSR_STVEC, a3 slli a3, a0, LGREG la a1, __cpu_up_stack_pointer la a2,

临时虚拟地址空间映射

概述 为什么要做临时虚拟地址空间映射? 一旦开启MMU,PC的下一条指令地址会经过MMU转化,未开启MMU之前地址的翻译是不需要经过MMU转化直接访问。对应开启MMU之后,应该要使用虚拟地址,才能访问到正确的指令内存。 前面描述了虚拟地址转换为物理地址是通过MMU自动转换,但是需要给MMU创建好页表,这样MMU才能自动查询到物理地址。页表也是对应的物理内存,也是需要分配的,在正常系统运行时,页表的

虚拟地址与物理地址概念

地址空间 虚拟地址:程序使用的内存地址;物理地址:硬件的地址空间。虚拟地址通过MMU转化为物理地址,虚拟地址的长度与实际的物理内存容量没有关系,从系统中每个进程的角度看,地址空间的进程无法感知其他进程的存在。 32位cpu处理的地址空间为2^32=4G,所以虚拟地址空间为4G,分为用户空间和内核空间。用户空间的范围0~TASK_SIZE(可配置)通常为0x00000000~0xBFFFFFFF,内

arch初始化

_start_kernel: /* Mask all interrupts */ csrw CSR_SIE, zero csrw CSR_SIP, zero ① 将sie,sip寄存器设置为0,关闭所有中断和清除中断的pending(不是异常)。 /* Load the global pointer */ .option push .option norelax la gp, __global_p

Linux系统RISC-V架构启动流程分析之概述

典型的linux系统启动流程如上,但本文主要探讨的是OS的启动流程,opensbi,uboot暂不涉及。主要围绕arch/riscv/kernel/head.S进行分析。 _start j _start_kernel _start_kernel arch init //关中断,关浮点检测,挑选一个主hart启动初始化序列 clear bss//清除BSS setup_vm//为打开MMU做准备,f

Linux risc-v head.S调试记录

调试准备 gdb调试 0x0000000080200000为opensbi跳转执行的物理地址,linux内核的img会加载到这个地址运行,如果要在这个地方断点,就b *(0x0000000080200000),没法对head.S中进行断点,因为linux加载后会变成虚拟地址。调试的符号需要把CONFIG_DEBUG_INFO=y打开。 li s4,-13 j _start_kernel //j 0

RISC-V backtrace实现原理

start_kernel addi sp,sp,-16 ---① 分配栈帧sp=sp-16,sp指向栈顶 sw ra,12(sp) ---② 将ra存储到sp+12的位置 sw s0,8(sp) xxxxxx jal ra, 6000dba2 <backtrace> xxxxxx lw s0,8(sp) lw ra,12(sp) addi sp,sp,16 _backtrace for

RISC-V动态链接实验

准备 实验环境 qemu linux启动环境: https://www.laumy.tech/1186.html 代码 动态库 cat swap.c #include <stdio.h> int shared = 1; int z; void swap(int *a, int *b) { printf(\" *a ^= *b ^= *a ^= *b; } 主程序 #include <

opensbi分析(一)

引导Hart启动 _start: /* Find preferred boot HART id */ MOV_3R s0, a0, s1, a1, s2, a2 # 将a0,a1,a2的参数分别赋值为s0,s1,s2,这3个参数是前一阶段传入的参数。 # a0: hart id # a1: device tree # a2: struct fw_dynamic_info地址 call fw_boo

qemu+opensbi+uboot+linux+busybox启动环境搭建

前置条件 qemu+工具链安装 安装好交叉编译工具链和qemu环境,参考:https://www.laumy.tech/1127.html#risc-v64_Xuantie 代码下载 opensbi:(https://gitee.com/tinylab/qemu-opensbi \\\"version: v1.2\\\") uboot:

RISC-V架构与FreeRTOS任务栈变化

栈的基本概念 在FreeRTOS中,每个任务有一个全局的tskTCB实例,pxCurrentTCB指针指向的是正在运行的任务实例,有三个和栈相关的变量pxTopOfStack和pxStack,pxEndOfStack。 pxTopOfStack指向当前堆栈栈顶,随着进栈出栈,pxTopOfStack指向的位置是会变化的; pxStack指向当前堆栈的起始位置,一经分配后,堆栈起始位置就固定了,不会

平头哥E90X中断处理汇编部分

任务上下文保存 addi sp, sp, -portCONTEXT_SIZE store_x x1, 1 * portWORD_SIZE( sp ) store_x x5, 2 * portWORD_SIZE( sp ) store_x x6, 3 * portWORD_SIZE( sp ) store_x x7, 4 * portWORD_SIZE( sp ) store_x x8, 5 * p

平头哥E90X异常处理

上下文入栈保存 addi sp, sp, -portCONTEXT_SIZE ----开辟一段栈空间,这里的sp可能是主栈或任务栈 store_x x1, 1 * portWORD_SIZE( sp ) ----依次存储相关寄存器 store_x x5, 2 * portWORD_SIZE( sp ) store_x x6, 3 * portWORD_SIZE( sp ) store_x x7,

平头哥E90X的head.S分析

关闭中断 /* disable interrupt */ li t0, MR_MIE --- t0=0x08 csrc mstatus, t0 --- mstatus = mstatus | ~t0 csrw mie, zero --- mie = zero mstatus第4bit清0,mie清0。 设置异常处理入口 /* setup the address of exception handl

平头哥RISC-V+gdb+vscode调试

工具准备 T-HeadDebugServer工具:(https://www.xrvm.cn/community/download?id=4238019891233361920 \\\"链接\\\") T-HeadDebugServer使用说明:(https://www.xrvm.cn/community/download?id=4170589434888130560 \\\"链接\\\") vsc