Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1361089
  • 博文数量: 343
  • 博客积分: 13098
  • 博客等级: 上将
  • 技术积分: 2862
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-06 00:35
文章存档

2012年(131)

2011年(31)

2010年(53)

2009年(23)

2008年(62)

2007年(2)

2006年(36)

2005年(5)

分类: 虚拟化

2012-05-13 00:46:27

Backend Driver

The following is a simple example which shows how to add a new device and trigger the probe() function of a backend driver using xenstore-write tool. This is relevant for Xen 3.1

 

Currently in Xen, triggering of the probe() method in a backend driver or a frontend driver is done by writing some values to the xenstore into directories where the xenbus poses watches. This writing to the xenstore is currently done in Xen from the python code, and it is wrapped deep inside the xend and/or xm commands. Eventually it is done in the writeDetails method of the class. (And both blkif and netif use it).

For those who want who want to be able to trigger the probe() function without diving too deeply into the python code, this should suffice.

For the purposes of this little tutorial, let's assume that you have built and installed Xen 3.1 from source and have used it to fire up a guest domain at least once. After you've done that, let's say we want to add new device. We will add a device named "mydevice". Let's begin with the backend. For this purpose, we will add a directory named "deviceback" to linux-2.6-sparse/drivers/xen. This directory will store the backend portion of our driver.

First, create linux-2.6-sparse/drivers/xen/deviceback. Next, add the following three files to that directory: deviceback.c, xenbus.c, common.h and Makefile.

 

Here is a minimal skeleton implementation of these files:

deviceback.c

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include "common.h"
  3. static int __init deviceback_init(void)
  4. {
  5.         device_xenbus_init();
  6. }
  7. static void deviceback_cleanup()
  8. {
  9. }
  10. module_init(deviceback_init);
  11. module_exit(deviceback_cleanup);

xenbus.c

点击(此处)折叠或打开

  1. #include <xen/xenbus.h>
  2. #include <linux/module.h>
  3. #include <linux/slab.h>
  4. struct backendinfo
  5. {
  6.         struct xenbus_device* dev;
  7.         long int frontend_id;
  8.         struct xenbus_watch backend_watch;
  9.         struct xenbus_watch watch;
  10.         char* frontpath;
  11. };
  12. //////////////////////////////////////////////////////////////////////////////
  13. static int device_probe(struct xenbus_device* dev,
  14.                         const struct xenbus_device_id* id)
  15. {
  16.         struct backendinfo* be;
  17.         char* frontend;
  18.         int err;
  19.         be = kmalloc(sizeof(*be),GFP_KERNEL);
  20.         memset(be,0,sizeof(*be));
  21.         be->dev = dev;
  22.         printk("Probe fired!\n");
  23.         return 0;
  24. }
  25. //////////////////////////////////////////////////////////////////////////////
  26. static int device_uevent(struct xenbus_device* xdev,
  27.                           char** envp, int num_envp,
  28.                           char* buffer, int buffer_size)
  29. {
  30.         return 0;
  31. }
  32. static int device_remove(struct xenbus_device* dev)
  33. {
  34.         return 0;
  35. }
  36. //////////////////////////////////////////////////////////////////////////////
  37. static struct xenbus_device_id device_ids[] =
  38. {
  39.         { "mydevice" },
  40.         { "" }
  41. };
  42. //////////////////////////////////////////////////////////////////////////////
  43. static struct xenbus_driver deviceback =
  44. {
  45.         .name = "mydevice",
  46.         .owner = THIS_MODULE,
  47.         .ids = device_ids,
  48.         .probe = device_probe,
  49.         .remove = device_remove,
  50.         .uevent = device_uevent,
  51. };
  52. //////////////////////////////////////////////////////////////////////////////
  53. void device_xenbus_init()
  54. {
  55.         xenbus_register_backend(&deviceback);
  56. }

common.h

点击(此处)折叠或打开

  1. #ifndef COMMON_H
  2. #define COMMON_H
  3. void device_xenbus_init(void);
  4. #endif

Makefile

点击(此处)折叠或打开

  1. #Makefile
  2. obj-y += xenbus.o deviceback.o

Next, we should add our new backend device to the Makefile in linux-2.6-sparse/drivers/xen/Makefile. Add the following line to the bottom of that file:

点击(此处)折叠或打开

  1. obj-y += deviceback/

This will make sure that it will be included in the build.

Next, we need to add symlinks from linux-2.6-sparse/drivers/xen/deviceback into linux-2.6.18-xen/drivers/xen/deviceback:

  1. Create linux-2.6.18-xen/drivers/xen/deviceback
  2. Change into that directory
  3. Add the symlinks: 'ln -s ../../../../linux-2.6-xen-sparse/./drivers/xen/deviceback/./* .'

Now we should build the new drivers and reboot with the new Xen image. You can do this by going back to the root directory of the source tree (the place where you typed 'make world' when doing your normal build before) and do 'make install-kernels'. (Note: This will overwrite the previous Xen kernel!) Finally, reboot.

 

After the machine boots back up, go ahead and start a guest domain and you should notice that device_probe() does not get executed. (Check /var/log/syslog on dom0 to look for the printk() to show up.)

 

How can we trigger the probe() function of our backend driver? We just need to write the correct key/value pairs into the xenstore.

 

The call to xenbus_register_backend() in xenbus.c causes xenbus to set a watch on local/domain/0/backend/mydevice in the xenstore. Specifically, anytime anything is written into that location in the store the watch fires and checks for a specific set of key/value pairs that indicate the probe should be fired.

 

So performing the following 4 calls using xenstore-write will trigger our probe() function. Change the X with the ID of a running guest domain. (Check 'xm list' for this. If you've only started one guest, this number is probably 1.)

 

点击(此处)折叠或打开

  1. xenstore-write /local/domain/X/device/mydevice/0/state 1
  2. xenstore-write /local/domain/0/backend/mydevice/X/0/frontend-id X
  3. xenstore-write /local/domain/0/backend/mydevice/X/0/frontend /local/domain/X/device/mydevice/0
  4. xenstore-write /local/domain/0/backend/mydevice/X/0/state 1


You should see the probe message appear the Dom0's /var/log/syslog. What happened here behind the scenes ,without going too deep, is that the xenbus_register_backend() put a watch on the xenback directory of /local/domain/0 in the xenstore. Once frontend, frontend-id, and state are all written to the watched location, the xenbus driver will gather all of that information, as well as the state of the frontend driver (written in that first line) and use it to setup the appropriate data structures. From there, the probe() function is finally fired.



Frontend Driver

For this purpose,we will add a directory named "devicefront" to linux-2.6-sparse/drivers/xen.

 

We will create 2 files there: devicefront.c and Makefile.

 

We will also add directories and symlinks as we did in the deviceback case.

 

Makefile:

点击(此处)折叠或打开

  1. obj-y := devicefront.o
devicefront.c

The devicefront.c will be (a minimalist implementation):

点击(此处)折叠或打开

  1. // devicefront.c
  2. #include <xen/xenbus.h>
  3. #include <linux/module.h>
  4. #include <linux/list.h>
  5. struct device_info
  6. {
  7.         struct list_head list;
  8.         struct xenbus_device* xbdev;
  9. };
  10. //////////////////////////////////////////////////////////////////////////////
  11. static int devicefront_probe(struct xenbus_device* dev,
  12.                              const struct xenbus_device_id* id)
  13. {
  14.         printk("Frontend Probe Fired!\n");
  15.         return 0;
  16. }
  17. //////////////////////////////////////////////////////////////////////////////
  18. static struct xenbus_device_id devicefront_ids[] =
  19. {
  20.         {"mydevice"},
  21.         {}
  22. };
  23. static struct xenbus_driver devicefront =
  24. {
  25.         .name = "mydevice",
  26.         .owner = THIS_MODULE,
  27.         .ids = devicefront_ids,
  28.         .probe = devicefront_probe,
  29. };
  30. static int devicefront_init(void)
  31. {
  32.         printk("%s\n",__FUNCTION__);
  33.         xenbus_register_frontend(&devicefront);
  34. }
  35. module_init(devicefront_init);

We should also remember to add the following to the Makefile under linux-2.6-sparse/drivers/xen:

点击(此处)折叠或打开

  1. obj-y += devicefront/

Getting the frontend driver to fire is a bit more complicated, the following bash script should help you:

点击(此处)折叠或打开

  1. #!/bin/bash
  2. if [ $# != 2 ]
  3. then
  4.         echo "Usage: $0 "
  5. else
  6.         # Write backend information into the location the frontend will look
  7.         # for it.
  8.         xenstore-write /local/domain/${2}/device/${1}/0/backend-id 0
  9.         xenstore-write /local/domain/${2}/device/${1}/0/backend \
  10.                        /local/domain/0/backend/${1}/${2}/0
  11.         # Write frontend information into the location the backend will look
  12.         # for it.
  13.         xenstore-write /local/domain/0/backend/${1}/${2}/0/frontend-id ${2}
  14.         xenstore-write /local/domain/0/backend/${1}/${2}/0/frontend \
  15.                        /local/domain/${2}/device/${1}/0
  16.         # Set the permissions on the backend so that the frontend can
  17.         # actually read it.
  18.         xenstore-chmod /local/domain/0/backend/${1}/${2}/0 r
  19.         # Write the states. Note that the backend state must be written
  20.         # last because it requires a valid frontend state to already be
  21.         # written.
  22.         xenstore-write /local/domain/${2}/device/${1}/0/state 1
  23.         xenstore-write /local/domain/0/backend/${1}/${2}/0/state 1
  24. fi

Here's how to use it:

  • Startup a Xen guest that contains your frontend driver, and be sure dom0 contains the backend driver.
  • Figure out the frontend-id for the guest. This is the ID field when running xm list. Let's say that number is 3.
  • Run the script as so: ./probetest.sh mydevice 3

 

That should fire both the frontend driver. (You'll have to check /var/log/messages in the guest to verify that the probe was fired.)

阅读(2702) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~