LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 09-07-2011, 04:43 AM   #1
leechaotang
LQ Newbie
 
Registered: Aug 2011
Posts: 10

Rep: Reputation: Disabled
How to emulate a PCI device in Linux


Hi,

I want to emulate a PCI express device in Linux, how should I do it?

i.e. there is no real hardware PCI express in system, but I want Linux to act as there is a
PCI express device there. How to do it?

Thanks!

Mark
 
Old 09-07-2011, 01:18 PM   #2
frieza
Senior Member
 
Registered: Feb 2002
Location: harvard, il
Distribution: Ubuntu 11.4,DD-WRT micro plus ssh,lfs-6.6,Fedora 15,Fedora 16
Posts: 3,233

Rep: Reputation: 406Reputation: 406Reputation: 406Reputation: 406Reputation: 406
first of all, what kind of device are you trying to emulate and for what purpose?
i've never tried doing this myself but i would start by looking at how other hardware device drivers access hardware as well as download a few emulators such as qemu to figure out how they emulate hardware, learn how to write a kernel module that emulates the hardware device and produces a device node in /dev
but how you do it depends on what you are doing and your purpose.
 
Old 09-10-2011, 05:38 AM   #3
robvoo
LQ Newbie
 
Registered: Jul 2009
Distribution: debian, ubuntu
Posts: 22

Rep: Reputation: 2
Hi frieza,

You should first think about the following, how do you want to interface to your PCI device?
It is possible to create a stub driver which you can access with device operations like
(read, write, mmap, ioctls) from user space.

Don't know if it is possible to emulate a real pci device with a kernel module
because this is handled by the PCI subsystem.

What is the purpose of the simulated device?

Regards Rob
 
Old 09-16-2011, 02:40 AM   #4
osmiy
LQ Newbie
 
Registered: Sep 2011
Distribution: ArchLinux, OpenWRT
Posts: 1

Rep: Reputation: Disabled
Lightbulb Try to create dummy PCI bus.

As far as I tried, the simplest way is to create the dummy PCI bus with custom read/write handlers.

See the `pci_scan_bus` usage.

I tried that code for x86 platform.

Code:
   #define MY_PCI_DOMAIN_NUM 0x0001
   #define MY_PCI_BUS_NUM 0x00

   struct pci_bus my_pci_bus = NULL;
   struct pci_sysdata my_pci_sd;

   memset (&my_pci_sd, 0 sizeof (my_pci_sd));
   my_pci_sd.domain = MY_PCI_DOMAIN_NUM;
   my_pci_sd.node = -1;

   memset (&my_pci_ops, 0, sizeof (my_pci_ops));
   my_pci_ops.read = my_pci_read;
   my_pci_ops.write = my_pci_write;

   my_pci_bus = pci_scan_bus(MY_PCI_BUS_NUM, &my_pci_ops, NULL);

   if (my_pci_bus)
   {
      printk (KERN_INFO "Successfully created MY PCI bus");
   }
You should implement the `my_pci_read` and `my_pci_write` to emulate PCI device responses, according to the PCI standard.

I'm not sure that is right solution, but it works on my side.
 
Old 03-18-2015, 05:34 AM   #5
neel.basu
LQ Newbie
 
Registered: Mar 2015
Posts: 1

Rep: Reputation: Disabled
I know the thread is old. But I have to create a fake PCI device with custom read/write function. I am trying to replicate this example and hitting errors. Can you please post an working demo ?

I was getting compilation errors on
Code:
struct pci_bus my_pci_bus = NULL;
so I changed that to
Code:
struct pci_bus my_pci_bus = {};
This is my current code

Code:
#define MY_PCI_DOMAIN_NUM 0x0001
#define MY_PCI_BUS_NUM 0x00

#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>

int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val){
  return 0;
}
int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val){
  return 0;
}

struct pci_ops my_pci_ops = {};

int pci_bus_match(struct device *dev, struct device_driver *drv){
  return 0;
}

struct bus_type pci_bus_type = {
       name:	"pci",
       match:	pci_bus_match,
};

extern struct bus_type pci_bus_type;

MODULE_LICENSE("Dual BSD/GPL");

struct pci_bus my_pci_bus = {};
struct pci_sysdata my_pci_sd;
// 
// memset (&my_pci_sd, 0 sizeof (my_pci_sd));
// my_pci_sd.domain = MY_PCI_DOMAIN_NUM;
// my_pci_sd.node = -1;
// 


static int hello_init(void){
    struct pci_bus* my_pci_bus;
    
    printk(KERN_ALERT "Hello, world\n");
    memset (&my_pci_ops, 0, sizeof (my_pci_ops));
    my_pci_ops.read = pci_read;
    my_pci_ops.write = pci_write;
    
    my_pci_bus = pci_scan_bus(MY_PCI_BUS_NUM, &my_pci_ops, NULL);
    if(my_pci_bus){
      printk(KERN_INFO "Successfully created MY PCI bus");
    }
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);
after I do `sudo insmod pci` I don not get any new device in lspci. and dmesg is full of traces

Code:
[15516.161020] BUG: unable to handle kernel NULL pointer dereference at           (null)
[15516.164054] IP: [<ffffffff813ba983>] pci_create_root_bus+0x73/0x440
[15516.165495] PGD 106bc6067 PUD 1230ed067 PMD 0 
[15516.166922] Oops: 0000 [#1] SMP 
[15516.168340] Modules linked in: pci(OE+) cdc_acm uas usb_storage vhost_net vhost macvtap macvlan fuse ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack xt_CHECKSUM iptable_mangle tun bridge stp llc ip6table_filter ip6_tables ebtable_nat ebtables bnep bluetooth vfat fat uvcvideo videobuf2_vmalloc videobuf2_core videobuf2_memops v4l2_common videodev media rtsx_pci_ms memstick rtsx_pci_sdmmc mmc_core kvm_amd kvm hp_wmi sparse_keymap crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel arc4 rt2800pci rt2800mmio rt2800lib rt2x00pci rt2x00mmio rt2x00lib hp_accel eeprom_93cx6 lis3lv02d mac80211 input_polldev cfg80211 crc_ccitt microcode joydev serio_raw k10temp snd_hda_codec_idt snd_hda_codec_generic rtsx_pci mfd_core
[15516.169995]  video
[15516.169996]  snd_hda_codec_hdmi
[15516.169996]  snd_hda_intel
[15516.169997]  snd_hda_controller
[15516.169998]  snd_hda_codec
[15516.169999]  snd_hwdep
[15516.169999]  snd_seq
[15516.170000]  snd_seq_device
[15516.170001]  snd_pcm
[15516.170001]  rfkill
[15516.170002]  i2c_piix4
[15516.170003]  acpi_cpufreq
[15516.170003]  snd_timer
[15516.170004]  snd
[15516.170006]  soundcore
[15516.170007]  shpchp
[15516.170008]  wmi
[15516.170008]  hp_wireless
[15516.170009]  binfmt_misc
[15516.170010]  nfsd
[15516.170010]  auth_rpcgss
[15516.170011]  nfs_acl
[15516.170012]  lockd
[15516.170013]  grace
[15516.170014]  sunrpc
[15516.170014]  radeon
[15516.170015]  r8169
[15516.170016]  mii
[15516.170017]  i2c_algo_bit
[15516.170018]  drm_kms_helper
[15516.170018]  ttm
[15516.170019]  drm
[15516.170020]  [last unloaded: hello_printk]

[15516.170024] CPU: 3 PID: 1738 Comm: insmod Tainted: G           OE  3.18.7-100.fc20.x86_64 #1
[15516.170026] Hardware name: Hewlett-Packard HP Pavilion g6 Notebook PC/184A, BIOS F.26 02/21/2013
[15516.170028] task: ffff88014ada6220 ti: ffff880103854000 task.ti: ffff880103854000
[15516.170030] RIP: 0010:[<ffffffff813ba983>] 
[15516.170033]  [<ffffffff813ba983>] pci_create_root_bus+0x73/0x440
[15516.170035] RSP: 0018:ffff880103857bf8  EFLAGS: 00010286
[15516.170037] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[15516.170038] RDX: ffff88000ffaf870 RSI: 0000000000000000 RDI: ffff88000ffafc00
[15516.170039] RBP: ffff880103857c98 R08: 0000000000000000 R09: ffff8801a8801500
[15516.170040] R10: 000000000ffaf801 R11: ffff8801038579ce R12: ffff88000ffaf800
[15516.170041] R13: 0000000000000000 R14: ffffffffa0851710 R15: 0000000000000000
[15516.170044] FS:  00007f1bc7f75740(0000) GS:ffff8801aed80000(0000) knlGS:00000000f45ffb40
[15516.170045] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[15516.170046] CR2: 0000000000000000 CR3: 0000000133833000 CR4: 00000000000407e0
[15516.170048] Stack:
[15516.170048]  000000000000000c
[15516.170050]  0000000000000006
[15516.170050]  ffff880103857c88
[15516.170051]  ffff880103857cb0

[15516.170052]  ffff8801a8801c00
[15516.170053]  ffffffff813b8131
[15516.170054]  ffff880057c68920
[15516.170054]  ffff880103857cb0

[15516.170056]  ffffffff81cac360
[15516.170056]  ffff880103857cb0
[15516.170057]  ffffffff81cac360
[15516.170057]  0000000000000000

[15516.170059] Call Trace:

[15516.170065]  [<ffffffff813b8131>] ? pci_add_resource_offset+0x31/0x70

[15516.170071]  [<ffffffff813bb7c8>] pci_scan_bus+0x78/0xc0

[15516.170075]  [<ffffffffa084f030>] ? pci_bus_match+0x10/0x10 [pci]

[15516.170079]  [<ffffffffa084f06d>] hello_init+0x3d/0x60 [pci]

[15516.170083]  [<ffffffff81002144>] do_one_initcall+0xd4/0x210

[15516.170088]  [<ffffffff811cf192>] ? __vunmap+0xc2/0x110

[15516.170093]  [<ffffffff811152ab>] load_module+0x1cab/0x2730

[15516.170096]  [<ffffffff81110f00>] ? store_uevent+0x70/0x70

[15516.170101]  [<ffffffff8120ef70>] ? kernel_read+0x50/0x80

[15516.170106]  [<ffffffff81115ee6>] SyS_finit_module+0xa6/0xd0

[15516.170112]  [<ffffffff8174cfa9>] system_call_fastpath+0x12/0x17
[15516.170114] Code: 
[15516.170115] c4 
[15516.170115] 0f 
[15516.170116] 84 
[15516.170116] 21 
[15516.170117] 03 
[15516.170118] 00 
[15516.170118] 00 
[15516.170119] 4c 
[15516.170119] 89 
[15516.170120] a8 
[15516.170120] c8 
[15516.170121] 00 
[15516.170121] 00 
[15516.170122] 00 
[15516.170122] 4c 
[15516.170123] 89 
[15516.170123] b0 
[15516.170124] b8 
[15516.170124] 00 
[15516.170125] 00 
[15516.170126] 00 
[15516.170126] 49 
[15516.170127] 63 
[15516.170127] c7 
[15516.170128] 49 
[15516.170128] 89 
[15516.170129] 84 
[15516.170129] 24 
[15516.170130] 80 
[15516.170130] 00 
[15516.170131] 00 
[15516.170132] 00 
[15516.170132] 41 
[15516.170133] 88 
[15516.170133] 84 
[15516.170134] 24 
[15516.170134] d8 
[15516.170135] 00 
[15516.170135] 00 
[15516.170136] 00 
[15516.170136] 44 
[15516.170137] 89 
[15516.170137] fe 
[15516.170138] <41> 
[15516.170139] 8b 
[15516.170139] 7d 
[15516.170140] 00 
[15516.170140] e8 
[15516.170141] b4 
[15516.170141] 8a 
[15516.170142] 00 
[15516.170142] 00 
[15516.170143] 48 
[15516.170144] 85 
[15516.170144] c0 
[15516.170145] 74 
[15516.170145] 3f 
[15516.170146] f6 
[15516.170146] 05 
[15516.170147] ba 
[15516.170147] cc 
[15516.170148] 94 
[15516.170148] 00 
[15516.170149] 04 

[15516.170150] RIP 
[15516.170153]  [<ffffffff813ba983>] pci_create_root_bus+0x73/0x440
[15516.170154]  RSP <ffff880103857bf8>
[15516.170155] CR2: 0000000000000000
[15516.179558] ---[ end trace d99a70d9357a4b3b ]---
Thank You

Last edited by neel.basu; 03-18-2015 at 06:16 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
No connection wireless PCI device in Linux Suse 11.1 J.Scholten Linux - Wireless Networking 1 07-09-2009 09:55 AM
Is there a way to emulate a usb device? mriedel Linux - Software 4 04-23-2009 10:03 AM
What is the Linux difference between PCIE and PCI device driver? jbreaka4lyfe Linux - General 0 06-04-2008 02:54 PM
Emulate/simulate an USB (or COM) device Adony Linux - Software 4 04-15-2007 03:51 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 02:06 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration