nvdimm 驱动的分析

nvdimm 驱动的分析

1.驱动的简介

nvdimm在内核中的驱动,是基于一个典型的字符类型的设备驱动模型去实现的。因此,同样需要实现设备驱动的几个典型操作:open/release/mmap/ioctl。 在open阶段通过efi或者e820 table探测到nvdimm的起始物理地址和长度,通过set_mtrr()设置nvdimm对应程序空间的cache属性,通过io_remmap()把物理地址映射到内核虚拟地址;在release阶段,释放上面的资源。在内核实现mmap,为用户实现用户态mmap()提供支持;定义各种命令,进而在ioctl()中实现,进而为用户和内核态的驱动提供交互接口。最后通过register_chrdev()注册这个设备。

2.主要的数据结构

作为一个驱动,主要的函数当然是file_operations. nvdimm也不例外:

static const struct file_operations nvdimm_fops = {
    .owner = THIS_MODULE,
    .open = nvdimm_open,
    .release = nvdimm_close,
    .mmap = nvdimm_mmap,
    .unlocked_ioctl = nvdimm_ioctl,
};

3. 主要的函数

3.0 Init和Deinit

nvdimmInit()主要功能如下:
{探测设备得到物理地址,set_mtrr、ioramp()为物理地址分配内核空间,注册字符驱动,启动监控nvdimm电容、温度、电量、健康状态的内核线程,注册关机保存数据的服务}

nvdimmDeInit()主要功能:执行和上面的相反的操作

3.1 nvdimm_ioctl()

读取nvdimm状态,设置寄存器的接口,读取eeprom,更新eeprom,dump 寄存器等。 注意这里多次用到copy_to_usr() copy_from_usr() 来同步数据,

3.2 nvdimm_mmap()

为了支持用户态mmap()

3.3 nvdimm_remap();

映射nvdimm物理地址到虚拟内核地址。

4. 和用户态的接口

需要包含公共函数接口,使用举例如下:

fd = open("/dev/Agiga");
ioctl(fd, cmd); //
mmap(fd, ....); //
close(fd);

5. 难点

5.1 支持不同级别的数据一致性

在nvimm_ioremap()中实现,通过调用set_mtrr()实现,然后call相应的ioremap/iormap_wc/iormap_catch。注意由于它只在初始化的时候执行一次,这就意味着一旦驱动加载,它的cache 模式
就固定了,不能运行时动态修改。

5.2 在write back模式的时候需要flush Dcache.

具体执行是通过flush_Dcache(),注意这里是需要考虑多多核的架构,得让每一个perCPU都去做:
void dcache_flush(void)
{
if (nvdimm_cache == MEM_WRITE_BACK) {
if (on_each_cpu(do_wbinvd, NULL, 1) != 0)
printf("Timed out waiting for cache flush.\n");
}
}
然后通过ioctl的一个命令和flush_Dcache相关联,这样用户态就可以刷nvdimm对应的Dcache了。而且,通过上面的代码,可以看到,只在cache 模式为write-back 时才真正的刷Dcache.

5.3 如何实现panci或者关机时保存数据

nvdimm的核心特性是掉电、异常关机或者重启时会触发ADR(新的机制会这样做),此后硬件会把nvdimm里DRAM上的数据自动写到它的SSD上去。如果此时需要设置某些寄存器,就需要把设置寄存器的动作注册到panic_notifier_list里去。这样,内核关机或者panic依次执行这个 &panic_notifier_list这个函数链,最终就可以完成设置那些寄存器的操作。
示例如下:

5.3.1 驱动里实现 panic_task_backup() 函数

mypanic_task(struct notifier_block *this, unsigned long event, void *ptr)

{
UINT32 rc = SUCCESS;
struct nvdimm_device *nvdimm;
................

dcache_flush();

for (index = 0; index < total; index++) {
    timeOut = 60 * 5;
    /* step 0: Enable NVDIMM BACKUP function */
    smb_cmd.dev_index = index;
    smb_cmd.rw = SMB_BYTE_WRITE;    // byte write
    .......
    /* return status of operation */
    if (rc == SUCCESS) {
        printk(KERN_CRIT
               "SUCCESS to enable backup mode 0x%c of NVDIMM%d during panic!\n",
               backup_type, index);
    }
    .......
}

5.3.2 声明一个notifier

static struct notifier_block mybackup = {.notifier_call = mypanic_task,
};

5.3.2 注册mybackup到panic 通知链条

atomic_notifier_chain_register(&panic_notifier_list, &mybackup);

参考上面的命令就可以把它注册成功,这样在backup_bloc()里触发备份数据,把DRAM里面的数据写到磁盘。

原文地址:http://blog.51cto.com/xiamachao/2064402

时间: 2024-11-08 23:06:00

nvdimm 驱动的分析的相关文章

intel万兆网卡驱动简要分析

原创文章,转载请注明: 转载自pagefault 本文链接地址: intel万兆网卡驱动简要分析 这里分析的驱动代码是给予linux kernel 3.4.4 对应的文件在drivers/net/ethernet/intel 目录下,这个分析不涉及到很细节的地方,主要目的是理解下数据在协议栈和驱动之间是如何交互的. 首先我们知道网卡都是pci设备,因此这里每个网卡驱动其实就是一个pci驱动.并且intel这里是把好几个万兆网卡(82599/82598/x540)的驱动做在一起的. 首先我们来看对

Linux下hp打印机驱动hplip分析

Hplip分析 版本是2.14,源码位置:http://hplipopensource.com.图的来源:http://hplipopensource.com/node/128. 1.D-Bus初始化流程 D-Bus的初始化同样是在ui4/devmgr5.py开始的. ui4/devmgr5.py 01 class DevMgr5(QMainWindow,  Ui_MainWindow): 02     ...... 03     # TODO: Make sbus init mandatory

Linux网卡驱动架构分析

一.网卡驱动架构 由上到下层次依次为:应用程序→系统调用接口→协议无关接口→网络协议栈→设备无关接口→设备驱动. 二.重要数据结构 1.Linux内核中每一个网卡由一个net_device结构来描述. 2.网卡操作函数集:net_device_ops,这个数据结构是上面net_device的一个成员. 3.网络数据包:sk_buff. 三.网卡驱动代码分析 所用文件为cs89x0.c,主要分析三个部分:网卡初始化.发送数据.接收数据. ㈠网卡初始化 网卡驱动初始化主要在函数init_module

Linux USB驱动框架分析 【转】

转自:http://blog.chinaunix.net/uid-11848011-id-96188.html 初次接触与OS相关的设备驱动编写,感觉还挺有意思的,为了不至于忘掉看过的东西,笔记跟总结当然不可缺,更何况我决定为嵌入式卖命了.好,言归正传,我说一说这段时间的收获,跟大家分享一下Linux的驱动开发.但这次只先针对Linux的USB子系统作分析,因为周五研讨老板催货.当然,还会顺带提一下其他的驱动程序写法. 事实上,Linux的设备驱动都遵循一个惯例——表征驱动程序(用driver更

Linux USB驱动框架分析(2)【转】

转自:http://blog.chinaunix.net/uid-23046336-id-3243543.html 看了http://blog.chinaunix.net/uid-11848011-id-96188.html的驱动框架分析,感觉受益匪浅.对于一些内容,我自己查漏补缺. 首先我们按照顺序,看内核模块的注册以及释放函数如下: 点击(此处)折叠或打开 static int __init usb_skel_init(void) { int result; /* register this

Android中Input型输入设备驱动原理分析(一)

转自:http://blog.csdn.net/eilianlau/article/details/6969361 话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也增加几个属于android自己的机制.典型的IPC Android中的input设备驱动主要包括:游戏杆(joystick).鼠标(mouse)和事件设备(Event). 1.Inpu

[国嵌攻略][133][网卡驱动架构分析]

Linux网络子系统 1.系统调用接口:提供系统调用 2.协议无关接口:统一网络协议给系统调用接口使用 3.网络协议栈  :实现网络协议 4.设备无关接口:统一设备驱动程序给网络协议使用 5.设备驱动程序:实现网卡驱动 Linux驱动在内核中都有一个结构来描述,首先找到设备描述结构,然后找到设备如何注册和初始化. 网卡描述结构 在Linux内核中,每个网卡都由一个net_device结构来描述,其中一些重要成员: char name[IFNAMSIZ]   设备名,如:eth%d unsigne

块设备驱动架构分析

1. 块设备概念:块设备是指只能以块为单位进行访问的设备,块的大小一般是512个字节的整数倍.常见的块设备包括硬件,SD卡,光盘等.</span> 上边是通过一个编写好的块设备驱动,然后安装块设备驱动以及一些相关操作来体会块设备驱动!(此处省略) 2. 块设备驱动的系统架构 2.1 系统架构---VFS VFS是对各种具体文件系统的一种封装,用户程序访问文件提供统一的接口. 2.2 系统架构---Cache 当用户发起文件访问请求的时候,首先回到Disk Cache中寻址文件是否被缓存了,如果

Hadoop 2.0 Yarn代码:心跳驱动服务分析

当RM(ResourcesManager)和NM(NodeManager)陆续将所有模块服务启动,最后启动是NodeStatusUpdater,NodeStatusUpdater将用Hadoop RPC远程调用ResourcesTrackerService中的函数,进行资源是初始化等操作,为将要运行的Job做好准备.以下主要分析在Job提交之前 RM与NM在心跳的驱动下操作. AD: hadoop-yarn-server-resourcemanager下的包 org.apache.hadoop.