ELF mmap 映射过程

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    国内:https://weharmony.gitee.io
    国外:https://weharmony.github.io
上级 53892606
......@@ -130,7 +130,7 @@ LITE_OS_SEC_TEXT_INIT VOID HalClockInit(VOID)
{
UINT32 ret;
g_sysClock = HalClockFreqRead();
g_sysClock = HalClockFreqRead();//读取时钟源频率
ret = LOS_HwiCreate(OS_TICK_INT_NUM, MIN_INTERRUPT_PRIORITY, 0, OsTickHandler, 0);
if (ret != LOS_OK) {
PRINT_ERR("%s, %d create tick irq failed, ret:0x%x\n", __FUNCTION__, __LINE__, ret);
......@@ -148,7 +148,7 @@ LITE_OS_SEC_TEXT_INIT VOID HalClockStart(VOID)
/* triggle the first tick */
TimerCtlWrite(0);
TimerTvalWrite(OS_CYCLE_PER_TICK);
TimerTvalWrite(OS_CYCLE_PER_TICK);//递减计时器,使能tick中断,产生周期性tick
TimerCtlWrite(1);
}
......
......@@ -1379,18 +1379,18 @@ LITE_OS_SEC_TEXT UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINT
if ((sp == 0) || (LOS_Align(sp, LOSCFG_STACK_POINT_ALIGN_SIZE) != sp)) {//对齐
return LOS_NOK;
}
//注意 sp此时指向栈底,栈底地址要大于栈顶
if ((mapBase == 0) || (mapSize == 0) || (sp <= mapBase) || (sp > (mapBase + mapSize))) {//参数检查
return LOS_NOK;
}
LosTaskCB *taskCB = OsCurrTaskGet();
LosTaskCB *taskCB = OsCurrTaskGet();//获取当前任务
SCHEDULER_LOCK(intSave);//拿自旋锁
taskCB->userMapBase = mapBase;//用户态栈顶
taskCB->userMapSize = mapSize;//用户态栈大小
taskCB->userMapBase = mapBase;//用户态栈顶位置
taskCB->userMapSize = mapSize;//用户态栈
taskCB->taskEntry = (TSK_ENTRY_FUNC)entry;//任务的入口函数
//初始化内核态栈
TaskContext *taskContext = (TaskContext *)OsTaskStackInit(taskCB->taskID, taskCB->stackSize,
(VOID *)taskCB->topOfStack, FALSE);
OsUserTaskStackInit(taskContext, (UINTPTR)taskCB->taskEntry, sp);//初始化用户栈,将内核栈中上下文的 context->R[0] = sp ,context->sp = sp
......
......@@ -100,6 +100,8 @@ extern "C" {
#define EXC_INTERACT_MEM_SIZE 0x100000
内核空间范围: 0x40000000 ~ 0xFFFFFFFF
用户空间氛围: 0x00000000 ~ 0x3FFFFFFF
cached地址和uncached地址的区别是
对cached地址的访问是委托给CPU进行的,也就是说你的操作到底是提交给真正的外设或内存,还是转到CPU缓存,
......@@ -129,27 +131,27 @@ cached地址和uncached地址的区别是
#define _U32_C(X) X##U
#define U32_C(X) _U32_C(X)
#define KERNEL_VMM_BASE U32_C(KERNEL_VADDR_BASE)
#define KERNEL_VMM_BASE U32_C(KERNEL_VADDR_BASE) //速度快,使用cache
#define KERNEL_VMM_SIZE U32_C(KERNEL_VADDR_SIZE)
#define KERNEL_ASPACE_BASE KERNEL_VMM_BASE //内核空间开始地址
#define KERNEL_ASPACE_SIZE KERNEL_VMM_SIZE //内核空间大小
/* Uncached vmm aspace */
#define UNCACHED_VMM_BASE (KERNEL_VMM_BASE + KERNEL_VMM_SIZE)//未缓存虚拟空间基地址
#define UNCACHED_VMM_BASE (KERNEL_VMM_BASE + KERNEL_VMM_SIZE)//未缓存虚拟空间基地址,适用于DMA,LCD framebuf,
#define UNCACHED_VMM_SIZE DDR_MEM_SIZE //未缓存虚拟空间大小
#define VMALLOC_START (UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)//动态分配基地址
#define VMALLOC_SIZE 0x08000000//128M
#ifdef LOSCFG_KERNEL_MMU
#define PERIPH_DEVICE_BASE (VMALLOC_START + VMALLOC_SIZE)
//UART,LCD,摄像头,I2C,中断控制器统称为外部设备
#ifdef LOSCFG_KERNEL_MMU //使用MMU时,只是虚拟地址不一样,但映射的物理设备空间一致.
#define PERIPH_DEVICE_BASE (VMALLOC_START + VMALLOC_SIZE) //不使用buffer,cache
#define PERIPH_DEVICE_SIZE U32_C(PERIPH_PMM_SIZE)
#define PERIPH_CACHED_BASE (PERIPH_DEVICE_BASE + PERIPH_DEVICE_SIZE)
#define PERIPH_CACHED_BASE (PERIPH_DEVICE_BASE + PERIPH_DEVICE_SIZE)//使用cache但不用buffer
#define PERIPH_CACHED_SIZE U32_C(PERIPH_PMM_SIZE)
#define PERIPH_UNCACHED_BASE (PERIPH_CACHED_BASE + PERIPH_CACHED_SIZE)
#define PERIPH_UNCACHED_BASE (PERIPH_CACHED_BASE + PERIPH_CACHED_SIZE)//不使用cache但使用buffer
#define PERIPH_UNCACHED_SIZE U32_C(PERIPH_PMM_SIZE)
#else
#else //不使用MMU时,外部设备空间地址一致.
#define PERIPH_DEVICE_BASE PERIPH_PMM_BASE
#define PERIPH_DEVICE_SIZE U32_C(PERIPH_PMM_SIZE)
#define PERIPH_CACHED_BASE PERIPH_PMM_BASE
......
......@@ -188,7 +188,7 @@ VADDR_T LOS_MMap(VADDR_T vaddr, size_t len, unsigned prot, unsigned long flags,
if (status != LOS_OK) {
LOS_RbDelNode(&vmSpace->regionRbTree, &newRegion->rbNode);//从红黑树和双循环链表中删除
LOS_RegionFree(vmSpace, newRegion);//释放
resultVaddr = (VADDR_T)-ENOMEM;//linux错误代码含义 ENOMEM:内存溢出
resultVaddr = (VADDR_T)-ENOMEM;
goto MMAP_DONE;
}
......
......@@ -36,13 +36,13 @@
#include "los_vm_phys.h"
#include "los_vm_map.h"
#include "los_vm_dump.h"
//运行ELF
STATIC INT32 OsExecve(const ELFLoadInfo *loadInfo)
{
if ((loadInfo == NULL) || (loadInfo->elfEntry == 0)) {
return LOS_NOK;
}
//任务运行的两个硬性要求:1.提供入口指令 2.运行栈空间.
return OsExecStart((TSK_ENTRY_FUNC)(loadInfo->elfEntry), (UINTPTR)loadInfo->stackTop,
loadInfo->stackBase, loadInfo->stackSize);
}
......
......@@ -511,7 +511,7 @@ STATIC INT32 OsMmapELFFile(INT32 fd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EH
}
if ((*loadBase == 0) && (elfEhdr->elfType == LD_ET_DYN)) {
*loadBase = mapAddr;
*loadBase = mapAddr;//改变装载基地址
}
//.bss 的区分标识为 实际使用内存大小要大于文件大小,而且必是可写
if ((elfPhdrTemp->memSize > elfPhdrTemp->fileSize) && (elfPhdrTemp->flags & PF_W)) {
......@@ -902,7 +902,7 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo)
return -EINVAL;
}
}
//先映射 ELF文件本身
//先映射 ELF文件
ret = OsMmapELFFile(loadInfo->execInfo.fd, loadInfo->execInfo.elfPhdr, &loadInfo->execInfo.elfEhdr,
&loadInfo->loadAddr, mapSize, &loadBase);
if (ret != LOS_OK) {
......
git add -A
git commit -m 'ELF加载过程代码注解
git commit -m 'ELF mmap 映射过程
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
国内:https://weharmony.gitee.io
国外:https://weharmony.github.io
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册