内核从用户空间访问BAR寄存器

时间:2013-11-20 18:41:26

标签: linux linux-kernel

我正在尝试在Linux上为自定义powerpc板上的FC类设备(HBA)开发用户级驱动程序。我已经使用remap_pfn_range()将PCI配置空间和BAR寄存器映射到用户空间并锁定了地址空间。当我试图访问BAR寄存器以清除用户空间中的邮箱等时,我的内核出现内核恐慌。

有人可以指点调试内核恐慌并验证PCI配置。 是否可以进行这种内存映射。 TLB似乎有映射条目。

lspci O / p:

lspci -vvv
00:01.0 Class 0c04: Device 1077:2a31 (rev 02)
    Subsystem: Device 1077:0000
    Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
    Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
    Interrupt: pin A routed to IRQ 0
    Region 0: Memory at 80000000 (64-bit, prefetchable) [size=8K]
    Region 2: Memory at 80140000 (64-bit, prefetchable) [size=16K]
    Region 4: Memory at 87000000 (64-bit, prefetchable) [size=1M]
    Expansion ROM at 80100000 [disabled] [size=256K]
    Capabilities: [44] Power Management version 3
        Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold+)
        Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
    Capabilities: [4c] Express (v2) Endpoint, MSI 00
        DevCap: MaxPayload 1024 bytes, PhantFunc 0, Latency L0s <4us, L1 <1us
            ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+
        DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
            RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop FLReset-
            MaxPayload 128 bytes, MaxReadReq 512 bytes
        DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
        LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM L0s, Latency L0 <2us, L1 <2us
            ClockPM- Surprise- LLActRep- BwNot-
        LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
            ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
        LnkSta: Speed 2.5GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
        DevCap2: Completion Timeout: Range B, TimeoutDis+, LTR+, OBFF Via message/WAKE#
        DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled
        LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1-
             EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest-
    Capabilities: [88] Vital Product Data
        No end tag found
    Capabilities: [90] MSI-X: Enable- Count=32 Masked-
        Vector table: BAR=2 offset=00000000
        PBA: BAR=2 offset=00001000
    Capabilities: [100 v1] Advanced Error Reporting
        UESta:  DLP- SDES- TLP- FCP- CmpltT- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
        UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
        UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
        CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
        CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
        AERCap: First Error Pointer: 00, GenCap+ CGenEn- ChkCap+ ChkEn-
    Capabilities: [154 v1] Alternative Routing-ID Interpretation (ARI)
        ARICap: MFVC- ACS-, Next Function: 1
        ARICtl: MFVC- ACS-, Function Group: 0
    Capabilities: [19c v1] Address Translation Service (ATS)
        ATSCap: Invalidate Queue Depth: 08
        ATSCtl: Enable-, Smallest Translation Unit: 00
    Capabilities: [1a4 v1] Transaction Processing Hints
        No steering table available
    Capabilities: [1b0 v1] #19
    Capabilities: [1cc v1] Latency Tolerance Reporting
        Max snoop latency: 0ns
        Max no snoop latency: 0ns
<4>[ 3486.328040] Bad trap at PC: fe27fc4, SR: 2d000, vector=102
<4>[ 3486.328104] Bad trap at PC: c000fb94, SR: 29000, vector=102
<4>[ 3486.328143] Oops: Exception in kernel mode, sig: 5 [#1]
<4>[ 3486.328168] PREEMPT DEBUG_PAGEALLOC APP
<4>[ 3486.328197] Modules linked in: qlapci memdev ttyprint
<4>[ 3486.328240] NIP: c000fb94 LR: c000f7cc CTR: 00000000
<4>[ 3486.328272] REGS: c7ffdf10 TRAP: 0102   Not tainted  (2.6.32)
<4>[ 3486.328300] MSR: 00029000 <EE,ME,CE>  CR: 24002484  XER: 00000018
<4>[ 3486.328352] TASK = c4060df0[828] 'app' THREAD: c405e000
<4>[ 3486.328376] GPR00: 00000000 c405ff00 c4060df0 00004000 c405fd88 00000000 ffffffff 00000010 
<4>[ 3486.328440] GPR08: 00000000 00000002 00029002 c405e000 24002482 100aa0fc 00000000 90800000 
<4>[ 3486.328503] GPR16: 00000000 00000003 100a2258 00000000 10038e44 911ff930 00a00000 0ffbe1bc 
<4>[ 3486.328567] GPR24: 00001000 0ffbc124 911ff490 10098a38 0ff7894c 00000011 0ff77ff4 0ff78488 
<4>[ 3486.328665] NIP [c000fb94] do_user_signal+0x8/0xc4
<4>[ 3486.328697] LR [c000f7cc] ret_from_crit_exc+0x0/0x104
<4>[ 3486.328723] Call Trace:
<4>[ 3486.328746] [c405ff00] [c000f7cc] ret_from_crit_exc+0x0/0x104 (unreliable)
<4>[ 3486.328782] Instruction dump:
<4>[ 3486.328804] 4817f901 3d400002 614a1002 7d400124 54290024 8129003c 71200004 40a2ffdc
<4>[ 3486.328865] 71202006 4182fb64 614a8000 7d400124 <806100b0> 70600001 41820058 91a10044 
<0>[ 3486.328932] Kernel panic - not syncing: Fatal exception

2 个答案:

答案 0 :(得分:1)

要从用户空间访问PCI资源,请在相应的sysfs文件上调用mmap(),如下所示:

fd = open("/sys/devices/pci0000:00/0000:00:12.3/resource0", O_RDWR | O_SYNC);
ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

在PowerPC上,由于X的兼容性解决方法,这可能不起作用;您应该重新启用#if 0arch/powerpc/kernel/pci-common.c内的两个代码块。

答案 1 :(得分:0)

  

&#34;我的公司有这个商业计划,这取决于我们利用所有Linux内核和用户空间开发人员的工作,违背他们保持源代码开放的愿望,但我们需要以某种方式做到这一点这使得他们起诉我们风险太大。但是,我发现以合法的方式做这件事非常困难。有人会帮助我吗?&#34;

没有。您描述的驱动程序类型属于内核。内核中已经有几十个类似的驱动程序,你可以很容易地使用这些作为指导来适应/构建一个。您不希望这样,因为这意味着您必须使用GPLv2许可内核驱动程序(因为编写驱动程序的简单方法是使用GPLv2&#39;现有代码),并且您的雇主不要# 39;我想要那个。

您的雇主可以轻松使用另一个免费内核,例如freebsd或openbsd,或者其中一个专有内核,但这也与他们的商业计划背道而驰:他们希望利用Linux。他们希望吃蛋糕,保留蛋糕,并向其他人收费。你在这里寻求帮助来做到这一点:帮助你和你的雇主避免Linux内核开发人员的愿望,同时利用他们的工作。

自私多少?

PCI ID,1077:2a31,表示基于QLogic的接口芯片;您似乎正在开发iSCSI SAN盒。内核中的类似芯片有许多驱动程序变体,因此开发内核驱动程序内核驱动程序要容易得多。如果你做得很好,可以被上游接受,你的维护工作就会大大减少。唯一的缺点是你的雇主必须根据他们产品的优点进行竞争;换句话说,他们实际上必须考虑一个可行的商业计划,而不是使用他们用于他们已经做了十多年的所有Windows工作的相同的商业计划。

时代变了。商业模式也必须发展。


您选择的方法无效。您可以使用特定的内核版本,或者创建用户空间组件与之通信的内核驱动程序(shim)。 Linux中的内核用户空间界面根本不是为了满足你想做的事情而构建的。您需要依赖的部分不存在,或者从内核版本更改为版本。

您遇到的问题的正确解决方案是在内核空间中进行。

现在,如果您要更改方法,并切换到开源内核驱动程序模型,那么很乐意为您提供帮助。

如果您坚持使用Linux,考虑到硬件和现有代码库,您几乎肯定会最终重用现有的GPLv2代码,因此内核驱动程序必须是开源的。 (尽管如此,不要接受我的话;请你的律师确定。)

如果你坚持保持你的驱动程序关闭源,切换到另一个内核 - freebsd,openbsd,或者可能购买其中一个专有的内核。 遵循许可的精神,社区将为您提供帮助。

如果你坚持使用Linux但保持你的驱动程序封闭源代码,至少有自己的技能。


在djs9999对以上内容的评论之后编辑:

您可以使用中间(&#34;硬件探索&#34;)驱动程序作为角色设备,而不是尝试从用户空间执行所有操作,而不是&#34; shim&#34; 驱动程序。 Linux Device Drivers是一个非常好的信息来源,包含一个非常有用的示例字符驱动程序 scull

基本思想是用户空间组件打开您的角色驱动程序。内核驱动程序初始化硬件,映射所需的缓冲区/邮箱内存,初始化硬件中断等。 (如果在设备关闭时清理它们,则硬件探索变得更加容易 - 特别是不需要加载/卸载内核模块。)

字符驱动程序接口使得用户空间组件可以mmap()缓冲区/邮箱,并使用read()从硬件接收通知(中断,消息完成)作为消息,并{{1如果需要,将消息从用户空间组件发送到内核组件。 write()mmap()read()每个都有不同的回调,因此在内核字符驱动程序中这很容易做到;再次,请参阅LDD3 scull 驱动程序示例。

(大多数开发人员倾向于使用write()来处理上述大部分内容,但实际上并不需要。ioctl() / mmap() / read()界面更容易清洁工具。)

现在,这为您提供了一个垫片驱动程序,允许您使用非常简单的内核字符驱动程序从用户空间应用程序中探索硬件。应用程序只需要访问字符设备节点(即,如果您将节点配置为由特定用户拥有,则您的用户空间组件不需要root权限),并且内核字符驱动程序将管理所有低级控件

您可能希望这样做的原因是,它是探索硬件的最简单方法。在许多国家/地区,法律允许您出于互操作性原因分析任何闭源代码的行为,尽管大多数公司出于法律原因将探索和新驱动程序开发分开。基本上,探索用于构造文档,该文档指定如何/必须/可以访问硬件以实现期望的操作。 新驱动程序不会重用任何代码,而是仅基于派生文档编写。

在硬件上有足够好的文档后,您可以开始开发实际的开源驱动程序。

我手头没有任何FC硬件,也没有开发这种驱动程序的经验,所以我在帮助开发FC驱动程序方面几乎毫无用处。但是,Linux内核源代码中的Documentation/scsi/,尤其是Documentatio/scsi/scsi_fc_transport.txt中的文件应该是有用的;就像我说的那样,内核中已经有iSCSI支持等了。在kernel.org(archives at MARC.info)上的linux-scsi邮件列表是你可以要求指针的地方,甚至可能是一个帮助你为硬件开发实际免费驱动程序的导师。

最后,Greg Kroah-Hartmann(website)因帮助公司为其硬件开发免费驱动程序而闻名。以this announcement from January 2007为例。如果您在公司工作,联系他获取信息或更好的联系方式或其他帮助以开发驱动程序,可能是个好主意。