Thursday, February 28, 2013

Adding a simple io device to gem5

Last time, I added custom pseudo-instructions in gem5. Today, I add a device in gem5 and then use the device from within a simulated (linux-x86_64) system.

Adding a device to gem5 is lightly documented in the ASPLOS tutorial and gem5 wiki. I would suggest starting with the tutorial, and read about the memory system as well.

Devices are located in gem5/src/dev/ subtree, with architecture-specific files located in subdirectories. The IsaFake device, which I found before the ASPLOS tutorial, was useful for starting. To create a simple device, I copied isa_fake.[cc|hh] to mydev.[cc|hh], and copied BadDevice.py to MyDevice.py. Then I copied the parameters for IsaFake from Device.py into the parameters of MyDevice.py, and added mydev.cc and MyDevice.py to the SConscript. After renaming (search-replace IsaFake/BadDevice with MyDevice, isa_fake with mydev, etc), I needed to add the device to the system. I'm working with x86, so I attached it in the x86/Pc.py file, with:

from MyDevice import MyDevice
...
    my_device = MyDevice(pio_addr=x86IOAddress(0xe000), pio_size=8)
...
        self.fake_floppy.pio = bus.master
        self.my_device.pio = bus.master
        self.pciconfig.pio = bus.default
...

After compiling and running gem5 the device is listed in the m5out/config.ini file.

Accessing the device requires a device driver. To learn about writing drivers, read a good book. For this driver, a simple kernel module will do.
#include <linux kernel.h>
#include <linux module.h>
#include <linux errno.h>
#include <linux ioport.h>
#include <asm io.h>

#define BASE 0xe000
#define SIZE 0x08

int init_module(void)
{
  int t1;
  if ( ! request_region(BASE, SIZE, "mydev") ) {
    printk( KERN_INFO "unable to get io port at 0x%8X\n", BASE );
    return -ENODEV;
  }

  /* a little test */
  t1 = inl(BASE);
  printk( KERN_INFO "read %d\n", t1 );

  outl(0, BASE);
  t1 = inl(BASE);
  printk( KERN_INFO "read %d\n", t1 );
  return 0;
}

void cleanup_module(void)
{
  release_region(BASE, SIZE);
}

Compile the module against the Linux kernel, boot gem5, get the module into the simulated system (e.g. with m5 readfile), and insert the module. With the default parameters from the IsaFake device, the write is ignored and the device returns -1 whenever it is read.

I did not get I/O memory working, but for now I/O ports are fine for me.

16 comments:

  1. Hi Gedare , Thanks for such a nice blog. I was wondering if it's possible to combine McPat (a power tool) with GEM5. I would like to simulate power aware dynamic cache resizing using GEM5. Do you have any idea on which file I have to work.Thanks

    ReplyDelete
  2. Nil, I'm not sure. You'd have to dig into gem5 to figure that out. If McPat can read the trace output of gem5 then that could probably give a way to get power numbers.

    ReplyDelete
  3. Hi I have been trying to follow this tutorial. On building the system without your changes an Isa_fake.hh is produced in the build/X86/params folder. However after your changes the my_dev.hh file is not produced in a similar fashion. What am I missing?

    ReplyDelete
  4. Well I solved it actually. you need to change the #include params/IsaFake to params/myDevice.hh as in the name of your class. Similarly with the debug/myDevice.hh...

    You can delete both these comments or Edit them if you think they are redundant, as I think they are ;)

    ReplyDelete
  5. Glad you fixed it. I know there are a few places to make updates during the copy-paste-rename phase. Better to leave your comments in case others find the same problem! :)

    ReplyDelete
  6. Hi,

    When you say get the module into the simulated system, how would I go about doing that? What file would I be inputting?

    ReplyDelete
    Replies
    1. You can provide a file with the --script argument to fs.py, and then 'm5 readfile' will copy that file to stdout. Redirect it to a file in the shell. So something like... 'fs.py --script="myfile.txt"' and then in m5term something like 'm5 readfile > myfile.txt'

      Delete
  7. Hi Gedare,

    how did you manged to compile your kernel-module? As far as i see, there is no /lib/module folder contained in the default image provided by gem5. Therefore, i can't compile the kernel module. Can you give me a hint to handle this issue?

    Best regards

    ReplyDelete
    Replies
    1. Hi Björn, I compiled the Linux kernel first. I used version 2.6.28.4 and the config file provided by the gem5 maintainers. Once you have compiled the kernel, you can compile a module for it.

      Delete
    2. Hi Gedare,
      I want to add a new io device in my gem5 simulator and i follow your article, and i can compile my kernel with gem5 config file but i can't compile a module for it, please take me some more hints , i'm trying so hard but i'm new in linux and these concepts.
      thanks for your attention

      Delete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Hello Gedare, this tutorial is very helpful!! I manage to attach MyDevice and it works properly using X86. However, I want to attach the same device using ARM architecture in GEM5. I attach the MyDevice to /arm/Realview.py with similar way with Pl050 keyboard but the problem is that i get the following error: Unable to handle kernel paging request at virtual address c400e000. May you help me please??

    Thank you in advance!

    ReplyDelete
    Replies
    1. You have to put the device in a proper IO address for the ARM target. I don't off-hand know what that might be. On ARM, you might try to hook off the PCI-e..

      Delete
  10. Hi Gedare,
    can you guide me for using the UART device in gem5 configuration. in fact, I am looking for device to give me uart for fully communication with gem5 full system simulator.
    thanks

    ReplyDelete
  11. Hi Gedare,
    I am working on gem5 and I want to know how to find the address range of an application execution in gem5. secondly if i want to modify the cache architecture of gem5, how can i do that. any help will be appreciated.

    ReplyDelete
  12. Hi Gedare, I am working on adding a Pci device based on your example to Pc.py. I am getting an error "AssertionError: SimObject Pc already present". I don't know what's causing the error. Did you get this error and how did you get past it?
    BTW, I get this error also with Cmos.py, just running it without change and the assertion SimObject Cmos already present also exists.

    ReplyDelete