业余的SSD探索笔记

目前在日本从事SSD的开发,
日本太拘泥于硬件,导致软件开发的效率和品质比较低下。
(写完代码之后Debug和Test全凭DebugLog和MemoryDump。。。)

于是就有了一个想法,
是不是能写一个一个便于SSD开发的模拟环境呢?
同时自己也想试试全面的学习整个存储的stack(也太贪心了。。)

1.基本构想

层次构成备考
Application/TestFIOlinux下主流的IQ测试软件,开源
KernelLinux。。。
Driver标准的 linux NVMe Driver。。。
虚拟机Qemu可以参考LightNvm的Qemu
虚拟设备Qemu可以参考VSSIM,以及LightNvm的Qemu
FLT也许把现在的工作中写的简化一下拿过来也ok。。。
虚拟NANDSLC,MLC,TLC,3DEagleTree可以参考

2.进展及步骤记录

由于懂得不多,就一点一点学习研究,一点一点构建吧
首先从搭建一个可以用GDB来调试 NVMe Driver 以及 虚拟的NVMe 设备的环境开始。

目前做到的是:
1. 成功的编译支持nvme的qemu
2. 成功的编译linux(带nvme driver,带debug info)
3. qemu上面成功运行linux,成功的挂载了虚拟的nvme设备。
4. 成功的用gdb来debug NVMe Driver
5. 成功的用gdb来debug NVMe 虚拟设备
接下来:
6. 分析NVMe Driver的代码
7. 分析NVMe 虚拟设备的代码

Qemu的编译及调试:

https://github.com/OpenChannelSSD/qemu-nvme.git
TBD(用的是lightNvm的qemu环境)

Linux的编译及调试:

参考文章:

http://www.linux-magazine.com/Online/Features/Qemu-and-the-Kernel

遇上的问题及解决的办法:

本来是尝试在64位的linux上面进行调试的,但是试了一下发现gdb还不能支持qemu上的64位的linux的调试(从start_kernel开始的调试)
换成了32bit的linux之后问题就解决了

make qemu_x86_64_defconfig
使用时遇上了 “gdb replay g packet is too long”的问题,查了一下面的内容,发现好像是gdb的问题,还没得到解决。
http://stackoverflow.com/questions/8662468/remote-g-packet-reply-is-too-long
https://lists.nongnu.org/archive/html/qemu-discuss/2014-10/msg00069.html
http://stackoverflow.com/questions/8662468/remote-g-packet-reply-is-too-long
http://augustl.com/blog/2014/gdb_progress/
https://sourceware.org/bugzilla/show_bug.cgi?id=13984

Linux Driver的基本解析:

详细的分析可以参考:
http://blog.csdn.net/panzhenjie/article/details/51581063
这里只是列出基本的Function Tree及动作Sequence


相关系统文件及信息

/proc/devices : 代表某种设备对应的主设备号,而不是设备的实例
/proc/iomem:IO空间映射
/dev: 代表某种设备的实例
lspci -k


Function Tree (Version 4.5.3)


nvme_init
├nvme_workq = alloc_workqueue : 创建一个全局的workqueue
├nvme_core_init
│├register_blkdev : 注册一个名字叫nvme的块设备
│├__register_chrdev : 注册一个名字叫nvme的字符设备
│└class_create(THIS_MODULE, “nvme”);
└pci_register_driver :
注册了一个pci驱动(属性和callback表)
- 包括:name:“nvme”,
- id_table
- nvme_probe函数
- nvme_remove函数
- nvme_remove函数
- pm ops:(nvme_suspend,nvme_resume)
- error handler:(nvme_error_detect,nvme_slot_reset,nvme_error_resume,nvme_reset_notify)

nvme_exit
├pci_unregister_driver
├nvme_core_exit
└destory_workqueue

nvme_probe
├dev_to_node
├kzalloc_node(sizeof( * dev))
├kzalloc_node(num_possible_cpus() * sizeof( * dev->entry)):msi相关信息(cpu core个)
├kzalloc_node((num_possible_cpus() + 1) * sizeof(void * )):admin queue(1个)+ io queue(cpu core个)的相关信息
├get_device
├pci_set_drvdata
├nvme_dev_map
│├bars = pci_select_bars:pci设备的配置空间里有6个32位的bar寄存器,每一位代表一个bar(base address register)是否被置位
│├pci_request_selected_regions(pdev, bars, “nvme”):把对应的这个几个bar保留起来,不让别人使用。 (结果可以在/proc/iomem中确认)
│└dev->bar = ioremap:把pci bar的物理地址映射到虚拟地址
├INIT_WORK(&dev->scan_work, nvme_dev_scan);
├INIT_WORK(&dev->reset_work, nvme_reset_work);
├INIT_WORK(&dev->remove_work, nvme_remove_dead_ctrl_work);
├init_completion(&dev->ioq_wait);
├nvme_setup_prp_pools:创建dma pool,后面就可以通过其他dma函数从dma pool中获得memory
│├dev->prp_page_pool = dma_pool_create(“prp list page”, dev->dev,PAGE_SIZE, PAGE_SIZE, 0);
│└dev->prp_small_pool = dma_pool_create(“prp list 256”, dev->dev,256, 256, 0);
├nvme_init_ctrl
│├nvme_set_instance
│├device_create_with_group
│├get_device
│├dev_set_drvdata
│├ida_init
│├spin_lock
│├
│├
└queue_work(nvme_workq):调度nvme_reset_work

PCIe的基础知识

目前在看下面的文章补补PCIe相关知识:
http://blog.sina.com.cn/s/articlelist_1685243084_3_1.html
http://free-electrons.com/doc/pci-drivers.pdf

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值