zoukankan      html  css  js  c++  java
  • hisi mmz模块驱动讲解

    一、概述

    如图所示,在海思平台上将内存分为两个部分:os内存和mmz内存。os内存指:由linux操作系统管理的内存;mmz内存:由mmz驱动模块进行管理供媒体业务单独使用的内存,在驱动加载时可以指定该模块管理内存的大小:

    insmod hi_osal.ko mmz=anonymous,0,0x4fa00000,6Manony=1 || report_error
    

    image

    二、数据结构

    1、mmz区域描述符

    struct hil_media_memory_zone {
    
       char name[HIL_MMZ_NAME_LEN+1]; //mmz区域名字:anonymous
    
           
    
       unsigned long gfp;   //区域标识:0
    
     
    
       unsigned long phys_start; //mmz区域起始物理地址:0x4fa00000
    
       unsigned long nbytes; //mmz区域大小:6M
    
           
    
       struct list_head list; //mmz链表
    
     
    
       unsigned char *bitmap; //位图
    
       struct list_head mmb_list; //mmz区域的mmb链表,存放所有申请到的物理内存
    
       
    
       unsigned int alloc_type;
    
       unsigned long block_align;
    
       
    
       void (*destructor)(const void *);
    
    };
    

    2、mmb内存描述符

    hil_media_memory_block描述了从mmz区域申请一块内存,同一个mmz区域内的所有mmb通过链表连接。

    struct hil_media_memory_block {
    
       #ifndef MMZ_V2_SUPPORT
    
       unsigned int id;
    
       #endif
    
       char name[HIL_MMB_NAME_LEN+1]; //该mmb模块使用者名字
    
       struct hil_media_memory_zone *zone; //指向mmb所属的mmz区域
    
       struct list_head list; //mmb链表
    
            
    
       unsigned long phys_addr; //申请到的mmb起始物理地址
    
       void *kvirt;  //对应内核虚拟地址,从代码看未用
    
       unsigned long length; //申请的mmb大小
    
       
    
       unsigned long flags; //标识
    
       
    
       unsigned int order;
    
     
    
       int phy_ref; //引用计数
    
       int map_ref; //引用计数
    
    };
    

    3、mmz_userdev_info

    该结构体保存打开该设备文件的进程信息,存放在file结构体的private_data成员里。

    struct mmz_userdev_info {
    
       pid_t pid;         //打开设备文件的进程pid
    
       pid_t mmap_pid;
    
       struct semaphore sem; //信号量
    
       struct list_head list; //指向mmb_info链表
    
    };
    

    4、mmb_info

    该结构体描述应用申请到mmb后的相关信息,同进程的mmb_info通过链表形式管理。

    struct mmb_info {
    
       unsigned long phys_addr;    //申请到的物理内存,同mmb.phys.addr
    
       unsigned long align;        /* ifyou need your phys-memory have special align size */
    
       unsigned long size;     //申请的物理内存大小
    
       unsigned int order;
    
       
    
        void *mapped;       //指向mmap后的虚拟地址空间
    
           
    
       union {
    
           struct {
    
               unsigned long prot  :8; /*PROT_READ or PROT_WRITE */
    
               unsigned long flags :12;/* MAP_SHARED or MAP_PRIVATE */
    
       
    
    #ifdef __KERNEL__
    
               unsigned long reserved :8; /* reserved, do not use */
    
               unsigned long delayed_free :1;
    
               unsigned long map_cached :1;
    
    #endif
    
           };
    
           unsigned long w32_stuf;
    
       };
    
       
    
       char mmb_name[HIL_MMB_NAME_LEN+1];
    
       char mmz_name[HIL_MMZ_NAME_LEN+1];
    
       unsigned long gfp;      /*reserved, do set to 0 */
    
       
    
    #ifdef __KERNEL__
    
       int map_ref;
    
       int mmb_ref;
    
           
    
       struct list_head list;    //mmb_info链表
    
       hil_mmb_t *mmb;     //指向申请到的mmb
    
    #endif
    
    };
    

    三、关系图

    1、mmz和mmb关系

    下图展示了mmz驱动管理mmz和mmb的关系。mmz驱动模块支持多个mmz区域,只要在加载mmz.ko时通过参数传递即可,一般情况下只有一个mmz区域。多个mmz区域之间通过链表的形式组织在一起,链表头为mmz_list;而每个mmz区域通过mmb_list维护mmb链表,管理该区域内所有已经申请了的物理内存区域;每个mmb通过zone成员知道自己属于哪个mmz区域。

    通过/proc/media-mem可以查看mmz和mmb使用情况:

    +---ZONE: PHYS(0x4FA00000, 0x4FFFFFFF),GFP=0, nBYTES=6144KB,  NAME="anonymous"
    
      |-MMB: phys(0x4FA00000, 0x4FA81FFF), kvirt=0x  (null), flags=0x00000000, length=520KB,       name="DCCM_MSG_BUF"
    
      |-MMB: phys(0x4FA82000, 0x4FA84FFF), kvirt=0x  (null), flags=0x00000000, length=12KB,        name="SYS_scale_coef"
    
      |-MMB: phys(0x4FA85000, 0x4FA87FFF), kvirt=0x  (null), flags=0x00000000, length=12KB,        name="SYS_scale_coef"
    
      |-MMB: phys(0x4FA88000, 0x4FB07FFF), kvirt=0x  (null), flags=0x00000000, length=512KB,       name="TDE_MemPool"
    
       |-MMB: phys(0x4FB08000, 0x4FB3CFFF),kvirt=0x  (null), flags=0x00000000,length=212KB,      name="IVE_QUEUE"
    
      |-MMB: phys(0x4FB3D000, 0x4FB3DFFF), kvirt=0x  (null), flags=0x00000000, length=4KB,name="IVE_TEMP_NODE"
      
      --MMZ_USE_INFO:
    
     total size=6144KB(6MB),used=1272KB(1MB +248KB),remain=4872KB(4MB + 776KB),zone_number=1,block_number=6
    

    image

    2、mmb、mmb_info和mmb_userdev_info关系

    下图展示了mmz驱动和应用申请数据结构之间的关系:

    image

    当应用打开设备文件/dev/mmz_userdev时会申请一个属于该进程的mmb_userdev_info结构体,mmb_userdev_info成员list指向属于该进程的所有mmb_info,mmb_info的mmb成员指向为其分配的mmb,而*mmaped存放mmb物理内存(phy_addr)进行映射后的虚拟地址供用户空间使用。

    由于mmz大部分为媒体业务独立使用,内存在媒体硬件模块流转,应用无需访问,这时不用映射,只有当应用需要访问时才需要进行映射。可以把mmz管理的整个内存看做存储盘上的一个大文件,应用层要访问mmz的物理内存通过mmap方式进行映射(类似文件),映射的文件偏移就是mmb.phy_addr,映射大小就是申请的mmb.length,通过mmap方式映射到内核后根据返回的虚拟地址就可以访问该mmb内存。

  • 相关阅读:
    Java实现 LeetCode 69 x的平方根
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 66 加一
    Java实现 LeetCode 66 加一
    CxSkinButton按钮皮肤类
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/11297705.html
Copyright © 2011-2022 走看看