驱动开发注意事项

更新时间:
2023-08-02
下载文档

驱动开发注意事项

本节主要介绍 ECS 容器版本的 BSP 编程注意事项。

地址映射

VAPP 地址映射

容器版本的应用程序虚拟起始地址不得小于 LW_CFG_VMM_PGD_SIZE,建议设定为 LW_CFG_VMM_PGD_SIZE

KMOD 地址映射

容器版本的 BSP 中,供内核模块使用的物理地址空间需要单独划分区域,如下所示,增加了 KMOD 物理内存区域。

LW_MMU_PHYSICAL_DESC    _G_physicalDesc[] = {
#if LW_CFG_CONTAINER_EN > 0
    {                                              /*  KMOD 内存                     */
            BSP_CFG_KMOD_BASE,
            BSP_CFG_KMOD_BASE,
            BSP_CFG_KMOD_SIZE,
            LW_PHYSICAL_MEM_KMOD
    },
#endif                                             /*  LW_CFG_CONTAINER_EN          */

Kernel Mirror 映射

对于 AARCH64、MIPS、CSKY、RISC-V、x86、x86-64、LoongArch64 平台,以及当 ARM 使能 LPAE 功能时,需要在 BSP 的 bspmap.h 中增加 Kernel Mirror 区域的虚拟空间映射。因为在这些处理器平台中,MMU 页表的权限配置不能有效区分内核 DATA 段在内核态可读写,但在用户态只读的场景,因此需要单独映射 Kernel Mirror 段为用户态进程提供对内核 DATA 段的只读权限,增加方式如下所示:

LW_MMU_VIRTUAL_DESC    _G_virtualDesc[] = {
#if LW_CFG_CONTAINER_EN > 0
#if LW_CFG_KERN_MIRROR_MAP_EN > 0
        {                                           /*  内核平板映射虚拟空间           */
                BSP_CFG_RAM_BASE,
                BSP_CFG_TEXT_SIZE + BSP_CFG_DATA_SIZE,
                LW_VIRTUAL_MEM_KERN_FLAT
        },
        {                                           /*  内核镜像映射虚拟空间          */
                BSP_CFG_VAPP_START + BSP_CFG_VAPP_SIZE,
                BSP_CFG_TEXT_SIZE + BSP_CFG_DATA_SIZE,
                LW_VIRTUAL_MEM_KERN_MIRROR
        },
#endif                                              /*  LW_CFG_KERN_MIRROR_MAP_EN   */
#endif                                              /*  LW_CFG_CONTAINER_EN         */

注意:
如果 BSP 中有多个 DATA 段,则需要为每个 DATA 段添加 Kernel Mirror 映射。

PAGETAB 地址映射

为了支持运行更多的容器,BSP 可以单独创建页表堆用于分配容器页表空间。

  1. 以内存大小为 16GB 的 x86_64 设备为例,对 BSP 增加页表堆机制,主要修改如下:

    • bspx64/config.h 文件中增加 2.2GB 页表堆配置。
    #define BSP_CFG_PAGE_TAB_SIZE               ((2LU * 1024 + 200LU) * 1024 *   1024)
    
    • bspInit.c 中增加页表堆全局变量。
    PVOID       _G_pvPagetabHeapMem  = LW_NULL;
    size_t      _G_stPagetabHeapSize = 0;
    
    • bspMultiBootParse() 中在 DATA 段后增加页表段。
    /*
     * HEAP
     */
    i++;
    _G_physicalDesc[i].PHYD_ulPhyAddr = (addr_t)&__e_kernel;
    _G_physicalDesc[i].PHYD_ulVirMap  = (addr_t)&__e_kernel;
    _G_physicalDesc[i].PHYD_stSize    = stHeapMemSize;
    _G_physicalDesc[i].PHYD_uiType    = LW_PHYSICAL_MEM_DATA;
    
    *ppvKernelHeapMem  = (PVOID)_G_physicalDesc[i].PHYD_ulPhyAddr;
    *pstKernelHeapSize = (size_t)_G_physicalDesc[i].PHYD_stSize;
    
    /*
     * PAGE Table
     */
    i++;
    _G_physicalDesc[i].PHYD_ulPhyAddr = (addr_t)&__e_kernel + stHeapMemSize;
    _G_physicalDesc[i].PHYD_ulVirMap  = (addr_t)&__e_kernel + stHeapMemSize;
    _G_physicalDesc[i].PHYD_stSize    = BSP_CFG_PAGE_TAB_SIZE;
    _G_physicalDesc[i].PHYD_uiType    = LW_PHYSICAL_MEM_PAGETAB;
    
    _G_pvPagetabHeapMem  = (PVOID)_G_physicalDesc[i].PHYD_ulPhyAddr;
    _G_stPagetabHeapSize = (size_t)_G_physicalDesc[i].PHYD_stSize;
    
  2. 以 ARM64 设备为例,对 BSP 增加页表堆机制,主要修改如下

    • bsp/config.h 文件中增加 1GB 页表堆配置和页表基地址配置。
    #define BSP_CFG_PAGETAB_SIZE                   (1LU * 1024 * 1024 * 1024)
    #define BSP_CFG_PAGETAB_BASE                   (0x40000000)
    
    • 在 bsp/bspMap.h 中的 _G_physicalDesc 变量中增加如下页表段配置:
    #if LW_CFG_CONTAINER_EN > 0
    {                                                       /* 容器版本页表内存 */
        BSP_CFG_PAGETAB_BASE,
        BSP_CFG_PAGETAB_BASE,
        BSP_CFG_PAGETAB_SIZE,
        LW_PHYSICAL_MEM_PAGETAB
    },
    #endif
    

注意:

  • BSP 中若没有配置页表堆,页表空间将直接使用内核堆。
  • 增加页表段后,DMA、APP 段空间需要根据实际情况重新计算。
  • 地址重新调整后需要注意当前 TEXT、DATA、DMA 段地址范围不能与虚拟地址空间产生冲突,若有重叠部分需要进一步调整。

内存分配

因考虑到云原生环境中需要运行 JSRE,此时需要注意系统堆的分配,不应将系统堆分配的过小,一般应在总内存的 25% 以上。

注意事项

  • 在中断中不能访问应用空间内存

    因为在系统陷入中断时,不能确认是否已经进行过容器的切换。若进行过容器的切换,则中断再访问切换前的容器内应用地址空间时,会出现访问错误。所以驱动开发时不应将应用中的地址空间直接传递到中断服务函数中使用。

  • 驱动创建的线程增加全局对象属性

    驱动内创建的线程应含 LW_OPTION_OBJECT_GLOBAL 属性,否则可能出现如下错误情形:

    线程的创建是由容器内进程调用的。当容器内进程消亡时,非 LW_OPTION_OBJECT_GLOBAL 属性的线程会在消亡过程中被回收,此回收过程在内核中进行,内核中因无法访问此进程所在的容器上下文,导致错误。

文档内容是否对您有所帮助?
有帮助
没帮助