页表部分注解 , 博客见于 鸿蒙内核源码分析(页表管理)

    百图画鸿蒙 + 百文说内核 + 百万注源码  => 挖透鸿蒙内核源码
    鸿蒙研究站 | http://weharmonyos.com (国内)
              | https://weharmony.github.io (国外)
    oschina | https://my.oschina.net/weharmony
    博客园 | https://www.cnblogs.com/weharmony/
    知乎 | https://www.zhihu.com/people/weharmonyos
    csdn | https://blog.csdn.net/kuangyufei
    51cto | https://harmonyos.51cto.com/column/34
    掘金 | https://juejin.cn/user/756888642000808
    公众号 | 鸿蒙研究站 (weharmonyos)
上级 9281a817
......@@ -169,7 +169,7 @@ extern "C" {
#define MMU_DESCRIPTOR_L2_AP_P_RO_U_NA (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_1)
#define MMU_DESCRIPTOR_L2_AP_MASK (MMU_DESCRIPTOR_L2_AP2_1 | MMU_DESCRIPTOR_L2_AP01_3)
#define MMU_DESCRIPTOR_L2_SHAREABLE (1 << 10)
#define MMU_DESCRIPTOR_L2_SHAREABLE (1 << 10)
#define MMU_DESCRIPTOR_L2_NON_GLOBAL (1 << 11)
#define MMU_DESCRIPTOR_L2_SMALL_PAGE_ADDR(x) ((x) & MMU_DESCRIPTOR_L2_SMALL_FRAME)
......
......@@ -125,7 +125,7 @@ STATIC INT32 AddEmmcParts(INT32 rootAddr, INT32 rootSize, INT32 userAddr, INT32
}
#endif
//增加一个分
//增加一个分
STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 userAddr, UINT64 userSize)
{
#ifdef LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7
......@@ -166,14 +166,14 @@ STATIC INT32 AddPartitions(CHAR *dev, UINT64 rootAddr, UINT64 rootSize, UINT64 u
return LOS_NOK;
}
//获取根文件系统参
//获取根文件系统参
STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *rootSize, UINT32 *mountFlags)
{
INT32 ret;
CHAR *rootAddrStr = NULL;
CHAR *rootSizeStr = NULL;
CHAR *rwTag = NULL;
//获取文件系统放在哪种设备
//获取文件系统放在哪种设备
ret = LOS_GetArgValue("root", dev);//root = flash | mmc |
if (ret != LOS_OK) {
PRINT_ERR("Cannot find root!");
......@@ -185,7 +185,7 @@ STATIC INT32 ParseRootArgs(CHAR **dev, CHAR **fstype, UINT64 *rootAddr, UINT64 *
PRINT_ERR("Cannot find fstype!");
return ret;
}
//获取内核地址空间开始位
//获取内核地址空间开始位
ret = LOS_GetArgValue("rootaddr", &rootAddrStr);
if (ret != LOS_OK) {
*rootAddr = ROOTFS_ADDR;
......@@ -345,7 +345,7 @@ INT32 OsMountRootfs()
UINT64 userAddr;
UINT64 userSize;
UINT32 mountFlags;
//获取根文件系统参?
//获取根文件系统参?
ret = ParseRootArgs(&dev, &fstype, &rootAddr, &rootSize, &mountFlags);
if (ret != LOS_OK) {
return ret;
......@@ -355,7 +355,7 @@ INT32 OsMountRootfs()
if (ret != LOS_OK) {
return ret;
}
//检查内核和用户空间的有效?
//检查内核和用户空间的有效?
ret = CheckValidation(rootAddr, rootSize, userAddr, userSize);
if (ret != LOS_OK) {
return ret;
......
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*!
* @file los_swtmr.c
* @brief 软定时器主文件
......@@ -93,6 +62,37 @@
@endverbatim
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_swtmr_pri.h"
#include "los_init.h"
#include "los_process_pri.h"
......@@ -405,16 +405,15 @@ STATIC UINT32 SwtmrBaseInit(VOID)
return LOS_ERRNO_SWTMR_NO_MEMORY;
}
(VOID)memset_s(swtmr, size, 0, size);//清0
g_swtmrCBArray = swtmr;//软时钟
LOS_ListInit(&g_swtmrFreeList);//初始化空闲链表
(VOID)memset_s(swtmr, size, 0, size);//清0
g_swtmrCBArray = swtmr;//软时钟
LOS_ListInit(&g_swtmrFreeList);//初始化空闲链表
for (UINT16 index = 0; index < LOSCFG_BASE_CORE_SWTMR_LIMIT; index++, swtmr++) {
swtmr->usTimerID = index;//按顺序赋值
LOS_ListTailInsert(&g_swtmrFreeList, &swtmr->stSortList.sortLinkNode);//通过sortLinkNode将节点挂到空闲链表
}
//想要用静态内存池管理,就必须要使用LOS_MEMBOX_SIZE来计算申请的内存大小,因为需要点前缀内存承载头部信息.
size = LOS_MEMBOX_SIZE(sizeof(SwtmrHandlerItem), OS_SWTMR_HANDLE_QUEUE_SIZE);
//规划一片内存区域作为软时钟处理函数的静态内存池。
}
//想要用静态内存池管理,就必须要使用LOS_MEMBOX_SIZE来计算申请的内存大小,因为需要点前缀内存承载头部信息.
size = LOS_MEMBOX_SIZE(sizeof(SwtmrHandlerItem), OS_SWTMR_HANDLE_QUEUE_SIZE);//规划一片内存区域作为软时钟处理函数的静态内存池。
g_swtmrHandlerPool = (UINT8 *)LOS_MemAlloc(m_aucSysMem1, size); /* system resident resource */
if (g_swtmrHandlerPool == NULL) {
return LOS_ERRNO_SWTMR_NO_MEMORY;
......
......@@ -509,7 +509,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCreateParamCheck(const UINT32 *taskID,
TSK_INIT_PARAM_S *initParam, VOID **pool)
{
UINT32 poolSize = OS_SYS_MEM_SIZE;
*pool = (VOID *)m_aucSysMem1;//默认使用
*pool = (VOID *)m_aucSysMem1;//默认使用 系统动态内存池地址的起始地址
if (taskID == NULL) {
return LOS_ERRNO_TSK_ID_INVALID;
......@@ -657,7 +657,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreateOnly(UINT32 *taskID, TSK_INIT_PARAM_S
LosTaskCB *taskCB = NULL;
VOID *pool = NULL;
errRet = OsTaskCreateParamCheck(taskID, initParam, &pool);//参数检查
errRet = OsTaskCreateParamCheck(taskID, initParam, &pool);//参数检查,获取内存池 *pool = (VOID *)m_aucSysMem1;
if (errRet != LOS_OK) {
return errRet;
}
......@@ -719,8 +719,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in
return LOS_ERRNO_TSK_YIELD_IN_INT;
}
if (OsProcessIsUserMode(OsCurrProcessGet())) {
initParam->processID = OsGetKernelInitProcessID();
if (OsProcessIsUserMode(OsCurrProcessGet())) { //当前进程为用户进程
initParam->processID = OsGetKernelInitProcessID();//@note_thinking 为什么进程ID变成了内核态根进程
} else {
initParam->processID = OsCurrProcessGet()->processID;
}
......
......@@ -42,7 +42,7 @@ extern "C" {
#endif /* __cplusplus */
typedef struct {
UINT32 memUsed;
UINT32 memUsed; ///< 记录任务内存使用量
} TskMemUsedInfo;
extern VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID);
......@@ -53,7 +53,7 @@ extern VOID OsTaskMemClear(UINT32 taskID);
#ifdef LOS_MEM_SLAB
typedef struct {
UINT32 slabUsed;
UINT32 slabUsed; ///< 任务占用以slab分配方式内存量
} TskSlabUsedInfo;
extern VOID OsTaskSlabUsedInc(UINT32 usedSize, UINT32 taskID);
......
......@@ -16,8 +16,8 @@
| 包括 IO设备 |
| PERIPH_PMM_SIZE |
+----------------------------+ 外围设备基地址 PERIPH_DEVICE_BASE
| Vmalloc |
| kernel heap |内核堆空间
| Vmalloc 空间 |
| 内核栈 内核堆 |内核动态分配空间
| 128M |
| 映射区 |
+----------------------------+ 内核动态分配开始地址 VMALLOC_START
......
......@@ -32,9 +32,9 @@
#include "los_memstat_pri.h"
#include "los_task_pri.h"
/// 记录每个任务对内存的使用情况
LITE_OS_SEC_BSS_MINOR STATIC TskMemUsedInfo g_tskMemUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT];
/// 计算指定任务对内存使用增加量
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
......@@ -43,9 +43,9 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedInc(UINT32 usedSize, UINT32 taskID)
if (OS_INT_ACTIVE) {
return;
}
g_tskMemUsedInfo[taskID].memUsed += usedSize;
g_tskMemUsedInfo[taskID].memUsed += usedSize; ///< 叠加
}
/// 计算指定任务对内存使用减少量
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
......@@ -59,9 +59,9 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemUsedDec(UINT32 usedSize, UINT32 taskID)
OsCurrTaskGet()->taskName, g_tskMemUsedInfo[taskID].memUsed, usedSize);
return;
}
g_tskMemUsedInfo[taskID].memUsed -= usedSize;
g_tskMemUsedInfo[taskID].memUsed -= usedSize; ///< 递减
}
/// 获取指定任务对内存的使用情况
LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskMemUsage(UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
......@@ -70,7 +70,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskMemUsage(UINT32 taskID)
return g_tskMemUsedInfo[taskID].memUsed;
}
/// 清空任务内存使用记录
LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemClear(UINT32 taskID)
{
if (taskID >= LOSCFG_BASE_CORE_TSK_LIMIT) {
......@@ -82,8 +82,8 @@ LITE_OS_SEC_TEXT_MINOR VOID OsTaskMemClear(UINT32 taskID)
}
g_tskMemUsedInfo[taskID].memUsed = 0;
}
#ifdef LOS_MEM_SLAB
// Slab是一种内存分配器,通过将内存划分不同大小的空间分配给对象使用来进行缓存管理,应用于内核对象的缓存。
#ifdef LOS_MEM_SLAB //
LITE_OS_SEC_BSS_MINOR STATIC TskSlabUsedInfo g_tskSlabUsedInfo[LOSCFG_BASE_CORE_TSK_LIMIT];
LITE_OS_SEC_TEXT_MINOR VOID OsTaskSlabUsedInc(UINT32 usedSize, UINT32 taskID)
......
此差异已折叠。
......@@ -105,7 +105,7 @@
#define OS_MEM_COLUMN_NUM 8
UINT8 *m_aucSysMem0 = NULL; ///< 异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
UINT8 *m_aucSysMem1 = NULL; ///< 系统动态内存池地址的起始地址
UINT8 *m_aucSysMem1 = NULL; ///< 系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
#ifdef LOSCFG_MEM_MUL_POOL
VOID *g_poolHead = NULL; ///内存池头,由它牵引多个内存池
......@@ -378,14 +378,14 @@ STATIC INLINE struct OsMemNodeHead *PreSentinelNodeGet(const VOID *pool, const s
return NULL;
}
/// 大内存释放
UINT32 OsMemLargeNodeFree(const VOID *ptr)
{
LosVmPage *page = OsVmVaddrToPage((VOID *)ptr);
LosVmPage *page = OsVmVaddrToPage((VOID *)ptr);//获取物理页
if ((page == NULL) || (page->nPages == 0)) {
return LOS_NOK;
}
LOS_PhysPagesFreeContiguous((VOID *)ptr, page->nPages);
LOS_PhysPagesFreeContiguous((VOID *)ptr, page->nPages);//释放连续的几个物理页
return LOS_OK;
}
......@@ -2091,7 +2091,7 @@ UINT32 LOS_MemFreeNodeShow(VOID *pool)
return LOS_OK;
}
///内核空间动态内存(堆内存)初始化
///内核空间动态内存(堆内存)初始化 , 争取系统动态内存池
STATUS_T OsKHeapInit(size_t size)
{
STATUS_T ret;
......@@ -2110,38 +2110,38 @@ STATUS_T OsKHeapInit(size_t size)
return -1;
}
m_aucSysMem0 = m_aucSysMem1 = ptr;
ret = LOS_MemInit(m_aucSysMem0, size); //初始化内存池
m_aucSysMem0 = m_aucSysMem1 = ptr;// 指定内核内存池的位置
ret = LOS_MemInit(m_aucSysMem0, size); //初始化内存池,供内核分配动态内存
if (ret != LOS_OK) {
PRINT_ERR("vmm_kheap_init LOS_MemInit failed!\n");
g_vmBootMemBase -= size;
return ret;
}
#if OS_MEM_EXPAND_ENABLE
LOS_MemExpandEnable(OS_SYS_MEM_ADDR);
LOS_MemExpandEnable(OS_SYS_MEM_ADDR);//支持扩展系统动态内存
#endif
return LOS_OK;
}
///< 判断地址是否在堆区
BOOL OsMemIsHeapNode(const VOID *ptr)
{
struct OsMemPoolHead *pool = (struct OsMemPoolHead *)m_aucSysMem1;
struct OsMemNodeHead *firstNode = OS_MEM_FIRST_NODE(pool);
struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize);
struct OsMemPoolHead *pool = (struct OsMemPoolHead *)m_aucSysMem1;//内核堆区开始地址
struct OsMemNodeHead *firstNode = OS_MEM_FIRST_NODE(pool);//获取内存池首个节点
struct OsMemNodeHead *endNode = OS_MEM_END_NODE(pool, pool->info.totalSize);//获取内存池的尾节点
if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {
if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//如果在首尾范围内
return TRUE;
}
#if OS_MEM_EXPAND_ENABLE
UINT32 intSave;
UINT32 size;
MEM_LOCK(pool, intSave);
while (OsMemIsLastSentinelNode(endNode) == FALSE) {
size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);
firstNode = OsMemSentinelNodeGet(endNode);
endNode = OS_MEM_END_NODE(firstNode, size);
if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {
#if OS_MEM_EXPAND_ENABLE//内存池经过扩展后,新旧块的虚拟地址是不连续的,所以需要跳块判断
UINT32 intSave;
UINT32 size;//详细查看百篇博客系列篇之 鸿蒙内核源码分析(内存池篇)
MEM_LOCK(pool, intSave); //获取自旋锁
while (OsMemIsLastSentinelNode(endNode) == FALSE) { //哨兵节点是内存池结束的标记
size = OS_MEM_NODE_GET_SIZE(endNode->sizeAndFlag);//获取节点大小
firstNode = OsMemSentinelNodeGet(endNode);//获取下一块的开始地址
endNode = OS_MEM_END_NODE(firstNode, size);//获取下一块的尾节点
if (OS_MEM_MIDDLE_ADDR(firstNode, ptr, endNode)) {//判断地址是否在该块中
MEM_UNLOCK(pool, intSave);
return TRUE;
}
......
/*!
* @file los_vm_iomap.c
* @brief DMA
* @link
@verbatim
直接内存访问
直接内存访问(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的
硬件子系统(电脑外设),可以独立地直接读写系统内存,而不需中央处理器(CPU)介入处理
在同等程度的处理器负担下,DMA是一种快速的数据传送方式。很多硬件的系统会使用DMA,包含硬盘控制器、
绘图显卡、网卡和声卡。
DMA是所有现代电脑的重要特色,它允许不同速度的硬件设备来沟通,而不需要依于中央处理器的大量中断负载。
否则,中央处理器需要从来源把每一片段的资料复制到寄存器,然后把它们再次写回到新的地方。在这个时间中,
中央处理器对于其他的工作来说就无法使用。
DMA传输常使用在将一个内存区从一个设备复制到另外一个。当中央处理器初始化这个传输动作,传输动作本身是
由DMA控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存去。像是这样的操作
并没有让处理器工作拖延,使其可以被重新调度去处理其他的工作。DMA传输对于高性能嵌入式系统算法和网络是
很重要的。 举个例子,个人电脑的ISA DMA控制器拥有8个DMA通道,其中的7个通道是可以让计算机的中央处理器所利用。
每一个DMA通道有一个16位地址寄存器和一个16位计数寄存器。要初始化资料传输时,设备驱动程序一起设置DMA通道的
地址和计数寄存器,以及资料传输的方向,读取或写入。然后指示DMA硬件开始这个传输动作。当传输结束的时候,
设备就会以中断的方式通知中央处理器。
"分散-收集"(Scatter-gather)DMA允许在一次单一的DMA处理中传输资料到多个内存区域。相当于把多个简单的DMA要求
串在一起。同样,这样做的目的是要减轻中央处理器的多次输出输入中断和资料复制任务。
DRQ意为DMA要求;DACK意为DMA确认。这些符号一般在有DMA功能的电脑系统硬件概要上可以看到。
它们表示了介于中央处理器和DMA控制器之间的电子信号传输线路。
缓存一致性问题
DMA会导致缓存一致性问题。想像中央处理器带有缓存与外部内存的情况,DMA的运作则是去访问外部内存,
当中央处理器访问外部内存某个地址的时候,暂时先将新的值写入缓存中,但并未将外部内存的资料更新,
若在缓存中的资料尚未更新到外部内存前发生了DMA,则DMA过程将会读取到未更新的资料。
相同的,如果外部设备写入新的值到外部内存内,则中央处理器若访问缓存时则会访问到尚未更新的资料。
这些问题可以用两种方法来解决:
缓存同调系统(Cache-coherent system):以硬件方法来完成,当外部设备写入内存时以一个信号来通知
缓存控制器某内存地址的值已经过期或是应该更新资料。
非同调系统(Non-coherent system):以软件方法来完成,操作系统必须确认缓存读取时,DMA程序已经
开始或是禁止DMA发生。
第二种的方法会造成DMA的系统负担。
@endverbatim
* @version
* @author weharmonyos.com | 鸿蒙研究站 | 每天死磕一点点
* @date 2022-04-02
*/
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
......@@ -36,7 +82,7 @@
#include "los_vm_map.h"
#include "los_memory.h"
/// 分配DMA空间
VOID *LOS_DmaMemAlloc(DMA_ADDR_T *dmaAddr, size_t size, size_t align, enum DmaMemType type)
{
VOID *kVaddr = NULL;
......@@ -51,9 +97,9 @@ VOID *LOS_DmaMemAlloc(DMA_ADDR_T *dmaAddr, size_t size, size_t align, enum DmaMe
}
#ifdef LOSCFG_KERNEL_VM
kVaddr = LOS_KernelMallocAlign(size, align);
kVaddr = LOS_KernelMallocAlign(size, align);//不走内存池方式, 直接申请物理页
#else
kVaddr = LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, align);
kVaddr = LOS_MemAllocAlign(OS_SYS_MEM_ADDR, size, align);//从内存池中申请
#endif
if (kVaddr == NULL) {
VM_ERR("failed, size = %u, align = %u", size, align);
......@@ -61,16 +107,16 @@ VOID *LOS_DmaMemAlloc(DMA_ADDR_T *dmaAddr, size_t size, size_t align, enum DmaMe
}
if (dmaAddr != NULL) {
*dmaAddr = (DMA_ADDR_T)LOS_PaddrQuery(kVaddr);
*dmaAddr = (DMA_ADDR_T)LOS_PaddrQuery(kVaddr);//查询物理地址, DMA直接将数据灌到物理地址
}
if (type == DMA_NOCACHE) {
if (type == DMA_NOCACHE) {//无缓存模式 , 计算新的虚拟地址
kVaddr = (VOID *)VMM_TO_UNCACHED_ADDR((UINTPTR)kVaddr);
}
return kVaddr;
}
/// 释放 DMA指针
VOID LOS_DmaMemFree(VOID *vaddr)
{
UINTPTR addr;
......@@ -79,13 +125,13 @@ VOID LOS_DmaMemFree(VOID *vaddr)
return;
}
addr = (UINTPTR)vaddr;
// 未缓存区
if ((addr >= UNCACHED_VMM_BASE) && (addr < UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)) {
addr = UNCACHED_TO_VMM_ADDR(addr);
addr = UNCACHED_TO_VMM_ADDR(addr); //转换成未缓存区地址
#ifdef LOSCFG_KERNEL_VM
LOS_KernelFree((VOID *)addr);
LOS_KernelFree((VOID *)addr);//
#else
LOS_MemFree(OS_SYS_MEM_ADDR, (VOID *)addr);
LOS_MemFree(OS_SYS_MEM_ADDR, (VOID *)addr);//内存池方式释放
#endif
} else if ((addr >= KERNEL_VMM_BASE) && (addr < KERNEL_VMM_BASE + KERNEL_VMM_SIZE)) {
#ifdef LOSCFG_KERNEL_VM
......@@ -98,7 +144,7 @@ VOID LOS_DmaMemFree(VOID *vaddr)
}
return;
}
/// 将DMA虚拟地址转成物理地址
DMA_ADDR_T LOS_DmaVaddrToPaddr(VOID *vaddr)
{
return (DMA_ADDR_T)LOS_PaddrQuery(vaddr);
......
......@@ -102,8 +102,8 @@
#define VM_MAP_WASTE_MEM_LEVEL (PAGE_SIZE >> 2) ///< 浪费内存大小(1K)
LosMux g_vmSpaceListMux; ///< 用于锁g_vmSpaceList的互斥量
LOS_DL_LIST_HEAD(g_vmSpaceList); ///< 初始化全局虚拟空间节点,所有虚拟空间都挂到此节点上.
LosVmSpace g_kVmSpace; ///< 内核空间,用于内核运行栈,代码区,数据区
LosVmSpace g_vMallocSpace; ///< 内核空间,用于内核分配内存
LosVmSpace g_kVmSpace; ///< 内核非分配空间,用于内核运行栈,代码区,数据区
LosVmSpace g_vMallocSpace; ///< 内核分配空间,用于内核分配内存
/************************************************************
* 获取进程空间系列接口
......@@ -120,8 +120,8 @@ LosVmSpace *LOS_SpaceGet(VADDR_T vaddr)
return LOS_GetKVmSpace(); //获取内核空间
} else if (LOS_IsUserAddress(vaddr)) {//是否为用户空间
return LOS_CurrSpaceGet();
} else if (LOS_IsVmallocAddress(vaddr)) {//是否为内核空间
return LOS_GetVmallocSpace();//获取内核空间
} else if (LOS_IsVmallocAddress(vaddr)) {//是否为内核分配空间
return LOS_GetVmallocSpace();//获取内核分配空间
} else {
return NULL;
}
......@@ -246,7 +246,7 @@ BOOL OsVMallocSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb)//内核动态空
#endif
return OsVmSpaceInitCommon(vmSpace, virtTtb);//创建MMU,为后续的虚实映射做好初始化的工作
}
///内核进程虚拟空间初始化
///内核虚拟空间初始化
VOID OsKSpaceInit(VOID)
{
OsVmMapInit();//初始化后续操作 g_vmSpaceList 的互斥锁
......@@ -286,22 +286,22 @@ LosVmSpace *OsCreateUserVmSpace(VOID)
if (space == NULL) {
return NULL;
}
VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);//分配一个物理页用于存放虚实内存映射关系, 即:L1表
if (ttb == NULL) {//若连映射页都没有,剩下的也别玩了.
//此处为何直接申请物理页帧存放用户进程的页表,大概是因为所有页表都被存放在内核空间(g_kVmSpace)而非内核分配空间(g_vMallocSpace)
VADDR_T *ttb = LOS_PhysPagesAllocContiguous(1);//分配一个物理页用于存放虚实映射关系表, 即:L1表
if (ttb == NULL) {//若连页表都没有,剩下的也别玩了.
(VOID)LOS_MemFree(m_aucSysMem0, space);
return NULL;
}
(VOID)memset_s(ttb, PAGE_SIZE, 0, PAGE_SIZE);
(VOID)memset_s(ttb, PAGE_SIZE, 0, PAGE_SIZE);//4K空间置0
retVal = OsUserVmSpaceInit(space, ttb);//初始化用户空间,mmu
LosVmPage *vmPage = OsVmVaddrToPage(ttb);
LosVmPage *vmPage = OsVmVaddrToPage(ttb);//找到所在物理页框
if ((retVal == FALSE) || (vmPage == NULL)) {
(VOID)LOS_MemFree(m_aucSysMem0, space);
LOS_PhysPagesFreeContiguous(ttb, 1);
return NULL;
}
LOS_ListAdd(&space->archMmu.ptList, &(vmPage->node));
LOS_ListAdd(&space->archMmu.ptList, &(vmPage->node));//页表链表,先挂上L1,后续还会挂上 N个L2表
return space;
}
......@@ -1222,7 +1222,7 @@ VOID *LOS_KernelMallocAlign(UINT32 size, UINT32 boundary)
{
VOID *ptr = NULL;
#ifdef LOSCFG_KERNEL_VM
#ifdef LOSCFG_KERNEL_VM
if (OsMemLargeAlloc(size) && IS_ALIGNED(PAGE_SIZE, boundary)) {
ptr = LOS_PhysPagesAllocContiguous(ROUNDUP(size, PAGE_SIZE) >> PAGE_SHIFT);
} else
......@@ -1278,7 +1278,7 @@ VOID LOS_KernelFree(VOID *ptr)
{
#ifdef LOSCFG_KERNEL_VM
UINT32 ret;
if (OsMemIsHeapNode(ptr) == FALSE) {
if (OsMemIsHeapNode(ptr) == FALSE) {//判断地址是否在堆区
ret = OsMemLargeNodeFree(ptr);
if (ret != LOS_OK) {
VM_ERR("KernelFree %p failed", ptr);
......@@ -1287,7 +1287,7 @@ VOID LOS_KernelFree(VOID *ptr)
} else
#endif
{
(VOID)LOS_MemFree(OS_SYS_MEM_ADDR, ptr);
(VOID)LOS_MemFree(OS_SYS_MEM_ADDR, ptr);//从内存池中释放
}
}
......
......@@ -337,7 +337,7 @@ extern UINT32 __heap_end; ///< 堆区结束地址
* Starting address of the system memory
*/
#ifndef OS_SYS_MEM_ADDR
#define OS_SYS_MEM_ADDR (&m_aucSysMem1[0])//系统内存起始地址
#define OS_SYS_MEM_ADDR (&m_aucSysMem1[0])//系统内存起始地址(指虚拟地址)
#endif
/**
......
......@@ -291,7 +291,7 @@ LITE_OS_SEC_TEXT STATIC int LiteIpcMmap(struct file *filep, LosVmMapRegion *regi
if (ret) {
goto ERROR_MAP_OUT;
}
/* ipc pool init */
/* ipc pool init | ipc单独创建了内存池管理*/
if (LOS_MemInit(ipcInfo->pool.kvaddr, region->range.size) != LOS_OK) {//初始化ipc池
ret = -EINVAL;
goto ERROR_MAP_OUT;
......
git add -A
git commit -m ' 对静态内存实现注解
git commit -m ' 页表部分注解 , 博客见于 鸿蒙内核源码分析(页表管理)
百图画鸿蒙 + 百文说内核 + 百万注源码 => 挖透鸿蒙内核源码
鸿蒙研究站 | http://weharmonyos.com (国内)
| https://weharmony.github.io (国外)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册