c - Address mapping of PCI-memory in Kernel space -
i'm trying read , write , pci-device loadable kernel module.
therefore follow post:
pci_enable_device(dev); pci_request_regions(dev, "expdev"); bar1 = pci_iomap(dev, 1, 0); // void iowrite32(u32 val, void __iomem *addr) iowrite32( 0xaaaaaaaa, bar1 + 0x060000); /* offset device spec */
but @ end device doesn't work expected. address behind bar1
, found big value ffffbaaaaa004500
.
at point don't understand happen there , right. can interpret bar1
address inside kernel address space points directly base address 0x60000
offset pci chip select address?
and how can value write bar1 + offset
copied device? how mechanism work in behind of iowrite32
, pci_iomap
?
thanks , regards
alex
ps: tested read same address successfully.
register description of pci device:
pcibar0
pci base address 0; used memory-mapped configuration registerspcibar1
pci base address 1; used i/o-mapped configuration registerspcibar2
pci base address 2; used local address space 0pcibar3
pci base address 3; used local address space 1pcibar4
unused base addresspcibar5
unused base address
hello again.
in last time tried several approaches communicate bar2 register without success. here actual code:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/sched.h> module_license("gpl"); module_author("alex"); module_description("test module."); module_version("0.1"); #define dev_pci_vendorid 0x10b5 #define dev_pci_deviceid 0x1860 static struct pci_device_id pci_drvidtable[] = { { .vendor = dev_pci_vendorid, // vendor id .device = dev_pci_deviceid, // device id .subvendor = pci_any_id, // no subsystem available .subdevice = pci_any_id, // no subsystem available .class = pci_class_not_defined, // no device class .class_mask = 0, // no device class .driver_data = 0 // no private data driver }, { 0, } // end of table }; struct pci_data { /// io mapping pci config space uint32_t *pciconfigaddr; uint32_t *pcib2addr; // void __iomem *pciconfigaddr; wait_queue_head_t waitq; uint8_t flag; } *data; static irqreturn_t _expdev_irq (int irq, void *pdata) { struct pci_data *data = pdata; printk(kern_info "interrupt talks...\n"); data->flag = 1; wake_up_interruptible( &data->waitq ); return irq_handled; } static int _pci_probe ( struct pci_dev *pdev, const struct pci_device_id *ent ) { int ret = 0; int i; u16 reg_16; unsigned long bas2addr; data = kzalloc( sizeof(*data) , gfp_kernel ); if( !data ) { printk(kern_err "failed allocate memory.\n"); return -enomem; } pci_set_drvdata(pdev, data); // enabling device ret = pci_enable_device(pdev); if( ret ) { printk(kern_err "failed enable pci device.\n"); goto no_enable; } pci_read_config_word(pdev,0,®_16); printk(kern_info "vendorid. %x\n",reg_16); // checking if pci-device reachable checking bar0 defined , // memory mapped if( !(pci_resource_flags(pdev,0) & ioresource_mem) ) { printk(kern_err "incorrect bar configuration.\n"); ret = -enodev; goto bad_bar; } // taking ownership of memory region ret = pcim_iomap_regions(pdev, 0b0100, "expdev"); // ret = pci_request_regions(pdev,"expdev"); if( ret ) { printk(kern_err "failed request regions.\n"); goto failed_request_regions; } bas2addr = pci_resource_start(pdev, 2); reg_16 = 0xaa; = 0x060000; iowrite16( reg_16 , (unsigned long *)(bas2addr+i) ); printk( kern_info "bar2 register[0x%x] = 0x%x\n", i, ioread32( (unsigned long *)(bas2addr+i) ) ); printk(kern_info "module initialised.\n"); return 0; // error handling - backward disabling device failed_request_regions: bad_bar: pci_disable_device(pdev); no_enable: pci_set_drvdata(pdev, data); return ret; } static void _pci_remove( struct pci_dev *pdev ) { free_irq(pdev->irq, data); pci_disable_msi(pdev); pci_clear_master(pdev); pci_iounmap(pdev,data->pciconfigaddr); pci_release_regions(pdev); pci_disable_device(pdev); printk(kern_info "pci-device removed.\n"); } static struct pci_driver pci_drv = { .name = "expdev", .id_table = pci_drvidtable, .probe = _pci_probe, .remove = _pci_remove, }; // module related functions /////////////////////////////////////////////////// static int __init _module_init(void){ printk(kern_info "hello!\n"); pci_register_driver(&pci_drv); return 0; } static void __exit _module_exit(void){ pci_unregister_driver(&pci_drv); printk(kern_info "goodbye!\n"); } module_init(_module_init); module_exit(_module_exit);
this responding output tail -f /var/log/kern.log
kernel: [ 493.719999] hello! kernel: [ 493.720071] expdev 0000:05:02.0: enabling device (0000 -> 0003) kernel: [ 493.720845] vendorid. 10b5 kernel: [ 493.722375] bug: unable handle kernel paging request @ 00000000eb060000 kernel: [ 493.722381] ip: [<ffffffff8137aca8>] iowrite16+0x38/0x40 kernel: [ 493.722388] pgd 0 kernel: [ 493.722390] oops: 0002 [#1] smp kernel: [ 493.722394] modules linked in: expdev(ox+) rfcomm bnep bluetooth nvidia(pox) snd_hda_codec_hdmi joydev snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm coretemp snd_page_alloc snd_seq_midi snd_seq_midi_event snd_rawmidi gpio_ich kvm snd_seq snd_seq_device drm dcdbas snd_timer lpc_ich snd soundcore shpchp serio_raw ppdev i82975x_edac lp parport_pc edac_core parport mac_hid hid_generic usbhid hid psmouse ahci tg3 libahci ptp pps_core pata_acpi kernel: [ 493.722429] cpu: 0 pid: 3542 comm: insmod tainted: p ox 3.13.0-79-generic #123-ubuntu kernel: [ 493.722431] hardware name: dell inc. precision workstation 390 /0dn075, bios 2.3.0 05/01/2007 kernel: [ 493.722434] task: ffff8800549c3000 ti: ffff8800555e6000 task.ti: ffff8800555e6000 kernel: [ 493.722436] rip: 0010:[<ffffffff8137aca8>] [<ffffffff8137aca8>] iowrite16+0x38/0x40 kernel: [ 493.722440] rsp: 0018:ffff8800555e7b88 eflags: 00010212 kernel: [ 493.722442] rax: 00000000eb000000 rbx: ffff88007c2b4000 rcx: 0000000000000000 kernel: [ 493.722444] rdx: 00000000eb060000 rsi: 00000000eb060000 rdi: 00000000000000aa kernel: [ 493.722446] rbp: ffff8800555e7bb0 r08: 00000000ebffffff r09: 00000000ffffffec kernel: [ 493.722448] r10: 0000000000003692 r11: 0000000000000000 r12: 00000000eb060000 kernel: [ 493.722450] r13: ffff88007c2b4098 r14: ffff88007c2b4098 r15: ffffffffa022b140 kernel: [ 493.722452] fs: 00007fa8053ef740(0000) gs:ffff88007f800000(0000) knlgs:0000000000000000 kernel: [ 493.722454] cs: 0010 ds: 0000 es: 0000 cr0: 000000008005003b kernel: [ 493.722456] cr2: 00000000eb060000 cr3: 000000005a74b000 cr4: 00000000000007f0 kernel: [ 493.722458] stack: kernel: [ 493.722460] ffffffffa02291c4 00aa88007c2b4000 ffff88007c2b4000 0000000000000000 kernel: [ 493.722464] ffffffffa022b000 ffff8800555e7be8 ffffffff813ac8a5 ffffffff813adb45 kernel: [ 493.722467] ffff88007c2b4098 ffffffffffffffff ffff88007c2b4000 0000000000000017 kernel: [ 493.722471] call trace: kernel: [ 493.722477] [<ffffffffa02291c4>] ? _pci_probe+0x114/0x215 [expdev] kernel: [ 493.722481] [<ffffffff813ac8a5>] local_pci_probe+0x45/0xa0 kernel: [ 493.722484] [<ffffffff813adb45>] ? pci_match_device+0xc5/0xd0 kernel: [ 493.722487] [<ffffffff813adc69>] pci_device_probe+0xd9/0x130 kernel: [ 493.722492] [<ffffffff8149a4bd>] driver_probe_device+0x12d/0x3e0 kernel: [ 493.722495] [<ffffffff8149a843>] __driver_attach+0x93/0xa0 kernel: [ 493.722498] [<ffffffff8149a7b0>] ? __device_attach+0x40/0x40 kernel: [ 493.722501] [<ffffffff81498403>] bus_for_each_dev+0x63/0xa0 kernel: [ 493.722504] [<ffffffff81499e6e>] driver_attach+0x1e/0x20 kernel: [ 493.722507] [<ffffffff81499a50>] bus_add_driver+0x180/0x250 kernel: [ 493.722510] [<ffffffffa0005000>] ? 0xffffffffa0004fff kernel: [ 493.722514] [<ffffffff8149aec4>] driver_register+0x64/0xf0 kernel: [ 493.722517] [<ffffffffa0005000>] ? 0xffffffffa0004fff kernel: [ 493.722520] [<ffffffff813ac23c>] __pci_register_driver+0x4c/0x50 kernel: [ 493.722523] [<ffffffffa000502c>] _module_init+0x2c/0x1000 [expdev] kernel: [ 493.722528] [<ffffffff8100214a>] do_one_initcall+0xfa/0x1b0 kernel: [ 493.722532] [<ffffffff810598f3>] ? set_memory_nx+0x43/0x50 kernel: [ 493.722536] [<ffffffff810e2b7d>] load_module+0x12ed/0x1b50 kernel: [ 493.722540] [<ffffffff810de5f0>] ? store_uevent+0x40/0x40 kernel: [ 493.722544] [<ffffffff810e3556>] sys_finit_module+0x86/0xb0 kernel: [ 493.722548] [<ffffffff817363dd>] system_call_fastpath+0x1a/0x1f kernel: [ 493.722550] code: 81 fe 00 00 01 00 76 0b 0f b7 d6 89 f8 66 ef c3 0f 1f 00 55 48 c7 c6 b0 10 a9 81 48 89 d7 48 89 e5 e8 5d fe ff ff 5d c3 0f 1f 00 <66> 89 3e c3 0f 1f 40 00 48 81 fe ff ff 03 00 48 89 f2 77 2c 48 kernel: [ 493.722583] rip [<ffffffff8137aca8>] iowrite16+0x38/0x40 kernel: [ 493.722586] rsp <ffff8800555e7b88> kernel: [ 493.722588] cr2: 00000000eb060000 kernel: [ 493.722591] ---[ end trace 2d3dfa92998d58a7 ]---
according ian abbott tried approach successfully. don't understand mechanism behind works now. bar2 memory register type. approach uses ioremap
, not memory-mapping. how access bar2 via memory-mapping?
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> module_license("gpl"); module_author("alex"); module_description("test module."); module_version("0.1"); #define dev_pci_vendorid 0x10b5 #define dev_pci_deviceid 0x1860 static struct pci_device_id pci_drvidtable[] = { { .vendor = dev_pci_vendorid, // vendor id .device = dev_pci_deviceid, // device id .subvendor = pci_any_id, // no subsystem available .subdevice = pci_any_id, // no subsystem available .class = pci_class_not_defined, // no device class .class_mask = 0, // no device class .driver_data = 0 // no private data driver }, { 0, } // end of table }; struct pci_data { // struct pci_dev *pci_dev; /// io mapping pci config space uint32_t *pciconfigaddr; uint32_t *pcib2addr; wait_queue_head_t waitq; uint8_t flag; } *data; static int _pci_probe ( struct pci_dev *pdev, const struct pci_device_id *ent ) { int ret = 0; int i; u16 reg_16; unsigned long *pbas2addr; data = kzalloc( sizeof(*data) , gfp_kernel ); if( !data ) { printk(kern_err "failed allocate memory.\n"); return -enomem; } pci_set_drvdata(pdev, data); // enabling device ret = pci_enable_device(pdev); if( ret ) { printk(kern_err "failed enable pci device.\n"); goto no_enable; } pci_read_config_word(pdev,0,®_16); printk(kern_info "vendorid. %x\n",reg_16); // checking if pci-device reachable checking bar0 defined , // memory mapped if( !(pci_resource_flags(pdev,0) & ioresource_mem) ) { printk(kern_err "incorrect bar configuration.\n"); ret = -enodev; goto bad_bar; } // taking ownership of memory region pbas2addr = pci_ioremap_bar(pdev, 2); // void iowrite8(u8 val, void __iomem *addr) ( = 0x060000; i<0x070000; i++ ) { iowrite8( 0x11 , pbas2addr+i ); } // further read/write function in kernel: // inp, readl, readw, readb, ioread8, ioread16, ioread32 // outp, writel, writew, writeb, iowrite8, iowrite16, iowrite32 bad_bar: pci_disable_device(pdev); no_enable: pci_set_drvdata(pdev, data); return ret; } static void _pci_remove( struct pci_dev *pdev ) { pci_disable_device(pdev); printk(kern_info "pci-device removed.\n"); } static struct pci_driver pci_drv = { .name = "expdev", .id_table = pci_drvidtable, .probe = _pci_probe, .remove = _pci_remove, }; // module related functions /////////////////////////////////////////////////// static int __init _module_init(void){ printk(kern_info "hello!\n"); pci_register_driver(&pci_drv); return 0; } static void __exit _module_exit(void){ pci_unregister_driver(&pci_drv); printk(kern_info "goodbye!\n"); } module_init(_module_init); module_exit(_module_exit);
i'm @ end. think have follow docs doesn't work expected.
here code:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/delay.h> module_license("gpl"); module_author("alex"); module_description("test module."); module_version("0.1"); #define dev_pci_vendorid 0x10b5 #define dev_pci_deviceid 0x1860 static struct pci_device_id pci_drvidtable[] = { { .vendor = dev_pci_vendorid, // vendor id .device = dev_pci_deviceid, // device id .subvendor = pci_any_id, // no subsystem available .subdevice = pci_any_id, // no subsystem available .class = pci_class_not_defined, // no device class .class_mask = 0, // no device class .driver_data = 0 // no private data driver }, { 0, } }; static int _pci_probe ( struct pci_dev *pdev, const struct pci_device_id *ent ) { int ret = 0; int i; unsigned long *pbas2addr; // enabling device ret = pci_enable_device(pdev); if( ret ) { printk(kern_err "failed enable pci device.\n"); goto no_enable; } pci_request_regions(pdev, "expdev"); // checking if pci-device reachable checking bar0 defined , // memory mapped if( !(pci_resource_flags(pdev,0) & ioresource_mem) ) { printk(kern_err "incorrect bar configuration.\n"); ret = -enodev; goto bad_bar; } // taking ownership of memory region pbas2addr = pci_ioremap_bar(pdev, 2); printk(kern_info "bar2: %p\n",pbas2addr); ( = 0x060000; i<0x070000; i++ ) { iowrite8( 0x00 , pbas2addr+i ); } // next write operations cause crashing the module // load control word set icd in set-up-mode iowrite32(0b01111000000101, pbas2addr+0x200014); // load bit-stuffed set word iowrite32(0b10110001001001101110000, pbas2addr+0x200018); // 39.5 mhz // load control word set icd in set-up-mode iowrite32(0b01111000000100, pbas2addr+0x200014); msleep(10); // load control word set icd in set-up-mode iowrite32(0b01111000000000, pbas2addr+0x200014); return 0; bad_bar: pci_disable_device(pdev); return ret; } static void _pci_remove( struct pci_dev *pdev ) { pci_release_regions(pdev); pci_disable_device(pdev); printk(kern_info "pci-device removed.\n"); } static struct pci_driver pci_drv = { .name = "expdev", .id_table = pci_drvidtable, .probe = _pci_probe, .remove = _pci_remove, }; // module related functions static int __init _module_init(void){ printk(kern_info "hello!\n"); pci_register_driver(&pci_drv); return 0; } static void __exit _module_exit(void){ pci_unregister_driver(&pci_drv); printk(kern_info "goodbye!\n"); } module_init(_module_init); module_exit(_module_exit);
with for-loop:
kernel: [ 467.545079] hello! kernel: [ 467.545136] expdev 0000:05:02.0: enabling device (0000 -> 0003) kernel: [ 467.546807] bar2: ffffc90006c00000 kernel: [ 467.562146] pci-device removed. kernel: [ 467.562489] goodbye!
and can see outputs on device gpio.
if write higher addresses needed regarding device manual lkm crashes:
kernel: [ 1324.591578] hello! kernel: [ 1324.593300] bar2: ffffc90007c80000 kernel: [ 1324.605162] bug: unable handle kernel paging request @ ffffc90008c800a0 kernel: [ 1324.605168] ip: [<ffffffff8137ace8>] iowrite32+0x38/0x40 kernel: [ 1324.605175] pgd 7d00d067 pud 7d00e067 pmd 611e7067 pte 0 kernel: [ 1324.605179] oops: 0002 [#1] smp kernel: [ 1324.605183] modules linked in: expdev(ox+) rfcomm bnep bluetooth nvidia(pox) snd_hda_codec_hdmi joydev snd_hda_codec_idt snd_hda_intel snd_hda_codec gpio_ich coretemp drm snd_seq_midi kvm snd_seq_midi_event dcdbas snd_rawmidi snd_hwdep lpc_ich snd_seq snd_pcm snd_seq_device snd_page_alloc shpchp ppdev serio_raw snd_timer lp snd soundcore mac_hid i82975x_edac edac_core parport_pc parport hid_generic usbhid hid psmouse ahci libahci pata_acpi tg3 ptp pps_core [last unloaded: expdev] kernel: [ 1324.605219] cpu: 0 pid: 3155 comm: insmod tainted: p ox 3.13.0-79-generic #123-ubuntu kernel: [ 1324.605221] hardware name: dell inc. precision workstation 390 /0dn075, bios 2.3.0 05/01/2007 kernel: [ 1324.605224] task: ffff88007c048000 ti: ffff880061122000 task.ti: ffff880061122000 kernel: [ 1324.605226] rip: 0010:[<ffffffff8137ace8>] [<ffffffff8137ace8>] iowrite32+0x38/0x40 kernel: [ 1324.605229] rsp: 0018:ffff880061123b90 eflags: 00010292 kernel: [ 1324.605231] rax: 0000000000000016 rbx: ffffc90008c800a0 rcx: 0000000000000000 kernel: [ 1324.605233] rdx: ffffc90008c800a0 rsi: ffffc90008c800a0 rdi: 0000000000001e05 kernel: [ 1324.605235] rbp: ffff880061123bb0 r08: 0000000000000096 r09: 0000000000000306 kernel: [ 1324.605237] r10: 0000000000000000 r11: ffff8800611238c6 r12: ffffc90007f80000 kernel: [ 1324.605239] r13: ffffc90007c80000 r14: ffff88007c2b4098 r15: ffffffffa01fc140 kernel: [ 1324.605242] fs: 00007fc6802cb740(0000) gs:ffff88007f800000(0000) knlgs:0000000000000000 kernel: [ 1324.605244] cs: 0010 ds: 0000 es: 0000 cr0: 0000000080050033 kernel: [ 1324.605246] cr2: ffffc90008c800a0 cr3: 0000000062f96000 cr4: 00000000000007f0 kernel: [ 1324.605248] stack: kernel: [ 1324.605249] ffffffffa01fa0ec ffff88007c2b4000 0000000000000000 ffffffffa01fc000 kernel: [ 1324.605253] ffff880061123be8 ffffffff813ac8a5 ffffffff813adb45 ffff88007c2b4098 kernel: [ 1324.605257] ffffffffffffffff ffff88007c2b4000 0000000000000018 ffff880061123c30 kernel: [ 1324.605260] call trace: kernel: [ 1324.605267] [<ffffffffa01fa0ec>] ? _pci_probe+0xbc/0x110 [expdev] kernel: [ 1324.605271] [<ffffffff813ac8a5>] local_pci_probe+0x45/0xa0 kernel: [ 1324.605274] [<ffffffff813adb45>] ? pci_match_device+0xc5/0xd0 kernel: [ 1324.605277] [<ffffffff813adc69>] pci_device_probe+0xd9/0x130 kernel: [ 1324.605281] [<ffffffff8149a4bd>] driver_probe_device+0x12d/0x3e0 kernel: [ 1324.605285] [<ffffffff8149a843>] __driver_attach+0x93/0xa0 kernel: [ 1324.605288] [<ffffffff8149a7b0>] ? __device_attach+0x40/0x40 kernel: [ 1324.605290] [<ffffffff81498403>] bus_for_each_dev+0x63/0xa0 kernel: [ 1324.605293] [<ffffffff81499e6e>] driver_attach+0x1e/0x20 kernel: [ 1324.605296] [<ffffffff81499a50>] bus_add_driver+0x180/0x250 kernel: [ 1324.605300] [<ffffffffa0006000>] ? 0xffffffffa0005fff kernel: [ 1324.605303] [<ffffffff8149aec4>] driver_register+0x64/0xf0 kernel: [ 1324.605306] [<ffffffffa0006000>] ? 0xffffffffa0005fff kernel: [ 1324.605309] [<ffffffff813ac23c>] __pci_register_driver+0x4c/0x50 kernel: [ 1324.605313] [<ffffffffa000602c>] _module_init+0x2c/0x1000 [expdev] kernel: [ 1324.605317] [<ffffffff8100214a>] do_one_initcall+0xfa/0x1b0 kernel: [ 1324.605321] [<ffffffff810598f3>] ? set_memory_nx+0x43/0x50 kernel: [ 1324.605326] [<ffffffff810e2b7d>] load_module+0x12ed/0x1b50 kernel: [ 1324.605330] [<ffffffff810de5f0>] ? store_uevent+0x40/0x40 kernel: [ 1324.605334] [<ffffffff810e3556>] sys_finit_module+0x86/0xb0 kernel: [ 1324.605338] [<ffffffff817363dd>] system_call_fastpath+0x1a/0x1f kernel: [ 1324.605340] code: 81 fe 00 00 01 00 76 0b 0f b7 d6 89 f8 ef c3 0f 1f 40 00 55 48 c7 c6 bf 10 a9 81 48 89 d7 48 89 e5 e8 1d fe ff ff 5d c3 0f 1f 00 <89> 3e c3 0f 1f 44 00 00 48 81 ff ff ff 03 00 77 37 48 81 ff 00 kernel: [ 1324.605373] rip [<ffffffff8137ace8>] iowrite32+0x38/0x40 kernel: [ 1324.605376] rsp <ffff880061123b90> kernel: [ 1324.605378] cr2: ffffc90008c800a0 kernel: [ 1324.605381] ---[ end trace 9b1029fd3f919791 ]---
rip - why. offset within limits of 16 mb.
Comments
Post a Comment