ia64/xen-unstable

changeset 1076:7fee64560644

bitkeeper revision 1.712 (40278da0FlDvMYRMecrIx93_mifB0Q)

xc_netbsd_build.c, xc_elf.h, xendomains, netbsd:
new file
Many files:
Pull in user-space updates from v1.2.
author kaf24@scramble.cl.cam.ac.uk
date Mon Feb 09 13:39:44 2004 +0000 (2004-02-09)
parents 642aa90966e8
children 2c88db033b06
files .rootkeys docs/VBD-HOWTO.txt tools/examples/Makefile tools/examples/README tools/examples/defaults tools/examples/democd tools/examples/netbsd tools/examples/xc_dom_control.py tools/examples/xc_dom_create.py tools/examples/xendomains tools/xc/lib/xc.h tools/xc/lib/xc_elf.h tools/xc/lib/xc_netbsd_build.c tools/xc/py/Xc.c
line diff
     1.1 --- a/.rootkeys	Sun Feb 08 17:33:37 2004 +0000
     1.2 +++ b/.rootkeys	Mon Feb 09 13:39:44 2004 +0000
     1.3 @@ -45,9 +45,11 @@ 401d7e160vaxMBAUSLSicuZ7AQjJ3w tools/exa
     1.4  401d7e16UgeqroJQTIhwkrDVkoWgZQ tools/examples/README
     1.5  401d7e16GS8YesM1zateRbaOoI6YLQ tools/examples/defaults
     1.6  401d7e16NoWaBGC1RXbBcqAOr5Uaag tools/examples/democd
     1.7 +40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
     1.8  401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
     1.9  401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
    1.10  401d7e16X4iojyKopo_j63AyzYZd2A tools/examples/xc_vd_tool.py
    1.11 +40278d94cIUWl2eRgnwZtr4hTyWT1Q tools/examples/xendomains
    1.12  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.13  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.14  3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README
    1.15 @@ -70,10 +72,12 @@ 3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/xc/
    1.16  3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/xc/lib/xc.h
    1.17  3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/lib/xc_bvtsched.c
    1.18  3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/xc_domain.c
    1.19 +40278d99BLsfUv3qxv0I8C1sClZ0ow tools/xc/lib/xc_elf.h
    1.20  3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/xc_linux_build.c
    1.21  3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/xc_linux_restore.c
    1.22  3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
    1.23  3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/xc_misc.c
    1.24 +40278d9ctaHVDaEuwhXI3Om2JOjx9w tools/xc/lib/xc_netbsd_build.c
    1.25  3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/xc_private.c
    1.26  3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/xc_private.h
    1.27  3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/xc_vbd.c
     2.1 --- a/docs/VBD-HOWTO.txt	Sun Feb 08 17:33:37 2004 +0000
     2.2 +++ b/docs/VBD-HOWTO.txt	Mon Feb 09 13:39:44 2004 +0000
     2.3 @@ -21,10 +21,13 @@ Virtual Block Devices (VBDs):
     2.4  
     2.5  	A virtual block device can also consist of multiple extents from the
     2.6  	physical disks in the system, allowing them to be accessed as a single
     2.7 -	uniform device from the domain with access to that VBD.
     2.8 +	uniform device from the domain with access to that VBD.  The
     2.9 +	functionality is somewhat similar to that underpinning LVM, since
    2.10 +	you can combine multiple regions from physical devices into a single
    2.11 +	logical device, from the point of view of a guest virtual machine.
    2.12  
    2.13 -	Everyone who uses Xen / XenoLinux uses VBDs but for less advanced uses
    2.14 -	they can almost be ignored.
    2.15 +	Everyone who boots Xen / XenoLinux from a hard drive uses VBDs
    2.16 +	but for some uses they can almost be ignored.
    2.17  
    2.18  Virtual Disks (VDs):
    2.19  	VDs are an abstraction built on top of the functionality provided by
    2.20 @@ -43,10 +46,12 @@ Virtual Disks (VDs):
    2.21  	don't want to have to keep repartitioning in order to provide them with
    2.22  	disk space.
    2.23  
    2.24 +	Virtual Disks are rather like "logical volumes" in LVM.
    2.25 +
    2.26  If that didn't all make sense, it doesn't matter too much ;-)  Using the
    2.27  functionality is fairly straightforward and some examples will clarify things.
    2.28  The text below expands a bit on the concepts involved, finishing up with a
    2.29 -walkthrough of some simple virtual disk management tasks.
    2.30 +walk-through of some simple virtual disk management tasks.
    2.31  
    2.32  
    2.33  Virtual Block Devices
    2.34 @@ -58,39 +63,43 @@ functionality that will be useful to kno
    2.35  A VBD is made up of a number of extents from physical disk devices.  The
    2.36  extents for a VBD don't have to be contiguous, or even on the same device.  Xen
    2.37  performs address translation so that they appear as a single contiguous
    2.38 -device.
    2.39 +device to a domain.
    2.40  
    2.41  When the VBD layer is used to give access to entire drives or entire
    2.42 -partitions, the VBDs simply consist of a single extent, corresponding to the
    2.43 -drive or partition used.  When used with Virtual Disks, the extent list
    2.44 -functionality will be used (discussed later).
    2.45 +partitions, the VBDs simply consist of a single extent that corresponds to the
    2.46 +drive or partition used.  Lists of extents are usually only used when virtual
    2.47 +disks (VDs) are being used.
    2.48  
    2.49  Xen 1.2 and its associated XenoLinux release support automatic registration /
    2.50  removal of VBDs.  It has always been possible to add a VBD to a running
    2.51 -XenoLinux domain but it was then necessary to run "xen_vbd_refresh" in order
    2.52 -for the new device to be detected.  Nowadays, when a VBD is added, the domain
    2.53 -it's added to automatically registers the disk.
    2.54 +XenoLinux domain but it was then necessary to run the "xen_vbd_refresh" tool in
    2.55 +order for the new device to be detected.  Nowadays, when a VBD is added, the
    2.56 +domain it's added to automatically registers the disk, with no special action
    2.57 +by the user being required.
    2.58  
    2.59  Note that it is possible to use the VBD functionality to allow multiple domains
    2.60  write access to the same areas of disk.  This is almost always a bad thing!
    2.61 -
    2.62 -The provided example script createlinuxdom.py does its best to check that disk
    2.63 -areas are not shared unsafely and will catch many cases of this.  Setting the
    2.64 -vbd_expert variable in that script controls how unsafe it allows VBD mappings
    2.65 -to be - 0 should be right for most people ;-)
    2.66 +The provided example scripts for creating domains do their best to check that
    2.67 +disk areas are not shared unsafely and will catch many cases of this.  Setting
    2.68 +the vbd_expert variable in config files for xc_dom_create.py controls how
    2.69 +unsafe it allows VBD mappings to be - 0 (read only sharing allowed) should be
    2.70 +right for most people ;-).  Level 1 attempts to allow at most one writer to any
    2.71 +area of disk.  Level 2 allows multiple writers (i.e. anything!).
    2.72  
    2.73  
    2.74  Virtual Disk Management
    2.75  -----------------------
    2.76  
    2.77 -The VD management code runs entirely in userspace.  The code is written in
    2.78 +The VD management code runs entirely in user space.  The code is written in
    2.79  Python and can therefore be accessed from custom scripts, as well as from the
    2.80  convenience scripts provided.  The underlying VD database is a SQLite database
    2.81  in /var/db/xen_vdisks.sqlite.
    2.82  
    2.83 -The scripts provided are as follows:
    2.84 +Most virtual disk management can be performed using the xc_vd_tool.py script
    2.85 +provided in the tools/examples/ directory of the source tree.  It supports the
    2.86 +following operations:
    2.87  
    2.88 -vd_format.py -	     "Formats" a partition or disk device for use storing
    2.89 +initialise -	     "Formats" a partition or disk device for use storing
    2.90  		     virtual disks.  This does not actually write data to the
    2.91  		     specified device.  Rather, it adds the device to the VD
    2.92  		     free-space pool, for later allocation.
    2.93 @@ -100,7 +109,7 @@ vd_format.py -	     "Formats" a partitio
    2.94  		     have created yourself as part of the free space pool has
    2.95  		     undefined (possibly nasty) results.
    2.96  
    2.97 -vd_create.py -	     Creates a virtual disk of specified size by allocating space
    2.98 +create -	     Creates a virtual disk of specified size by allocating space
    2.99  		     from the free space pool.  The virtual disk is identified
   2.100  		     in future by the unique ID returned by this script.
   2.101  
   2.102 @@ -108,14 +117,39 @@ vd_create.py -	     Creates a virtual di
   2.103  		     most users, the best idea is to specify a time of 0 (which
   2.104  		     has the special meaning "never expire") and then
   2.105  		     explicitly delete the VD when finished with it -
   2.106 -		     otherwise, VDs could disappear unexpectedly...
   2.107 +		     otherwise, VDs will disappear if allowed to expire.
   2.108 +
   2.109 +delete -	     Explicitly delete a VD.  Makes it disappear immediately!
   2.110 +
   2.111 +setexpiry -	     Allows the expiry time of a (not yet expired) virtual disk
   2.112 +		     to be modified.  Be aware the VD will disappear when the
   2.113 +		     time has expired.
   2.114  
   2.115 -vd_refresh.py -	     Allows the expiry time of a (not yet expired) virtual disk to
   2.116 -		     be modified.  Be aware the VD will disappear when the time has
   2.117 -		     expired.
   2.118 +enlarge -            Increase the allocation of space to a virtual disk.
   2.119 +		     Currently this will not be immediately visible to running
   2.120 +		     domain(s) using it.  You can make it visible by destroying
   2.121 +		     the corresponding VBDs and then using xc_dom_control.py to
   2.122 +		     add them to the domain again.  Note: doing this to
   2.123 +		     filesystems that are in use may well cause errors in the
   2.124 +		     guest Linux, or even a crash although it will probably be
   2.125 +		     OK if you stop the domain before updating the VBD and
   2.126 +		     restart afterwards.
   2.127  
   2.128 -vd_delete.py -	     Explicitly delete a VD.  Makes it disappear immediately.
   2.129 +import -	     Allocate a virtual disk and populate it with the contents of
   2.130 +		     some disk file.  This can be used to import root file system
   2.131 +		     images or to restore backups of virtual disks, for instance.
   2.132 +
   2.133 +export -	     Write the contents of a virtual disk out to a disk file.
   2.134 +		     Useful for creating disk images for use elsewhere, such as
   2.135 +		     standard root file systems and backups.
   2.136  
   2.137 +list -		     List the non-expired virtual disks currently available in the
   2.138 +		     system.
   2.139 +
   2.140 +undelete -	     Attempts to recover an expired (or deleted) virtual disk.
   2.141 +
   2.142 +freespace -	     Get the free space (in megabytes) available for allocating
   2.143 +		     new virtual disk extents.
   2.144  
   2.145  The functionality provided by these scripts is also available directly from
   2.146  Python functions in the XenoUtil module - you can use this functionality in
   2.147 @@ -124,31 +158,40 @@ your own scripts.
   2.148  Populating VDs:
   2.149  
   2.150  Once you've created a VD, you might want to populate it from DOM0 (for
   2.151 -instance, to put a root filesystem onto it for a guest domain).  This can be
   2.152 -done by dynamically creating a VBD - this is discussed below.
   2.153 +instance, to put a root file system onto it for a guest domain).  This can be
   2.154 +done by creating a VBD for dom0 to access the VD through - this is discussed
   2.155 +below.
   2.156  
   2.157 -More detail:
   2.158 +More detail on how virtual disks work:
   2.159  
   2.160 -When you use vd_format.py to add a device to the free space pool, the device is
   2.161 -logically split up into extents.  These extents are recorded in the Virtual
   2.162 -Disk Management database in /var/db/xen_vdisks.sqlite.
   2.163 +When you "format" a device for virtual disks, the device is logically split up
   2.164 +into extents.  These extents are recorded in the Virtual Disk Management
   2.165 +database in /var/db/xen_vdisks.sqlite.
   2.166  
   2.167 -When you use vd_create.py to add create a virtual disk, some of the extents in
   2.168 +When you use xc_vd_tool.py to add create a virtual disk, some of the extents in
   2.169  the free space pool are reallocated for that virtual disk and a record for that
   2.170  VD is added to the database.  When VDs are mapped into domains as VBDs, the
   2.171  system looks up the allocated extents for the virtual disk in order to set up
   2.172  the underlying VBD.
   2.173  
   2.174  Free space is identified by the fact that it belongs to an "expired" disk.
   2.175 -When vd_format.py adds a real device to the free pool, it actually divides it
   2.176 -into extents and adds them to an already-expired virtual disk.
   2.177 +When "initialising" with xc_vd_tool.py adds a real device to the free pool, it
   2.178 +actually divides the device into extents and adds them to an already-expired
   2.179 +virtual disk.  The allocated device is not written to during this operation -
   2.180 +its availability is simply recorded into the virtual disks database.
   2.181  
   2.182  If you set an expiry time on a VD, its extents will be liable to be reallocated
   2.183  to new VDs as soon as that expiry time runs out.  Therefore, be careful when
   2.184 -setting expiry times.
   2.185 +setting expiry times!  Many users will find it simplest to set all VDs to not
   2.186 +expire automatically, then explicitly delete them later on.
   2.187  
   2.188 -Finally, vd_delete.py can be used to delete virtual disks when they are no
   2.189 -longer needed.  It works by causing them to expire immediately.
   2.190 +Deleted / expired virtual disks may sometimes be undeleted - currently this
   2.191 +only works when none of the virtual disk's extents have been reallocated to
   2.192 +other virtual disks, since that's the only situation where the disk is likely
   2.193 +to be fully intact.  You should try undeletion as soon as you realise you've
   2.194 +mistakenly deleted (or allowed to expire) a virtual disk.  At some point in the
   2.195 +future, an "unsafe" undelete which can recover what remains of partially
   2.196 +reallocated virtual disks may also be implemented.
   2.197  
   2.198  Security note:
   2.199  
   2.200 @@ -156,26 +199,33 @@ The disk space for VDs is not zeroed whe
   2.201  space pool OR when a VD expires OR when a VD is created.  Therefore, if this is
   2.202  not done manually it is possible for a domain to read a VD to determine what
   2.203  was written by previous owners of its constituent extents.  If this is a
   2.204 -problem, users should manually clean the VD in some way before allocating
   2.205 +problem, users should manually clean VDs in some way either on allocation, or
   2.206 +just before deallocation (automated support for this may be added at a later
   2.207 +date).
   2.208  
   2.209  
   2.210  Dynamically Registering VBDs
   2.211  ----------------------------
   2.212  
   2.213 -Two scripts are included to make it easy to add VDs to domains.
   2.214 +The domain control tool (xc_dom_control.py) includes the ability to add and
   2.215 +remove VBDs to / from running domains.  As usual, the command format is:
   2.216 +
   2.217 +xc_dom_control.py [operation] [arguments]
   2.218 +
   2.219 +The operations (and their arguments) are as follows:
   2.220  
   2.221 -add_vbd_to_dom.py -	 Creates a VBD corresponding to either a physical
   2.222 -			 device or a virtual disk and adds it as a specified
   2.223 -			 device under the target domain, with either read or
   2.224 -			 write access.
   2.225 +vbd_add dom uname dev mode - Creates a VBD corresponding to either a physical
   2.226 +		             device or a virtual disk and adds it as a
   2.227 +		             specified device under the target domain, with
   2.228 +		             either read or write access.
   2.229  
   2.230 -remove_vbd_from_dom.py - Removes the VBD associated with a specified device
   2.231 -			 node from the target domain.
   2.232 +vbd_remove dom dev	   - Removes the VBD associated with a specified device
   2.233 +			     node from the target domain.
   2.234  
   2.235  These scripts are most useful when populating VDs.  VDs can't be populated
   2.236  directly, since they don't correspond to real devices.  Using:
   2.237  
   2.238 -  add_vbd_to_dom.py vd:your_vd_id /dev/wherever 0 rw
   2.239 +  xc_dom_control.py vbd_add vd:your_vd_id /dev/whatever 0 w
   2.240  
   2.241  You can make a virtual disk available to DOM0.  Sensible devices to map VDs to
   2.242  in DOM0 are the /dev/xvd* nodes, since that makes it obvious that they are Xen
   2.243 @@ -184,90 +234,184 @@ virtual devices that don't correspond to
   2.244  You can then format, mount and populate the VD through the nominated device
   2.245  node.  When you've finished, use:
   2.246  
   2.247 -  remove_vbd_from_dom.py /dev/whatever 0
   2.248 +  xc_dom_control.py vbd_remove /dev/whatever 0
   2.249  
   2.250  To revoke DOM0's access to it.  It's then ready for use in a guest domain.
   2.251  
   2.252  
   2.253  
   2.254 -You can also use add_vbd_to_dom.py to grant access to a physical device to a
   2.255 -guest - you might use this to temporarily share a partition, or to add access
   2.256 -to a partition that wasn't granted at boot time.  Again, remove_vbd_from_dom.py
   2.257 -allows you to revoke access.
   2.258 +You can also use this functionality to grant access to a physical device to a
   2.259 +guest domain - you might use this to temporarily share a partition, or to add
   2.260 +access to a partition that wasn't granted at boot time.
   2.261  
   2.262  When playing with VBDs, remember that in general, it is only safe for two
   2.263 -domains to have access to a filesystem if they both have read-only access.  You
   2.264 -shouldn't be trying to share anything which is writeable, even if only by one
   2.265 +domains to have access to a file system if they both have read-only access.  You
   2.266 +shouldn't be trying to share anything which is writable, even if only by one
   2.267  domain, unless you're really sure you know what you're doing!
   2.268  
   2.269  
   2.270 +Granting access to real disks and partitions
   2.271 +--------------------------------------------
   2.272  
   2.273 -Walkthrough: Booting a domain from a VD
   2.274 ----------------------------------------
   2.275 +During the boot process, Xen automatically creates a VBD for each physical disk
   2.276 +and gives Dom0 read / write access to it.  This makes it look like Dom0 has
   2.277 +normal access to the disks, just as if Xen wasn't being used - in reality, even
   2.278 +Dom0 talks to disks through Xen VBDs.
   2.279 +
   2.280 +To give another domain access to a partition or whole disk then you need to
   2.281 +create a corresponding VBD for that partition, for use by that domain.  As for
   2.282 +virtual disks, you can grant access to a running domain, or specify that the
   2.283 +domain should have access when it is first booted.
   2.284 +
   2.285 +To grant access to a physical partition or disk whilst a domain is running, use
   2.286 +the xc_dom_control.py script - the usage is very similar to the case of adding
   2.287 +access virtual disks to a running domain (described above).  Specify the device
   2.288 +as "phy:device", where device is the name of the device as seen from domain 0,
   2.289 +or from normal Linux without Xen.  For instance:
   2.290 +
   2.291 +> xc_dom_control.py vbd_add phy:hdc /dev/whatever 2 r
   2.292 +
   2.293 +Will grant domain 2 read-only access to the device /dev/hdc (as seen from Dom0
   2.294 +/ normal Linux running on the same machine - i.e. the master drive on the
   2.295 +secondary IDE chain), as /dev/whatever in the target domain.
   2.296 +
   2.297 +Note that you can use this within domain 0 to map disks / partitions to other
   2.298 +device nodes within domain 0.  For instance, you could map /dev/hda to also be
   2.299 +accessible through /dev/xvda.  This is not generally recommended, since if you
   2.300 +(for instance) mount both device nodes read / write you could cause corruption
   2.301 +to the underlying filesystem.  It's also quite confusing ;-)
   2.302 +
   2.303 +To grant a domain access to a partition or disk when it boots, the appropriate
   2.304 +VBD needs to be created before the domain is started.  This can be done very
   2.305 +easily using the tools provided.  To specify this to the xc_dom_create.py tool
   2.306 +(either in a startup script or on the command line) use triples of the format:
   2.307 +
   2.308 +  phy:dev,target_dev,perms
   2.309 +
   2.310 +Where dev is the device name as seen from Dom0, target_dev is the device you
   2.311 +want it to appear as in the target domain and perms is 'w' if you want to give
   2.312 +write privileges, or 'r' otherwise.
   2.313 +
   2.314 +These may either be specified on the command line or in an initialisation
   2.315 +script.  For instance, to grant the same access rights as described by the
   2.316 +command example above, you would use the triple:
   2.317 +
   2.318 +  phy:hdc,/dev/whatever,r
   2.319 +
   2.320 +If you are using a config file, then you should add this triple into the
   2.321 +vbd_list variable, for instance using the line:
   2.322 +
   2.323 +  vbd_list = [ ('phy:dev', 'hdc', 'r') ]
   2.324 +
   2.325 +(Note that you need to use quotes here, since config files are really small
   2.326 +Python scripts.)
   2.327 +
   2.328 +To specify the mapping on the commandline, you'd use the -d switch and supply
   2.329 +the triple as the argument, e.g.:
   2.330 +
   2.331 +> xc_dom_create.py [other arguments] -d phy:hdc,/dev/whatever,r
   2.332 +
   2.333 +(You don't need to explicitly quote things in this case.)
   2.334 +
   2.335 +
   2.336 +Walk-through: Booting a domain from a VD
   2.337 +----------------------------------------
   2.338  
   2.339  As an example, here is a sequence of commands you might use to create a virtual
   2.340 -disk, populate it with a root filesystem and boot a domain from it.  These
   2.341 +disk, populate it with a root file system and boot a domain from it.  These
   2.342  steps assume that you've installed the example scripts somewhere on your PATH -
   2.343  if you haven't done that, you'll need to specify a fully qualified pathname in
   2.344 -the examples below.  The steps also assume that you know how to use the
   2.345 -createlinuxdom.py script provided and have already set it up for your local
   2.346 -configuration, apart from the virtual disks info.
   2.347 +the examples below.  It is also assumed that you know how to use the
   2.348 +xc_dom_create.py tool (apart from configuring virtual disks!)
   2.349 +
   2.350 +[ This example is intended only for users of virtual disks (VDs).  You don't
   2.351 +need to follow this example if you'll be booting a domain from a dedicated
   2.352 +partition, since you can create that partition and populate it, directly from
   2.353 +Dom0, as normal. ]
   2.354  
   2.355  First, if you haven't done so already, you'll initialise the free space pool by
   2.356  adding a real partition to it.  The details are stored in the database, so
   2.357  you'll only need to do it once.  You can also use this command to add further
   2.358  partitions to the existing free space pool.
   2.359  
   2.360 -> vd_format.py /dev/<real partition>
   2.361 +> xc_vd_tool.py format /dev/<real partition>
   2.362  
   2.363  Now you'll want to allocate the space for your virtual disk.  Do so using the
   2.364  following, specifying the size in megabytes.
   2.365  
   2.366 -> vd_create.py <chosen size>
   2.367 +> xc_vd_tool.py create <size in megabytes>
   2.368  
   2.369 -At this point, the vd_create.py program will tell you the virtual disk ID.
   2.370 -Note it down, as it is how you will identify the virtual device in future.
   2.371 +At this point, the program will tell you the virtual disk ID.  Note it down, as
   2.372 +it is how you will identify the virtual device in future.
   2.373  
   2.374  If you don't want the VD to be bootable (i.e. you're booting a domain from some
   2.375  other medium and just want it to be able to access this VD), you can simply add
   2.376 -it to the vbds list in your custom createlinuxdom.py (step 5) and then run that
   2.377 -script.  Any formatting / populating of the VD can be done from that domain.
   2.378 +it to the vbd_list used by xc_dom_create.py, either by putting it in a config
   2.379 +file or by specifying it on the command line.  Formatting / populating of the
   2.380 +VD could then done from that domain once it's started.
   2.381  
   2.382  If you want to boot off your new VD as well then you need to populate it with a
   2.383  standard Linux root filesystem.  You'll need to temporarily add the VD to DOM0
   2.384  in order to do this.  To give DOM0 r/w access to the VD, use the following
   2.385  command line, substituting the ID you got earlier.
   2.386  
   2.387 -> add_vbd_to_dom.py vd:<id> /dev/xvda 0 rw
   2.388 +> xc_dom_control.py vbd_add vd:<id> /dev/xvda 0 w
   2.389  
   2.390 -This attaches the VD to the device /dev/xvda - you can use other devices if you
   2.391 -choose too but with the xvd* devices it's obvious you're using a virtual device.
   2.392 +This attaches the VD to the device /dev/xvda in domain zero, with read / write
   2.393 +privileges - you can use other devices nodes if you choose too.
   2.394  
   2.395  Now make a filesystem on this device, mount it and populate it with a root
   2.396  filesystem.  These steps are exactly the same as under normal Linux.  When
   2.397  you've finished, unmount the filesystem again.
   2.398  
   2.399  You should now remove the VD from DOM0.  This will prevent you accidentally
   2.400 -changing it in DOM0, whilst the guest domain is using it.
   2.401 +changing it in DOM0, whilst the guest domain is using it (which could cause
   2.402 +filesystem corruption, and confuse Linux).
   2.403  
   2.404 -> remove_vbd_from_dom.py /dev/xvda 0
   2.405 +> xc_dom_control.py vbd_remove /dev/xvda 0
   2.406  
   2.407  It should now be possible to boot a guest domain from the VD.  To do this, you
   2.408 -should add the VD's details to the vbds list in step 5 of createlinuxdom.py and
   2.409 -set the value of rootbit in step 6.  For instance, you might add:
   2.410 +should specify the the VD's details in some way so that xc_dom_create.py will
   2.411 +be able to set up the corresponding VBD for the domain to access.  If you're
   2.412 +using a config file, you should include:
   2.413 +
   2.414 +  ('vd:<id>', '/dev/whatever', 'w')
   2.415  
   2.416 -('vd:<id>', '/dev/xvda', 'w')
   2.417 +In the vbd_list, substituting the appropriate virtual disk ID, device node and
   2.418 +read / write setting.
   2.419 +
   2.420 +To specify access on the command line, as you start the domain, you would use
   2.421 +the -d switch (note that you don't need to use quote marks here):
   2.422  
   2.423 -To the vbds list in step 5 - this gives the domain writeable access to the VD
   2.424 -as if it were the domain's /dev/xvda.
   2.425 +> xc_dom_create.py [other arguments] -d vd:<id>,/dev/whatever,w
   2.426 +
   2.427 +To tell Linux which device to boot from, you should either include:
   2.428 +
   2.429 +  root=/dev/whatever
   2.430  
   2.431 -Then you would set:
   2.432 +in your cmdline_root in the config file, or specify it on the command line,
   2.433 +using the -R option:
   2.434  
   2.435 -rootbit = "root=/dev/xvda ro"
   2.436 +> xc_dom_create.py [other arguments] -R root=/dev/whatever
   2.437  
   2.438 -In step 6 to tell the kernel where the root filesystem is.
   2.439 +That should be it: sit back watch your domain boot off its virtual disk!
   2.440  
   2.441  
   2.442 +Getting help
   2.443 +------------
   2.444  
   2.445 -Once these variables are set, you can run createlinuxdom.py to start your new
   2.446 -domain.
   2.447 +The main source of help using Xen is the developer's e-mail list:
   2.448 +<xen-devel@lists.sourceforge.net>.  The developers will help with problems,
   2.449 +listen to feature requests and do bug fixes.  It is, however, helpful if you
   2.450 +can look through the mailing list archives and HOWTOs provided to make sure
   2.451 +your question is not answered there.  If you post to the list, please provide
   2.452 +as much information as possible about your setup and your problem.
   2.453 +
   2.454 +There is also a general Xen FAQ, kindly started by Jan van Rensburg, which (at
   2.455 +time of writing) is located at: <http://xen.epiuse.com/xen-faq.txt>.
   2.456 +
   2.457 +Contributing
   2.458 +------------
   2.459 +
   2.460 +Patches and extra documentation are also welcomed ;-) and should also be posted
   2.461 +to the xen-devel e-mail list.
     3.1 --- a/tools/examples/Makefile	Sun Feb 08 17:33:37 2004 +0000
     3.2 +++ b/tools/examples/Makefile	Mon Feb 09 13:39:44 2004 +0000
     3.3 @@ -8,7 +8,8 @@ SRCS     = $(wildcard *.c)
     3.4  OBJS     = $(patsubst %.c,%.o,$(SRCS))
     3.5  
     3.6  INSTALL  = $(wildcard *.py)
     3.7 -ETC	 = defaults democd
     3.8 +ETC	 = defaults democd netbsd
     3.9 +INITD    = xendomains
    3.10  
    3.11  all: 
    3.12  
    3.13 @@ -17,14 +18,18 @@ install: all
    3.14  	cp -a $(INSTALL) /usr/bin
    3.15  	#chmod 755 $(INSTALL)
    3.16  	mkdir -p /etc/xc
    3.17 -	for i in $(ETC) ; do [ ! -e /etc/xc/$$i ] && echo Install $$i && cp $$i /etc/xc/ ; done || true 
    3.18 +	for i in $(ETC) ; do [ ! -e /etc/xc/$$i ] && echo Install $$i && cp $$i /etc/xc/ ; done || true
    3.19 +	mkdir -p /etc/xc/auto
    3.20 +	for i in $(INITD) ; do [ -e /etc/init.d/ ] && [ ! -e /etc/init.d/$$i ] && cp $$i /etc/init.d/ ; done || true
    3.21  
    3.22  dist: all
    3.23  	mkdir -p ../../../install/bin
    3.24  	mkdir -p ../../../install/etc
    3.25 +	mkdir -p ../../../install/init.d
    3.26  	cp -a $(INSTALL) ../../../install/bin
    3.27  	cp -a $(ETC) ../../../install/etc
    3.28  	#chmod 755 $(INSTALL)
    3.29 +	cp -a $(INITD) ../../../install/init.d
    3.30  
    3.31  clean:
    3.32  
     4.1 --- a/tools/examples/README	Sun Feb 08 17:33:37 2004 +0000
     4.2 +++ b/tools/examples/README	Mon Feb 09 13:39:44 2004 +0000
     4.3 @@ -18,10 +18,12 @@ xc_dom_control.py
     4.4    Usage: xc_dom_control.py [command] <params>
     4.5    stop      [dom]        -- pause a domain
     4.6    start     [dom]        -- un-pause a domain
     4.7 -  shutdown  [dom]        -- request a domain to shutdown
     4.8 +  shutdown  [dom]        -- request a domain to shutdown (can specify 'all')
     4.9 +                            (optionally wait for complete shutdown)
    4.10    destroy   [dom]        -- immediately terminate a domain
    4.11    pincpu    [dom] [cpu]  -- pin a domain to the specified CPU
    4.12 -  save      [dom] [file] -- suspend a domain's memory to file
    4.13 +  suspend   [dom] [file] -- write domain's memory to a file and terminate
    4.14 +			    (resume by re-running xc_dom_create with -L option)
    4.15    restore   [file]       -- resume a domain from a file
    4.16    list                   -- print info about all domains
    4.17    listvbds               -- print info about all virtual block devs
    4.18 @@ -34,7 +36,7 @@ xc_dom_control.py
    4.19    vif_getsched [dom] [vif] -- print vif's scheduling parameters
    4.20    vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to 
    4.21                              domain as dev e.g. 'vbd_add phy:sda3 hda1 rw'
    4.22 -  vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' 
    4.23 +  vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev'
    4.24  
    4.25  
    4.26  xc_dom_create.py
    4.27 @@ -47,10 +49,12 @@ in [] brackets. Arguments are as follows
    4.28  Arguments to control the parsing of the defaults file:
    4.29   -f config_file   -- Use the specified defaults script. 
    4.30                       Default: ['/etc/xc/defaults']
    4.31 + -L state_file    -- Load virtual machine memory state from state_file
    4.32   -D foo=bar       -- Set variable foo=bar before parsing config
    4.33 -                     E.g. '-D vmid=3:ip=1.2.3.4'
    4.34 +                     E.g. '-D vmid=3;ip=1.2.3.4'
    4.35   -h               -- Print extended help message, including all arguments
    4.36   -n               -- Dry run only, don't actually create domain
    4.37 + -q               -- Quiet - write output only to the system log
    4.38  
    4.39  
    4.40  The config file 'defaults' requires the following variable to be defined:
    4.41 @@ -69,7 +73,7 @@ Arguments to override current config rea
    4.42   -d udisk,dev,rw  -- Add disk, partition, or virtual disk to domain. E.g. to 
    4.43                       make partion sda4 available to the domain as hda1 with 
    4.44                       read-write access: '-b phy:sda4,hda1,rw' To add 
    4.45 -                     multiple disks use multiple -d flags or seperate with ':'
    4.46 +                     multiple disks use multiple -d flags or seperate with ';'
    4.47                       Default: ['']
    4.48   -i vfr_ipaddr    -- Add IP address to the list which Xen will route to
    4.49                       the domain. Use multiple times to add more IP addrs.
    4.50 @@ -107,3 +111,18 @@ xc_vd_tool
    4.51     device    - physical partition to 'format' to hold vd's. e.g. hda4
    4.52     ext_size  - extent size (default 64MB)
    4.53  
    4.54 +
    4.55 +xendomains
    4.56 +This is a Sys-V init script for RedHat systems.
    4.57 +
    4.58 + - Usage: xendomains {start|stop|status}
    4.59 +
    4.60 +   start  -- starts all the domains with config files in /etc/xc/auto/
    4.61 +   stop   -- stops ALL running domains, waiting for them to shutdown cleanly
    4.62 +             (if possible) before returning
    4.63 +   status -- prints a list of the running domains, the same as
    4.64 +             "xc_dom_control.py list"
    4.65 +
    4.66 +On a RedHat system it should be possible to issue commands to this
    4.67 +script using the "service" command and to configure if / when it is
    4.68 +run automatically, using the "chkconfig" command.
     5.1 --- a/tools/examples/defaults	Sun Feb 08 17:33:37 2004 +0000
     5.2 +++ b/tools/examples/defaults	Mon Feb 09 13:39:44 2004 +0000
     5.3 @@ -26,7 +26,7 @@ if vmid == 0:
     5.4  image = "../../../install/boot/xenolinux.gz"
     5.5  ramdisk = ""
     5.6  #ramdisk = "/boot/initrd.gz"
     5.7 -builder_fn='xc.linux_build' # this is a linux domain
     5.8 +builder_fn='linux' # this is a linux domain
     5.9  
    5.10  # STEP 2. The initial memory allocation (in megabytes) for the new domain.
    5.11  mem_size = 64
     6.1 --- a/tools/examples/democd	Sun Feb 08 17:33:37 2004 +0000
     6.2 +++ b/tools/examples/democd	Mon Feb 09 13:39:44 2004 +0000
     6.3 @@ -8,7 +8,7 @@ def config_usage ():
     6.4      print >>sys.stderr, """
     6.5  The config file %s requires the following vars to be defined:
     6.6   ip               -- List of IP addr(s) for Xen to route to domain 
     6.7 -                     e.g. -Dip='1.2.3.4,5.6.7.8'
     6.8 +                     e.g. '-Dip=1.2.3.4,5.6.7.8'
     6.9  The following variables may be optionally defined:
    6.10   mem              -- Adjust initial memory allocation (default 64MB)
    6.11   netmask          -- Override gateway for kernel ip= command line
    6.12 @@ -18,13 +18,13 @@ The following variables may be optionall
    6.13  try:
    6.14      ip
    6.15  except:
    6.16 -    print "Set variable 'ip' using -Dip='1.2.3.4,5.6.7.8'"
    6.17 +    print "Set variable 'ip' using '-Dip=1.2.3.4,5.6.7.8'"
    6.18      assert()
    6.19  
    6.20  # STEP 1. Specify kernel image file and otional ramdisk. Can be gzip'ed.
    6.21  image   = "/boot/xenolinux.gz"
    6.22  ramdisk = "/boot/initrd.gz"
    6.23 -builder_fn='xc.linux_build' # this is a linux domain
    6.24 +builder_fn='linux' # this is a linux domain
    6.25  
    6.26  # STEP 2. The initial memory allocation (in megabytes) for the new domain.
    6.27  try:
    6.28 @@ -34,7 +34,13 @@ except NameError:
    6.29  
    6.30  
    6.31  # STEP 3. A handy name for your new domain.
    6.32 -domain_name = "Demo CD VM %s" % ip
    6.33 +# appends either first hostname or last quad of first IP address dependant on value passed
    6.34 +
    6.35 +quads = string.split(ip, '.')
    6.36 +if len(quads) == 4:					# fragile heuristic for valid IP verification
    6.37 +	domain_name = "Xen VM .%s" % quads[3]		# use last quad of IP
    6.38 +else:
    6.39 +	domain_name = "Xen VM: %s" % ip			# use hostname passed in
    6.40  
    6.41  
    6.42  # STEP 4. Specify IP address(es), for the new domain.  You need to
    6.43 @@ -47,6 +53,7 @@ domain_name = "Demo CD VM %s" % ip
    6.44  vfr_ipaddr  = map(socket.gethostbyname,string.split(ip,','))
    6.45  
    6.46  
    6.47 +
    6.48  # STEP 5a. Identify any physcial partitions or virtual disks you want the
    6.49  # domain to have access to, and what you want them accessible as
    6.50  # e.g. vbd_list = [ ('phy:sda1','sda1', 'w'),
    6.51 @@ -72,46 +79,58 @@ vbd_expert = 0
    6.52  # You can use 'extrabit' to set the runlevel and custom environment
    6.53  # variables used by custom rc scripts (e.g. VMID=, usr= )
    6.54  
    6.55 -try: 
    6.56 -    netmask = socket.gethostbyname( netmask )
    6.57 -except NameError:
    6.58 -    netmask = XenoUtil.get_current_ipmask()
    6.59  
    6.60 -try: 
    6.61 -    gateway = socket.gethostbyname( gateway )
    6.62 -except NameError:
    6.63 -    gateway = XenoUtil.get_current_ipgw()
    6.64 -
    6.65 +# see if we have a local IP at all
    6.66  localip=''
    6.67  for i in vfr_ipaddr:
    6.68 -    if XenoUtil.check_subnet(i,'169.254.0.0','255.255.0.0'): localip=i
    6.69 +    if XenoUtil.check_subnet(i,'169.254.0.0','255.255.0.0'):
    6.70 +	localip=i
    6.71 +	break
    6.72 +
    6.73  
    6.74 -# Try to guess the machine's LAN settings
    6.75 +# if either netmask and gateway has been set from the command line,
    6.76 +# associate it with the first IP address that has been specified.
    6.77 +
    6.78 +myip = ''
    6.79  
    6.80 -lanip=''
    6.81 -if netmask and gateway:
    6.82 -    for i in vfr_ipaddr:
    6.83 -	if XenoUtil.check_subnet(i,gateway,netmask): 
    6.84 -	    lanip=i
    6.85 -	    break
    6.86 +try: 
    6.87 +    netmask = socket.gethostbyname( netmask )
    6.88 +    gateway = socket.gethostbyname( gateway )
    6.89 +    myip = vfr_ipaddr[0]
    6.90 +
    6.91 +except NameError:
    6.92 +    netmask = XenoUtil.get_current_ipmask()
    6.93 +    gateway = XenoUtil.get_current_ipgw()
    6.94 +
    6.95 +# if we haven't got an address, see if we have one that matches the LAN
    6.96  
    6.97 -# Have a fall back plan...
    6.98 +if not myip:
    6.99 +    if netmask and gateway:
   6.100 +	for i in vfr_ipaddr:
   6.101 +	    if XenoUtil.check_subnet(i,gateway,netmask): 
   6.102 +		myip=i
   6.103 +		break
   6.104  
   6.105 -if not netmask:
   6.106 -    netmask = '255.255.0.0' 
   6.107 +# if we still haven't got an address, see if there's a link local one
   6.108  
   6.109 -if not gateway:
   6.110 -    gateway = '169.254.1.0' 
   6.111 +if not myip and localip:
   6.112 +    myip = localip
   6.113 +    netmask = '255.255.0.0'
   6.114 +    gateway = '169.254.1.0'
   6.115 +
   6.116  
   6.117 -if not lanip:
   6.118 -    lanip = vfr_ipaddr[0]
   6.119 +# As a final fallback, through everything down the interface
   6.120  
   6.121 +if not myip:
   6.122 +    myip = vfr_ipaddr[0]
   6.123 +    netmask = '0.0.0.0' 
   6.124 +    gateway = '' 
   6.125  
   6.126  # Calculate the components with which we will build the command line
   6.127  
   6.128  nfsserv = '169.254.1.0'  
   6.129  
   6.130 -cmdline_ip="ip="+lanip+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
   6.131 +cmdline_ip="ip="+myip+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
   6.132  cmdline_root  = "root=/dev/ram0 rw init=/linuxrc"
   6.133  
   6.134  if localip:
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/examples/netbsd	Mon Feb 09 13:39:44 2004 +0000
     7.3 @@ -0,0 +1,113 @@
     7.4 +
     7.5 +##### Edit this python file to reflect the configuration of your system
     7.6 +
     7.7 +##### This example script expects a variable called 'vmid' to be set.
     7.8 +
     7.9 +def config_usage ():
    7.10 +    print >>sys.stderr,"""
    7.11 +The config file '%s' requires the following variable to be defined:
    7.12 + vmid             -- Numeric identifier for the new domain, used to calculate
    7.13 +                     the VM's IP address and root partition. E.g. -Dvmid=1
    7.14 +
    7.15 +Additionally the following variable may be defined:
    7.16 + image            -- Path to kernel image, can be gzip'ed. [/boot/netbsd]
    7.17 + mem              -- Memory size. [16]
    7.18 + name             -- Domain name. [NetBSD VM vmid]
    7.19 + ip               -- Primary IP address for domain. [this domain's IP + vmid]
    7.20 + nfsserv          -- NFS server IP address. [169.254.1.0]
    7.21 + nfsroot          -- Path to nfs root filesystem. [/netboot/netbsd]
    7.22 +""" % config_file
    7.23 +
    7.24 +
    7.25 +try:
    7.26 +    vmid=int(vmid) # convert to integer
    7.27 +except:
    7.28 +    print >>sys.stderr,"%s: This script expects 'vmid' to be set using -D vmid=X" % config_file
    7.29 +    assert()
    7.30 +
    7.31 +if vmid == 0:
    7.32 +    print >>sys.stderr,"%s: 'vmid' must be greater than 0" % config_file
    7.33 +    assert()
    7.34 +
    7.35 +
    7.36 +# STEP 1. Specify kernel image file. Can be gzip'ed.
    7.37 +if image == "": image = "/boot/netbsd"
    7.38 +
    7.39 +builder_fn='netbsd' # this is a NetBSD domain
    7.40 +
    7.41 +
    7.42 +# STEP 2. The initial memory allocation (in megabytes) for the new domain.
    7.43 +try:
    7.44 +    mem_size = int(mem)
    7.45 +except:
    7.46 +    mem_size = 16
    7.47 +
    7.48 +
    7.49 +# STEP 3. A handy name for your new domain.
    7.50 +try:
    7.51 +    domain_name = name
    7.52 +except:
    7.53 +    domain_name = "NetBSD VM %d" % vmid
    7.54 +
    7.55 +
    7.56 +# STEP 4. Specify IP address(es), for the new domain.  You need to
    7.57 +# configure IP addrs within the domain just as you do normally.  This
    7.58 +# is just to let Xen know about them so it can route packets
    7.59 +# appropriately.
    7.60 +
    7.61 +#vfr_ipaddr = ["111.222.333.444","222.333.444.555"]
    7.62 +try:
    7.63 +    vfr_ipaddr = [ip, XenoUtil.add_offset_to_ip('169.254.1.0',vmid),]
    7.64 +except:
    7.65 +    vfr_ipaddr = [XenoUtil.add_offset_to_ip(XenoUtil.get_current_ipaddr(),vmid),
    7.66 +                  XenoUtil.add_offset_to_ip('169.254.1.0',vmid),]
    7.67 +
    7.68 +
    7.69 +# STEP 5a. Identify any physcial partitions or virtual disks you want the
    7.70 +# domain to have access to, and what you want them accessible as
    7.71 +# e.g. vbd_list = [ ('phy:sda1','sda1', 'w'),
    7.72 +#	 ('phy:sda%d' % (3+vmid), 'hda2', 'r'), 
    7.73 +#	 ('vd:as73gd784dh','hda1','w'),
    7.74 +#	 ('phy:cdrom','hdd','r')
    7.75 +
    7.76 +#vbd_list = [ ('phy:sda%d'%(7+vmid),'sda1','w' ), 
    7.77 +#	     ('phy:sda6','sda6','r') ]
    7.78 +
    7.79 +
    7.80 +
    7.81 +# STEP 5b. Set the VBD expertise level.  Most people should leave this
    7.82 +# on 0, at least to begin with - this script can detect most dangerous
    7.83 +# disk sharing between domains and with this set to zero it will only
    7.84 +# allow read only sharing.
    7.85 +
    7.86 +vbd_expert = 0
    7.87 +
    7.88 +
    7.89 +# STEP 6. Build the command line for the new domain. Edit as req'd.
    7.90 +# You only need the ip= line if you're NFS booting or the root file system
    7.91 +# doesn't set it later e.g. in ifcfg-eth0 or via DHCP
    7.92 +# You can use 'extrabit' to set the runlevel and custom environment
    7.93 +# variables used by custom rc scripts (e.g. VMID=, usr= )
    7.94 +
    7.95 +netmask = XenoUtil.get_current_ipmask()
    7.96 +gateway = XenoUtil.get_current_ipgw()
    7.97 +try:
    7.98 +    nfsserv
    7.99 +except:
   7.100 +    nfsserv = '169.254.1.0'
   7.101 +
   7.102 +cmdline_ip = "ip="+vfr_ipaddr[0]+":"+nfsserv+":"+gateway+":"+netmask+"::eth0:off"
   7.103 +try:
   7.104 +    cmdline_root = "nfsroot="+nfsserv+":"+nfsroot
   7.105 +except:
   7.106 +    cmdline_root = "nfsroot="+nfsserv+":/netboot/netbsd"
   7.107 +    #cmdline_root = "nfsroot=/full/path/to/root/directory"
   7.108 +
   7.109 +cmdline_extra = "bootdev=xennet0"
   7.110 +
   7.111 +
   7.112 +# STEP 7. Set according to whether you want the script to watch the domain 
   7.113 +# and auto-restart it should it die or exit.
   7.114 +
   7.115 +auto_restart = False
   7.116 +#auto_restart = True
     8.1 --- a/tools/examples/xc_dom_control.py	Sun Feb 08 17:33:37 2004 +0000
     8.2 +++ b/tools/examples/xc_dom_control.py	Mon Feb 09 13:39:44 2004 +0000
     8.3 @@ -11,11 +11,13 @@ Usage: %s [command] <params>
     8.4  
     8.5    stop      [dom]        -- pause a domain
     8.6    start     [dom]        -- un-pause a domain
     8.7 -  shutdown  [dom]        -- request a domain to shutdown
     8.8 +  shutdown  [dom] [[-w]] -- request a domain to shutdown (can specify 'all')
     8.9 +                            (optionally wait for complete shutdown)
    8.10    destroy   [dom]        -- immediately terminate a domain
    8.11    pincpu    [dom] [cpu]  -- pin a domain to the specified CPU
    8.12 -  save      [dom] [file] -- suspend a domain's memory to file
    8.13 -  restore   [file]       -- resume a domain from a file
    8.14 +  suspend   [dom] [file] -- write domain's memory to a file and terminate
    8.15 +			    (resume by re-running xc_dom_create with -L option)
    8.16 +  unwatch   [dom]        -- kill the auto-restart daemon for a domain
    8.17    list                   -- print info about all domains
    8.18    listvbds               -- print info about all virtual block devs
    8.19    cpu_bvtset [dom] [mcuadv] [warp] [warpl] [warpu]
    8.20 @@ -30,7 +32,7 @@ Usage: %s [command] <params>
    8.21    vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' 
    8.22  """ % sys.argv[0]
    8.23  
    8.24 -import Xc, sys, re, string
    8.25 +import Xc, sys, re, string, time, os, signal
    8.26  
    8.27  if len(sys.argv) < 2:
    8.28      usage()
    8.29 @@ -41,6 +43,8 @@ cmd = sys.argv[1]
    8.30  
    8.31  xc = Xc.new()
    8.32  rc = ''
    8.33 +dom = None
    8.34 +
    8.35  
    8.36  if len( sys.argv ) > 2 and re.match('\d+$', sys.argv[2]):
    8.37      dom = string.atoi(sys.argv[2])
    8.38 @@ -52,7 +56,24 @@ elif cmd == 'start':
    8.39      rc = xc.domain_start( dom=dom )    
    8.40  
    8.41  elif cmd == 'shutdown':
    8.42 -    rc = xc.domain_destroy( dom=dom, force=0 )    
    8.43 +    list = []
    8.44 +    if dom != None:
    8.45 +        rc = xc.domain_destroy( dom=dom, force=0 )
    8.46 +        list.append(dom)
    8.47 +    elif sys.argv[2] == 'all':
    8.48 +        for i in xc.domain_getinfo():
    8.49 +            if i['dom'] != 0: # don't shutdown dom0!
    8.50 +                ret = xc.domain_destroy( dom=i['dom'], force=0 )
    8.51 +                if ret !=0: rc = ret
    8.52 +                else: list.append(i['dom'])
    8.53 +
    8.54 +    if len(sys.argv) == 4 and sys.argv[3] == "-w":
    8.55 +        # wait for all domains we shut down to terminate
    8.56 +        for dom in list:
    8.57 +            while True:
    8.58 +                info = xc.domain_getinfo(dom,1)
    8.59 +                if not ( info != [] and info[0]['dom'] == dom ): break
    8.60 +                time.sleep(1)
    8.61  
    8.62  elif cmd == 'destroy':
    8.63      rc = xc.domain_destroy( dom=dom, force=1 )    
    8.64 @@ -76,27 +97,55 @@ elif cmd == 'pincpu':
    8.65  	xc.domain_start( dom=dom )
    8.66  
    8.67  elif cmd == 'list':
    8.68 -    for i in xc.domain_getinfo(): print i
    8.69 +    print 'Dom  Name             Mem(kb)  CPU  State  Time(s)'
    8.70 +    for domain in xc.domain_getinfo():
    8.71 +
    8.72 +	run = (domain['running'] and 'r') or '-'		# domain['running'] ? run='r' : run='-'
    8.73 +	stop = (domain['stopped'] and 's') or '-'		# domain['stopped'] ? stop='s': stop='-'
    8.74 +
    8.75 +        domain['state'] = run + stop
    8.76 +        domain['cpu_time'] = domain['cpu_time']/1e8
    8.77 +
    8.78 +        print "%(dom)-4d %(name)-16s %(mem_kb)7d %(cpu)3d %(state)5s %(cpu_time)8d" % domain
    8.79 +
    8.80 +elif cmd == 'unwatch':
    8.81 +
    8.82 +    # the auto-restart daemon's pid file
    8.83 +    watcher = '/var/run/xendomains/%d.pid' % dom
    8.84 +
    8.85 +    if os.path.isfile(watcher):
    8.86 +        fd = open(watcher,'r')
    8.87 +        pid = int(fd.readline())
    8.88 +        os.kill(pid, signal.SIGTERM)
    8.89  
    8.90  elif cmd == 'listvbds':
    8.91 -    for i in xc.vbd_probe(): print i
    8.92 +    vbdInfo = xc.vbd_probe()
    8.93 +    for vbd in vbdInfo:
    8.94 +        print 'dom:' + str(vbd['dom'])
    8.95 +	del vbd['dom']
    8.96 +        print '-----'
    8.97 +        for field in vbd:
    8.98 +                print field + ': ' + str(vbd[field])
    8.99 +        print '\n'
   8.100  
   8.101 -elif cmd == 'save':
   8.102 +elif cmd == 'suspend':
   8.103      if len(sys.argv) < 4:
   8.104          usage()
   8.105          sys.exit(-1)
   8.106  
   8.107      file = sys.argv[3]
   8.108 -        
   8.109 -    rc = xc.linux_save( dom=dom, state_file=file, progress=1)
   8.110 +
   8.111 +    # the auto-restart daemon's pid file
   8.112 +    watcher = '/var/run/xendomains/%d.pid' % dom
   8.113  
   8.114 -elif cmd == 'restore':
   8.115 -    if len(sys.argv) < 3:
   8.116 -        usage()
   8.117 -        sys.exit(-1)
   8.118 -        
   8.119 -    file = sys.argv[2]
   8.120 -    rc = xc.linux_restore( state_file=file, progress=1 )
   8.121 +    if os.path.isfile(watcher):
   8.122 +        fd = open(watcher,'r')
   8.123 +        pid = int(fd.readline())
   8.124 +        os.kill(pid, signal.SIGTERM)
   8.125 +
   8.126 +    xc.domain_stop( dom=dom )
   8.127 +    rc = xc.linux_save( dom=dom, state_file=file, progress=1)
   8.128 +    if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
   8.129  
   8.130  elif cmd == 'cpu_bvtslice':
   8.131      if len(sys.argv) < 3:
   8.132 @@ -164,7 +213,8 @@ elif cmd == 'vif_getsched':
   8.133  
   8.134  
   8.135  elif cmd == 'vbd_add':
   8.136 -
   8.137 +    import XenoUtil
   8.138 +    
   8.139      XenoUtil.VBD_EXPERT_LEVEL = 0 # sets the allowed level of potentially unsafe mappings
   8.140  
   8.141      if len(sys.argv) < 6:
   8.142 @@ -196,6 +246,7 @@ elif cmd == 'vbd_add':
   8.143      print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, virt_dev)
   8.144  
   8.145  elif cmd == 'vbd_remove':
   8.146 +    import XenoUtil
   8.147  
   8.148      if len(sys.argv) < 4:
   8.149  	usage()
     9.1 --- a/tools/examples/xc_dom_create.py	Sun Feb 08 17:33:37 2004 +0000
     9.2 +++ b/tools/examples/xc_dom_create.py	Mon Feb 09 13:39:44 2004 +0000
     9.3 @@ -1,6 +1,6 @@
     9.4  #!/usr/bin/env python
     9.5  
     9.6 -import Xc, XenoUtil, string, sys, os, time, socket, getopt
     9.7 +import Xc, XenoUtil, string, sys, os, time, socket, getopt, signal, syslog
     9.8  
     9.9  config_dir  = '/etc/xc/'
    9.10  config_file = xc_config_file = config_dir + 'defaults'
    9.11 @@ -18,10 +18,12 @@ in [] brackets. Arguments are as follows
    9.12  Arguments to control the parsing of the defaults file:
    9.13   -f config_file   -- Use the specified defaults script. 
    9.14                       Default: ['%s']
    9.15 + -L state_file    -- Load virtual machine memory state from state_file
    9.16   -D foo=bar       -- Set variable foo=bar before parsing config
    9.17 -                     E.g. '-D vmid=3:ip=1.2.3.4'
    9.18 +                     E.g. '-D vmid=3;ip=1.2.3.4'
    9.19   -h               -- Print extended help message, including all arguments
    9.20   -n               -- Dry run only, don't actually create domain
    9.21 + -q               -- Quiet - write output only to the system log
    9.22  """ % (sys.argv[0], xc_config_file)
    9.23  
    9.24  def extra_usage ():
    9.25 @@ -36,8 +38,8 @@ Arguments to override current config rea
    9.26   -e vbd_expert    -- Saftey catch to avoid some disk accidents ['%d'] 
    9.27   -d udisk,dev,rw  -- Add disk, partition, or virtual disk to domain. E.g. to 
    9.28                       make partion sda4 available to the domain as hda1 with 
    9.29 -                     read-write access: '-b phy:sda4,hda1,rw' To add 
    9.30 -                     multiple disks use multiple -d flags or seperate with ':'
    9.31 +                     read-write access: '-d phy:sda4,hda1,rw' To add 
    9.32 +                     multiple disks use multiple -d flags or seperate with ';'
    9.33                       Default: ['%s']
    9.34   -i vfr_ipaddr    -- Add IP address to the list which Xen will route to
    9.35                       the domain. Use multiple times to add more IP addrs.
    9.36 @@ -68,30 +70,38 @@ def answer ( s ):
    9.37  def printvbds ( v ):
    9.38      s=''
    9.39      for (a,b,c) in v:
    9.40 -	s = s + ':%s,%s,%s' % (a,b,c)
    9.41 -    return s[1:]
    9.42 -
    9.43 +	s = s + '; %s,%s,%s' % (a,b,c)
    9.44 +    return s[2:]
    9.45  
    9.46 -bail=False; dryrun=False; extrahelp=False
    9.47 -image=''; ramdisk=''; builder_fn=''; 
    9.48 -mem_size=0; domain_name=''; vfr_ipaddr=[]; 
    9.49 -vbd_expert=0; auto_restart=0;
    9.50 +def output(string):
    9.51 +    global quiet
    9.52 +    syslog.syslog(string)
    9.53 +    if not quiet:
    9.54 +        print string
    9.55 +    return
    9.56 +
    9.57 +bail=False; dryrun=False; extrahelp=False; quiet = False
    9.58 +image=''; ramdisk=''; builder_fn=''; restore=0; state_file=''
    9.59 +mem_size=0; domain_name=''; vfr_ipaddr=[];
    9.60 +vbd_expert=0; auto_restart=False;
    9.61  vbd_list = []; cmdline_ip = ''; cmdline_root=''; cmdline_extra=''
    9.62  
    9.63  ##### Determine location of defautls file
    9.64  #####
    9.65  
    9.66  try:
    9.67 -    opts, args = getopt.getopt(sys.argv[1:], "h?nf:D:k:r:b:m:N:a:e:d:i:I:R:E:" )
    9.68 +    opts, args = getopt.getopt(sys.argv[1:], "h?nqf:D:k:r:b:m:N:a:e:d:i:I:R:E:L:" )
    9.69  
    9.70      for opt in opts:
    9.71  	if opt[0] == '-f': config_file= opt[1]
    9.72  	if opt[0] == '-h' or opt[0] == '-?' : bail=True; extrahelp=True
    9.73  	if opt[0] == '-n': dryrun=True
    9.74  	if opt[0] == '-D': 
    9.75 -	    for o in string.split( opt[1], ':' ):
    9.76 +	    for o in string.split( opt[1], ';' ):
    9.77  		(l,r) = string.split( o, '=' )
    9.78  		exec "%s='%s'" % (l,r)
    9.79 +        if opt[0] == '-q': quiet = True
    9.80 +        if opt[0] == '-L': restore = True; state_file = opt[1]
    9.81  
    9.82  
    9.83  except getopt.GetoptError:
    9.84 @@ -113,7 +123,8 @@ except:
    9.85  ##### Parse the config file
    9.86  #####
    9.87  
    9.88 -print "Parsing config file '%s'" % config_file
    9.89 +if not quiet:
    9.90 +    print "Parsing config file '%s'" % config_file
    9.91  
    9.92  try:
    9.93      execfile ( config_file )
    9.94 @@ -139,7 +150,7 @@ x_vfr_ipaddr  = []
    9.95  for opt in opts:
    9.96      if opt[0] == '-k': image = opt[1]
    9.97      if opt[0] == '-r': ramdisk = opt[1]
    9.98 -    if opt[0] == '-b': builder_fn = opt[1]  #XXXX
    9.99 +    if opt[0] == '-b': builder_fn = opt[1]  
   9.100      if opt[0] == '-m': mem_size = int(opt[1])
   9.101      if opt[0] == '-N': domain_name = opt[1]
   9.102      if opt[0] == '-a': auto_restart = answer(opt[1])
   9.103 @@ -150,7 +161,7 @@ for opt in opts:
   9.104      if opt[0] == '-i': x_vfr_ipaddr.append(opt[1])
   9.105      if opt[0] == '-d':
   9.106  	try:
   9.107 -	    vv = string.split(opt[1],':')	    
   9.108 +	    vv = string.split(opt[1],';')	    
   9.109  	    for v in vv:
   9.110  		(udisk,dev,mode) = string.split(v,',')
   9.111  		x_vbd_list.append( (udisk,dev,mode) )
   9.112 @@ -163,17 +174,18 @@ if x_vfr_ipaddr: vfr_ipaddr = x_vfr_ipad
   9.113  
   9.114  cmdline = cmdline_ip +' '+ cmdline_root +' '+ cmdline_extra
   9.115  
   9.116 +syslog.openlog('xc_dom_create.py %s' % config_file, 0, syslog.LOG_DAEMON)
   9.117 +
   9.118  ##### Print some debug info just incase things don't work out...
   9.119  ##### 
   9.120  
   9.121 -print
   9.122 -print 'VM image           : "%s"' % image
   9.123 -print 'VM ramdisk         : "%s"' % ramdisk
   9.124 -print 'VM memory (MB)     : "%d"' % mem_size
   9.125 -print 'VM IP address(es)  : "%s"' % reduce((lambda a,b: a+':'+b),vfr_ipaddr,'' )[1:]
   9.126 -print 'VM block device(s) : "%s"' % printvbds( vbd_list )
   9.127 -print 'VM cmdline         : "%s"' % cmdline
   9.128 -print
   9.129 +output('VM image           : "%s"' % image)
   9.130 +output('VM ramdisk         : "%s"' % ramdisk)
   9.131 +output('VM memory (MB)     : "%d"' % mem_size)
   9.132 +output('VM IP address(es)  : "%s"'
   9.133 +                % reduce((lambda a,b: a+'; '+b),vfr_ipaddr,'' )[2:])
   9.134 +output('VM block device(s) : "%s"' % printvbds( vbd_list ))
   9.135 +output('VM cmdline         : "%s"' % cmdline)
   9.136  
   9.137  if dryrun:
   9.138      sys.exit(1)
   9.139 @@ -194,7 +206,7 @@ def make_domain():
   9.140  
   9.141      # set up access to the global variables declared above
   9.142      global image, ramdisk, mem_size, domain_name, vfr_ipaddr, netmask
   9.143 -    global vbd_list, cmdline, xc, vbd_expert
   9.144 +    global vbd_list, cmdline, xc, vbd_expert, builder_fn
   9.145      	
   9.146      if not os.path.isfile( image ):
   9.147          print "Image file '" + image + "' does not exist"
   9.148 @@ -204,18 +216,25 @@ def make_domain():
   9.149          print "Ramdisk file '" + ramdisk + "' does not exist"
   9.150          sys.exit()
   9.151  
   9.152 -    id = xc.domain_create( mem_kb=mem_size*1024, name=domain_name )
   9.153 -    if id <= 0:
   9.154 -        print "Error creating domain"
   9.155 -        sys.exit()
   9.156 -
   9.157 -    ret = xc.linux_build( dom=id, image=image, ramdisk=ramdisk, 
   9.158 -			  cmdline=cmdline )
   9.159 -    if ret < 0:
   9.160 -        print "Error building Linux guest OS: "
   9.161 -        print "Return code from linux_build = " + str(ret)
   9.162 -        xc.domain_destroy ( dom=id )
   9.163 -        sys.exit()
   9.164 +    if restore:
   9.165 +        ret = eval('xc.%s_restore ( state_file=state_file, progress=1 )' % builder_fn)
   9.166 +        if ret < 0:
   9.167 +            print "Error restoring domain"
   9.168 +            sys.exit()
   9.169 +        else:
   9.170 +            id = ret
   9.171 +    else:
   9.172 +        id = xc.domain_create( mem_kb=mem_size*1024, name=domain_name )
   9.173 +        if id <= 0:
   9.174 +            print "Error creating domain"
   9.175 +            sys.exit()
   9.176 +            
   9.177 +        ret = eval('xc.%s_build ( dom=id, image=image, ramdisk=ramdisk, cmdline=cmdline )' % builder_fn)
   9.178 +        if ret < 0:
   9.179 +            print "Error building Linux guest OS: "
   9.180 +            print "Return code = " + str(ret)
   9.181 +            xc.domain_destroy ( dom=id )
   9.182 +            sys.exit()
   9.183  
   9.184      # setup the virtual block devices
   9.185  
   9.186 @@ -261,13 +280,33 @@ def make_domain():
   9.187      return id
   9.188  # end of make_domain()
   9.189  
   9.190 +def mkpidfile():
   9.191 +    global current_id
   9.192 +    if not os.path.isdir('/var/run/xendomains/'):
   9.193 +        os.mkdir('/var/run/xendomains/')
   9.194  
   9.195 +    fd = open('/var/run/xendomains/%d.pid' % current_id, 'w')
   9.196 +    print >> fd, str(os.getpid())
   9.197 +    fd.close()
   9.198 +    return
   9.199 +
   9.200 +def rmpidfile():
   9.201 +    global current_id
   9.202 +    os.unlink('/var/run/xendomains/%d.pid' % current_id)
   9.203 +
   9.204 +def death_handler(dummy1,dummy2):
   9.205 +    global current_id
   9.206 +    os.unlink('/var/run/xendomains/%d.pid' % current_id)
   9.207 +    output('Auto-restart daemon: daemon PID = %d for domain %d is now exiting'
   9.208 +              % (os.getpid(),current_id))
   9.209 +    sys.exit(0)
   9.210 +    return
   9.211  
   9.212  # The starting / monitoring of the domain actually happens here...
   9.213  
   9.214  # start the domain and record its ID number
   9.215  current_id = make_domain()
   9.216 -print "VM started in domain %d" % current_id
   9.217 +output("VM started in domain %d" % current_id)
   9.218  
   9.219  # if the auto_restart flag is set then keep polling to see if the domain is
   9.220  # alive - restart if it is not by calling make_domain() again (it's necessary
   9.221 @@ -282,15 +321,22 @@ if auto_restart:
   9.222  	os.setsid()
   9.223  	pid = os.fork()
   9.224  	if pid > 0:
   9.225 -	    print >> sys.stderr, 'Auto-restart daemon PID = %d' % pid
   9.226 +            output('Auto-restart daemon PID = %d' % pid)
   9.227  	    sys.exit(0)
   9.228 -    except:
   9.229 -	print >> sys.stderr, 'Problem starting daemon'
   9.230 +        signal.signal(signal.SIGTERM,death_handler)
   9.231 +    except OSError:
   9.232 +	print >> sys.stderr, 'Problem starting auto-restart daemon'
   9.233  	sys.exit(1)
   9.234  
   9.235 -    while auto_restart:
   9.236 +    mkpidfile()
   9.237 +
   9.238 +    while True:
   9.239  	time.sleep(1)
   9.240 -	if not xc.domain_getinfo(current_id):
   9.241 -	    print "Domain %d has terminated, restarting VM in new domain" % current_id
   9.242 +        info = xc.domain_getinfo(current_id, 1)
   9.243 +	if info == [] or info[0]['dom'] != current_id:
   9.244 +	    output("Auto-restart daemon: Domain %d has terminated, restarting VM in new domain"
   9.245 +                                     % current_id)
   9.246 +            rmpidfile()
   9.247  	    current_id = make_domain()
   9.248 -	    print "VM started in domain %d" % current_id
   9.249 +            mkpidfile()
   9.250 +	    output("Auto-restart daemon: VM restarted in domain %d" % current_id)
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/examples/xendomains	Mon Feb 09 13:39:44 2004 +0000
    10.3 @@ -0,0 +1,136 @@
    10.4 +#!/bin/sh
    10.5 +#
    10.6 +# /etc/init.d/xendomains
    10.7 +# Start / stop domains automatically when domain 0 boots / shuts down.
    10.8 +#
    10.9 +# chkconfig: 345 99 00
   10.10 +# description: Start / stop Xen domains.
   10.11 +#
   10.12 +# This script offers fairly basic functionality.
   10.13 +#
   10.14 +# Based on the example in the "Designing High Quality Integrated Linux
   10.15 +# Applications HOWTO" by Avi Alkalay
   10.16 +# <http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/>
   10.17 +#
   10.18 +
   10.19 +RETVAL=0
   10.20 +
   10.21 +INITD=/etc/init.d/
   10.22 +. $INITD/functions
   10.23 +
   10.24 +on_fn_exit()
   10.25 +{
   10.26 +    if [ $RETVAL -eq 0 ]; then
   10.27 +	success
   10.28 +    else
   10.29 +	failure
   10.30 +    fi
   10.31 +    
   10.32 +    echo
   10.33 +}
   10.34 +
   10.35 +start() {
   10.36 +    if [ -f /var/lock/subsys/xendomains ]; then return; fi
   10.37 +
   10.38 +    echo -n $"Starting auto Xen domains:"
   10.39 +
   10.40 +    # we expect config scripts for auto starting domains to be in
   10.41 +    # /etc/xc/auto/ - they could just be symlinks to files elsewhere
   10.42 +    if [ $(ls /etc/xc/auto/ | wc -l) -gt 0 ]; then
   10.43 +	
   10.44 +       # create all domains with config files in /etc/xc/auto
   10.45 +	for dom in /etc/xc/auto/*; do
   10.46 +	    xc_dom_create.py -q -f $dom
   10.47 +	    if [ $? -ne 0 ]; then
   10.48 +		RETVAL=$?
   10.49 +	    fi
   10.50 +	done
   10.51 +    fi
   10.52 +
   10.53 +    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/xendomains
   10.54 +
   10.55 +    on_fn_exit
   10.56 +}
   10.57 +
   10.58 +stop()
   10.59 +{
   10.60 +    # NB. this shuts down ALL Xen domains (politely), not just the ones in
   10.61 +    # /etc/xc/auto/*
   10.62 +    # This is because it's easier to do ;-) but arguably if this script is run
   10.63 +    # on system shutdown then it's also the right thing to do.
   10.64 +    
   10.65 +    echo -n $"Shutting down all Xen domains:"
   10.66 +
   10.67 +    if [ $(ls /var/run/xendomains/ | wc -l) -gt 0 ]; then
   10.68 +	
   10.69 +	cd /var/run/xendomains/
   10.70 +
   10.71 +	for pid in *; do
   10.72 +	   
   10.73 +	    kill -s SIGTERM $(cat $pid)
   10.74 +
   10.75 +	done
   10.76 +
   10.77 +    fi
   10.78 +
   10.79 +    sleep 3 # avoid races
   10.80 +
   10.81 +    xc_dom_control.py shutdown all -w # shut down all domains, politely and wait
   10.82 +                                      # for all to exit
   10.83 +    
   10.84 +    RETVAL=$?
   10.85 +
   10.86 +    [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/xendomains
   10.87 +
   10.88 +    on_fn_exit
   10.89 +}
   10.90 +
   10.91 +# This does NOT necessarily restart all running domains: instead it
   10.92 +# stops all running domains and then boots all the domains specified in
   10.93 +# /etc/xc/auto.  If other domains have been started manually then they will
   10.94 +# not get restarted.
   10.95 +# Commented out to avoid confusion!
   10.96 +#
   10.97 +#restart()
   10.98 +#{
   10.99 +#    stop
  10.100 +#    start
  10.101 +#}
  10.102 +
  10.103 +# same as restart for now - commented out to avoid confusion
  10.104 +#reload()
  10.105 +#{
  10.106 +#    restart
  10.107 +#}
  10.108 +
  10.109 +
  10.110 +case "$1" in
  10.111 +    start)
  10.112 +	start
  10.113 +	;;
  10.114 +
  10.115 +    stop)
  10.116 +	stop
  10.117 +	;;
  10.118 +
  10.119 +# The following are commented out to disable them by default to avoid confusion
  10.120 +# - see the notes above
  10.121 +#
  10.122 +#    restart)
  10.123 +#	restart
  10.124 +#	;;
  10.125 +#
  10.126 +#    reload)
  10.127 +#	reload
  10.128 +#	;;
  10.129 +
  10.130 +    status)
  10.131 +	xc_dom_control.py list
  10.132 +	;;
  10.133 +
  10.134 +    *)
  10.135 +	echo $"Usage: $0 {start|stop|status}"
  10.136 +	;;
  10.137 +esac
  10.138 +
  10.139 +exit $RETVAL
    11.1 --- a/tools/xc/lib/xc.h	Sun Feb 08 17:33:37 2004 +0000
    11.2 +++ b/tools/xc/lib/xc.h	Mon Feb 09 13:39:44 2004 +0000
    11.3 @@ -55,6 +55,11 @@ int xc_linux_build(int xc_handle,
    11.4                     const char *ramdisk_name,
    11.5                     const char *cmdline);
    11.6  
    11.7 +int xc_netbsd_build(int xc_handle,
    11.8 +                    unsigned int domid,
    11.9 +                    const char *image_name,
   11.10 +                    const char *cmdline);
   11.11 +
   11.12  int xc_bvtsched_global_set(int xc_handle,
   11.13                             unsigned long ctx_allow);
   11.14  int xc_bvtsched_domain_set(int xc_handle,
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/xc/lib/xc_elf.h	Mon Feb 09 13:39:44 2004 +0000
    12.3 @@ -0,0 +1,523 @@
    12.4 +/*
    12.5 + * Copyright (c) 1995, 1996 Erik Theisen.  All rights reserved.
    12.6 + *
    12.7 + * Redistribution and use in source and binary forms, with or without
    12.8 + * modification, are permitted provided that the following conditions
    12.9 + * are met:
   12.10 + * 1. Redistributions of source code must retain the above copyright
   12.11 + *    notice, this list of conditions and the following disclaimer.
   12.12 + * 2. Redistributions in binary form must reproduce the above copyright
   12.13 + *    notice, this list of conditions and the following disclaimer in the
   12.14 + *    documentation and/or other materials provided with the distribution.
   12.15 + * 3. The name of the author may not be used to endorse or promote products
   12.16 + *    derived from this software without specific prior written permission
   12.17 + *
   12.18 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   12.19 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   12.20 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   12.21 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   12.22 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   12.23 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   12.24 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   12.25 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   12.26 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   12.27 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   12.28 + */
   12.29 +
   12.30 +typedef u_int8_t	Elf_Byte;
   12.31 +
   12.32 +typedef u_int32_t	Elf32_Addr;	/* Unsigned program address */
   12.33 +typedef u_int32_t	Elf32_Off;	/* Unsigned file offset */
   12.34 +typedef int32_t		Elf32_Sword;	/* Signed large integer */
   12.35 +typedef u_int32_t	Elf32_Word;	/* Unsigned large integer */
   12.36 +typedef u_int16_t	Elf32_Half;	/* Unsigned medium integer */
   12.37 +
   12.38 +typedef u_int64_t	Elf64_Addr;
   12.39 +typedef u_int64_t	Elf64_Off;
   12.40 +typedef int32_t		Elf64_Shalf;
   12.41 +
   12.42 +typedef int32_t		Elf64_Sword;
   12.43 +typedef u_int32_t	Elf64_Word;
   12.44 +
   12.45 +typedef int64_t		Elf64_Sxword;
   12.46 +typedef u_int64_t	Elf64_Xword;
   12.47 +
   12.48 +typedef u_int32_t	Elf64_Half;
   12.49 +typedef u_int16_t	Elf64_Quarter;
   12.50 +
   12.51 +/*
   12.52 + * e_ident[] identification indexes 
   12.53 + * See http://www.caldera.com/developers/gabi/2000-07-17/ch4.eheader.html
   12.54 + */
   12.55 +#define EI_MAG0		0		/* file ID */
   12.56 +#define EI_MAG1		1		/* file ID */
   12.57 +#define EI_MAG2		2		/* file ID */
   12.58 +#define EI_MAG3		3		/* file ID */
   12.59 +#define EI_CLASS	4		/* file class */
   12.60 +#define EI_DATA		5		/* data encoding */
   12.61 +#define EI_VERSION	6		/* ELF header version */
   12.62 +#define EI_OSABI	7		/* OS/ABI ID */
   12.63 +#define EI_ABIVERSION	8		/* ABI version */ 
   12.64 +#define EI_PAD		9		/* start of pad bytes */
   12.65 +#define EI_NIDENT	16		/* Size of e_ident[] */
   12.66 +
   12.67 +/* e_ident[] magic number */
   12.68 +#define	ELFMAG0		0x7f		/* e_ident[EI_MAG0] */
   12.69 +#define	ELFMAG1		'E'		/* e_ident[EI_MAG1] */
   12.70 +#define	ELFMAG2		'L'		/* e_ident[EI_MAG2] */
   12.71 +#define	ELFMAG3		'F'		/* e_ident[EI_MAG3] */
   12.72 +#define	ELFMAG		"\177ELF"	/* magic */
   12.73 +#define	SELFMAG		4		/* size of magic */
   12.74 +
   12.75 +/* e_ident[] file class */
   12.76 +#define	ELFCLASSNONE	0		/* invalid */
   12.77 +#define	ELFCLASS32	1		/* 32-bit objs */
   12.78 +#define	ELFCLASS64	2		/* 64-bit objs */
   12.79 +#define	ELFCLASSNUM	3		/* number of classes */
   12.80 +
   12.81 +/* e_ident[] data encoding */
   12.82 +#define ELFDATANONE	0		/* invalid */
   12.83 +#define ELFDATA2LSB	1		/* Little-Endian */
   12.84 +#define ELFDATA2MSB	2		/* Big-Endian */
   12.85 +#define ELFDATANUM	3		/* number of data encode defines */
   12.86 +
   12.87 +/* e_ident[] Operating System/ABI */
   12.88 +#define ELFOSABI_SYSV		0	/* UNIX System V ABI */
   12.89 +#define ELFOSABI_HPUX		1	/* HP-UX operating system */
   12.90 +#define ELFOSABI_NETBSD		2	/* NetBSD */
   12.91 +#define ELFOSABI_LINUX		3	/* GNU/Linux */
   12.92 +#define ELFOSABI_HURD		4	/* GNU/Hurd */
   12.93 +#define ELFOSABI_86OPEN		5	/* 86Open common IA32 ABI */
   12.94 +#define ELFOSABI_SOLARIS	6	/* Solaris */
   12.95 +#define ELFOSABI_MONTEREY	7	/* Monterey */
   12.96 +#define ELFOSABI_IRIX		8	/* IRIX */
   12.97 +#define ELFOSABI_FREEBSD	9	/* FreeBSD */
   12.98 +#define ELFOSABI_TRU64		10	/* TRU64 UNIX */
   12.99 +#define ELFOSABI_MODESTO	11	/* Novell Modesto */
  12.100 +#define ELFOSABI_OPENBSD	12	/* OpenBSD */
  12.101 +#define ELFOSABI_ARM		97	/* ARM */
  12.102 +#define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */
  12.103 +
  12.104 +/* e_ident */
  12.105 +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
  12.106 +                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
  12.107 +                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
  12.108 +                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)
  12.109 +
  12.110 +/* ELF Header */
  12.111 +typedef struct elfhdr {
  12.112 +	unsigned char	e_ident[EI_NIDENT]; /* ELF Identification */
  12.113 +	Elf32_Half	e_type;		/* object file type */
  12.114 +	Elf32_Half	e_machine;	/* machine */
  12.115 +	Elf32_Word	e_version;	/* object file version */
  12.116 +	Elf32_Addr	e_entry;	/* virtual entry point */
  12.117 +	Elf32_Off	e_phoff;	/* program header table offset */
  12.118 +	Elf32_Off	e_shoff;	/* section header table offset */
  12.119 +	Elf32_Word	e_flags;	/* processor-specific flags */
  12.120 +	Elf32_Half	e_ehsize;	/* ELF header size */
  12.121 +	Elf32_Half	e_phentsize;	/* program header entry size */
  12.122 +	Elf32_Half	e_phnum;	/* number of program header entries */
  12.123 +	Elf32_Half	e_shentsize;	/* section header entry size */
  12.124 +	Elf32_Half	e_shnum;	/* number of section header entries */
  12.125 +	Elf32_Half	e_shstrndx;	/* section header table's "section 
  12.126 +					   header string table" entry offset */
  12.127 +} Elf32_Ehdr;
  12.128 +
  12.129 +typedef struct {
  12.130 +	unsigned char	e_ident[EI_NIDENT];	/* Id bytes */
  12.131 +	Elf64_Quarter	e_type;			/* file type */
  12.132 +	Elf64_Quarter	e_machine;		/* machine type */
  12.133 +	Elf64_Half	e_version;		/* version number */
  12.134 +	Elf64_Addr	e_entry;		/* entry point */
  12.135 +	Elf64_Off	e_phoff;		/* Program hdr offset */
  12.136 +	Elf64_Off	e_shoff;		/* Section hdr offset */
  12.137 +	Elf64_Half	e_flags;		/* Processor flags */
  12.138 +	Elf64_Quarter	e_ehsize;		/* sizeof ehdr */
  12.139 +	Elf64_Quarter	e_phentsize;		/* Program header entry size */
  12.140 +	Elf64_Quarter	e_phnum;		/* Number of program headers */
  12.141 +	Elf64_Quarter	e_shentsize;		/* Section header entry size */
  12.142 +	Elf64_Quarter	e_shnum;		/* Number of section headers */
  12.143 +	Elf64_Quarter	e_shstrndx;		/* String table index */
  12.144 +} Elf64_Ehdr;
  12.145 +
  12.146 +/* e_type */
  12.147 +#define ET_NONE		0		/* No file type */
  12.148 +#define ET_REL		1		/* relocatable file */
  12.149 +#define ET_EXEC		2		/* executable file */
  12.150 +#define ET_DYN		3		/* shared object file */
  12.151 +#define ET_CORE		4		/* core file */
  12.152 +#define ET_NUM		5		/* number of types */
  12.153 +#define ET_LOPROC	0xff00		/* reserved range for processor */
  12.154 +#define ET_HIPROC	0xffff		/*  specific e_type */
  12.155 +
  12.156 +/* e_machine */
  12.157 +#define EM_NONE		0		/* No Machine */
  12.158 +#define EM_M32		1		/* AT&T WE 32100 */
  12.159 +#define EM_SPARC	2		/* SPARC */
  12.160 +#define EM_386		3		/* Intel 80386 */
  12.161 +#define EM_68K		4		/* Motorola 68000 */
  12.162 +#define EM_88K		5		/* Motorola 88000 */
  12.163 +#define EM_486		6		/* Intel 80486 - unused? */
  12.164 +#define EM_860		7		/* Intel 80860 */
  12.165 +#define EM_MIPS		8		/* MIPS R3000 Big-Endian only */
  12.166 +/* 
  12.167 + * Don't know if EM_MIPS_RS4_BE,
  12.168 + * EM_SPARC64, EM_PARISC,
  12.169 + * or EM_PPC are ABI compliant
  12.170 + */
  12.171 +#define EM_MIPS_RS4_BE	10		/* MIPS R4000 Big-Endian */
  12.172 +#define EM_SPARC64	11		/* SPARC v9 64-bit unoffical */
  12.173 +#define EM_PARISC	15		/* HPPA */
  12.174 +#define EM_SPARC32PLUS	18		/* Enhanced instruction set SPARC */
  12.175 +#define EM_PPC		20		/* PowerPC */
  12.176 +#define EM_ARM		40		/* Advanced RISC Machines ARM */
  12.177 +#define EM_ALPHA	41		/* DEC ALPHA */
  12.178 +#define EM_SPARCV9	43		/* SPARC version 9 */
  12.179 +#define EM_ALPHA_EXP	0x9026		/* DEC ALPHA */
  12.180 +#define EM_X86_64	62		/* AMD x86-64 architecture */
  12.181 +#define EM_VAX		75		/* DEC VAX */
  12.182 +#define EM_NUM		15		/* number of machine types */
  12.183 +
  12.184 +/* Version */
  12.185 +#define EV_NONE		0		/* Invalid */
  12.186 +#define EV_CURRENT	1		/* Current */
  12.187 +#define EV_NUM		2		/* number of versions */
  12.188 +
  12.189 +/* Section Header */
  12.190 +typedef struct {
  12.191 +	Elf32_Word	sh_name;	/* name - index into section header
  12.192 +					   string table section */
  12.193 +	Elf32_Word	sh_type;	/* type */
  12.194 +	Elf32_Word	sh_flags;	/* flags */
  12.195 +	Elf32_Addr	sh_addr;	/* address */
  12.196 +	Elf32_Off	sh_offset;	/* file offset */
  12.197 +	Elf32_Word	sh_size;	/* section size */
  12.198 +	Elf32_Word	sh_link;	/* section header table index link */
  12.199 +	Elf32_Word	sh_info;	/* extra information */
  12.200 +	Elf32_Word	sh_addralign;	/* address alignment */
  12.201 +	Elf32_Word	sh_entsize;	/* section entry size */
  12.202 +} Elf32_Shdr;
  12.203 +
  12.204 +typedef struct {
  12.205 +	Elf64_Half	sh_name;	/* section name */
  12.206 +	Elf64_Half	sh_type;	/* section type */
  12.207 +	Elf64_Xword	sh_flags;	/* section flags */
  12.208 +	Elf64_Addr	sh_addr;	/* virtual address */
  12.209 +	Elf64_Off	sh_offset;	/* file offset */
  12.210 +	Elf64_Xword	sh_size;	/* section size */
  12.211 +	Elf64_Half	sh_link;	/* link to another */
  12.212 +	Elf64_Half	sh_info;	/* misc info */
  12.213 +	Elf64_Xword	sh_addralign;	/* memory alignment */
  12.214 +	Elf64_Xword	sh_entsize;	/* table entry size */
  12.215 +} Elf64_Shdr;
  12.216 +
  12.217 +/* Special Section Indexes */
  12.218 +#define SHN_UNDEF	0		/* undefined */
  12.219 +#define SHN_LORESERVE	0xff00		/* lower bounds of reserved indexes */
  12.220 +#define SHN_LOPROC	0xff00		/* reserved range for processor */
  12.221 +#define SHN_HIPROC	0xff1f		/*   specific section indexes */
  12.222 +#define SHN_ABS		0xfff1		/* absolute value */
  12.223 +#define SHN_COMMON	0xfff2		/* common symbol */
  12.224 +#define SHN_HIRESERVE	0xffff		/* upper bounds of reserved indexes */
  12.225 +
  12.226 +/* sh_type */
  12.227 +#define SHT_NULL	0		/* inactive */
  12.228 +#define SHT_PROGBITS	1		/* program defined information */
  12.229 +#define SHT_SYMTAB	2		/* symbol table section */
  12.230 +#define SHT_STRTAB	3		/* string table section */
  12.231 +#define SHT_RELA	4		/* relocation section with addends*/
  12.232 +#define SHT_HASH	5		/* symbol hash table section */
  12.233 +#define SHT_DYNAMIC	6		/* dynamic section */
  12.234 +#define SHT_NOTE	7		/* note section */
  12.235 +#define SHT_NOBITS	8		/* no space section */
  12.236 +#define SHT_REL		9		/* relation section without addends */
  12.237 +#define SHT_SHLIB	10		/* reserved - purpose unknown */
  12.238 +#define SHT_DYNSYM	11		/* dynamic symbol table section */
  12.239 +#define SHT_NUM		12		/* number of section types */
  12.240 +#define SHT_LOPROC	0x70000000	/* reserved range for processor */
  12.241 +#define SHT_HIPROC	0x7fffffff	/*  specific section header types */
  12.242 +#define SHT_LOUSER	0x80000000	/* reserved range for application */
  12.243 +#define SHT_HIUSER	0xffffffff	/*  specific indexes */
  12.244 +
  12.245 +/* Section names */
  12.246 +#define ELF_BSS         ".bss"		/* uninitialized data */
  12.247 +#define ELF_DATA        ".data"		/* initialized data */
  12.248 +#define ELF_DEBUG       ".debug"	/* debug */
  12.249 +#define ELF_DYNAMIC     ".dynamic"	/* dynamic linking information */
  12.250 +#define ELF_DYNSTR      ".dynstr"	/* dynamic string table */
  12.251 +#define ELF_DYNSYM      ".dynsym"	/* dynamic symbol table */
  12.252 +#define ELF_FINI        ".fini"		/* termination code */
  12.253 +#define ELF_GOT         ".got"		/* global offset table */
  12.254 +#define ELF_HASH        ".hash"		/* symbol hash table */
  12.255 +#define ELF_INIT        ".init"		/* initialization code */
  12.256 +#define ELF_REL_DATA    ".rel.data"	/* relocation data */
  12.257 +#define ELF_REL_FINI    ".rel.fini"	/* relocation termination code */
  12.258 +#define ELF_REL_INIT    ".rel.init"	/* relocation initialization code */
  12.259 +#define ELF_REL_DYN     ".rel.dyn"	/* relocaltion dynamic link info */
  12.260 +#define ELF_REL_RODATA  ".rel.rodata"	/* relocation read-only data */
  12.261 +#define ELF_REL_TEXT    ".rel.text"	/* relocation code */
  12.262 +#define ELF_RODATA      ".rodata"	/* read-only data */
  12.263 +#define ELF_SHSTRTAB    ".shstrtab"	/* section header string table */
  12.264 +#define ELF_STRTAB      ".strtab"	/* string table */
  12.265 +#define ELF_SYMTAB      ".symtab"	/* symbol table */
  12.266 +#define ELF_TEXT        ".text"		/* code */
  12.267 +
  12.268 +
  12.269 +/* Section Attribute Flags - sh_flags */
  12.270 +#define SHF_WRITE	0x1		/* Writable */
  12.271 +#define SHF_ALLOC	0x2		/* occupies memory */
  12.272 +#define SHF_EXECINSTR	0x4		/* executable */
  12.273 +#define SHF_MASKPROC	0xf0000000	/* reserved bits for processor */
  12.274 +					/*  specific section attributes */
  12.275 +
  12.276 +/* Symbol Table Entry */
  12.277 +typedef struct elf32_sym {
  12.278 +	Elf32_Word	st_name;	/* name - index into string table */
  12.279 +	Elf32_Addr	st_value;	/* symbol value */
  12.280 +	Elf32_Word	st_size;	/* symbol size */
  12.281 +	unsigned char	st_info;	/* type and binding */
  12.282 +	unsigned char	st_other;	/* 0 - no defined meaning */
  12.283 +	Elf32_Half	st_shndx;	/* section header index */
  12.284 +} Elf32_Sym;
  12.285 +
  12.286 +typedef struct {
  12.287 +	Elf64_Half	st_name;	/* Symbol name index in str table */
  12.288 +	Elf_Byte	st_info;	/* type / binding attrs */
  12.289 +	Elf_Byte	st_other;	/* unused */
  12.290 +	Elf64_Quarter	st_shndx;	/* section index of symbol */
  12.291 +	Elf64_Xword	st_value;	/* value of symbol */
  12.292 +	Elf64_Xword	st_size;	/* size of symbol */
  12.293 +} Elf64_Sym;
  12.294 +
  12.295 +/* Symbol table index */
  12.296 +#define STN_UNDEF	0		/* undefined */
  12.297 +
  12.298 +/* Extract symbol info - st_info */
  12.299 +#define ELF32_ST_BIND(x)	((x) >> 4)
  12.300 +#define ELF32_ST_TYPE(x)	(((unsigned int) x) & 0xf)
  12.301 +#define ELF32_ST_INFO(b,t)	(((b) << 4) + ((t) & 0xf))
  12.302 +
  12.303 +#define ELF64_ST_BIND(x)	((x) >> 4)
  12.304 +#define ELF64_ST_TYPE(x)	(((unsigned int) x) & 0xf)
  12.305 +#define ELF64_ST_INFO(b,t)	(((b) << 4) + ((t) & 0xf))
  12.306 +
  12.307 +/* Symbol Binding - ELF32_ST_BIND - st_info */
  12.308 +#define STB_LOCAL	0		/* Local symbol */
  12.309 +#define STB_GLOBAL	1		/* Global symbol */
  12.310 +#define STB_WEAK	2		/* like global - lower precedence */
  12.311 +#define STB_NUM		3		/* number of symbol bindings */
  12.312 +#define STB_LOPROC	13		/* reserved range for processor */
  12.313 +#define STB_HIPROC	15		/*  specific symbol bindings */
  12.314 +
  12.315 +/* Symbol type - ELF32_ST_TYPE - st_info */
  12.316 +#define STT_NOTYPE	0		/* not specified */
  12.317 +#define STT_OBJECT	1		/* data object */
  12.318 +#define STT_FUNC	2		/* function */
  12.319 +#define STT_SECTION	3		/* section */
  12.320 +#define STT_FILE	4		/* file */
  12.321 +#define STT_NUM		5		/* number of symbol types */
  12.322 +#define STT_LOPROC	13		/* reserved range for processor */
  12.323 +#define STT_HIPROC	15		/*  specific symbol types */
  12.324 +
  12.325 +/* Relocation entry with implicit addend */
  12.326 +typedef struct {
  12.327 +	Elf32_Addr	r_offset;	/* offset of relocation */
  12.328 +	Elf32_Word	r_info;		/* symbol table index and type */
  12.329 +} Elf32_Rel;
  12.330 +
  12.331 +/* Relocation entry with explicit addend */
  12.332 +typedef struct {
  12.333 +	Elf32_Addr	r_offset;	/* offset of relocation */
  12.334 +	Elf32_Word	r_info;		/* symbol table index and type */
  12.335 +	Elf32_Sword	r_addend;
  12.336 +} Elf32_Rela;
  12.337 +
  12.338 +/* Extract relocation info - r_info */
  12.339 +#define ELF32_R_SYM(i)		((i) >> 8)
  12.340 +#define ELF32_R_TYPE(i)		((unsigned char) (i))
  12.341 +#define ELF32_R_INFO(s,t) 	(((s) << 8) + (unsigned char)(t))
  12.342 +
  12.343 +typedef struct {
  12.344 +	Elf64_Xword	r_offset;	/* where to do it */
  12.345 +	Elf64_Xword	r_info;		/* index & type of relocation */
  12.346 +} Elf64_Rel;
  12.347 +
  12.348 +typedef struct {
  12.349 +	Elf64_Xword	r_offset;	/* where to do it */
  12.350 +	Elf64_Xword	r_info;		/* index & type of relocation */
  12.351 +	Elf64_Sxword	r_addend;	/* adjustment value */
  12.352 +} Elf64_Rela;
  12.353 +
  12.354 +#define	ELF64_R_SYM(info)	((info) >> 32)
  12.355 +#define	ELF64_R_TYPE(info)	((info) & 0xFFFFFFFF)
  12.356 +#define ELF64_R_INFO(s,t) 	(((s) << 32) + (u_int32_t)(t))
  12.357 +
  12.358 +/* Program Header */
  12.359 +typedef struct {
  12.360 +	Elf32_Word	p_type;		/* segment type */
  12.361 +	Elf32_Off	p_offset;	/* segment offset */
  12.362 +	Elf32_Addr	p_vaddr;	/* virtual address of segment */
  12.363 +	Elf32_Addr	p_paddr;	/* physical address - ignored? */
  12.364 +	Elf32_Word	p_filesz;	/* number of bytes in file for seg. */
  12.365 +	Elf32_Word	p_memsz;	/* number of bytes in mem. for seg. */
  12.366 +	Elf32_Word	p_flags;	/* flags */
  12.367 +	Elf32_Word	p_align;	/* memory alignment */
  12.368 +} Elf32_Phdr;
  12.369 +
  12.370 +typedef struct {
  12.371 +	Elf64_Half	p_type;		/* entry type */
  12.372 +	Elf64_Half	p_flags;	/* flags */
  12.373 +	Elf64_Off	p_offset;	/* offset */
  12.374 +	Elf64_Addr	p_vaddr;	/* virtual address */
  12.375 +	Elf64_Addr	p_paddr;	/* physical address */
  12.376 +	Elf64_Xword	p_filesz;	/* file size */
  12.377 +	Elf64_Xword	p_memsz;	/* memory size */
  12.378 +	Elf64_Xword	p_align;	/* memory & file alignment */
  12.379 +} Elf64_Phdr;
  12.380 +
  12.381 +/* Segment types - p_type */
  12.382 +#define PT_NULL		0		/* unused */
  12.383 +#define PT_LOAD		1		/* loadable segment */
  12.384 +#define PT_DYNAMIC	2		/* dynamic linking section */
  12.385 +#define PT_INTERP	3		/* the RTLD */
  12.386 +#define PT_NOTE		4		/* auxiliary information */
  12.387 +#define PT_SHLIB	5		/* reserved - purpose undefined */
  12.388 +#define PT_PHDR		6		/* program header */
  12.389 +#define PT_NUM		7		/* Number of segment types */
  12.390 +#define PT_LOPROC	0x70000000	/* reserved range for processor */
  12.391 +#define PT_HIPROC	0x7fffffff	/*  specific segment types */
  12.392 +
  12.393 +/* Segment flags - p_flags */
  12.394 +#define PF_X		0x1		/* Executable */
  12.395 +#define PF_W		0x2		/* Writable */
  12.396 +#define PF_R		0x4		/* Readable */
  12.397 +#define PF_MASKPROC	0xf0000000	/* reserved bits for processor */
  12.398 +					/*  specific segment flags */
  12.399 +
  12.400 +/* Dynamic structure */
  12.401 +typedef struct {
  12.402 +	Elf32_Sword	d_tag;		/* controls meaning of d_val */
  12.403 +	union {
  12.404 +		Elf32_Word	d_val;	/* Multiple meanings - see d_tag */
  12.405 +		Elf32_Addr	d_ptr;	/* program virtual address */
  12.406 +	} d_un;
  12.407 +} Elf32_Dyn;
  12.408 +
  12.409 +typedef struct {
  12.410 +	Elf64_Xword	d_tag;		/* controls meaning of d_val */
  12.411 +	union {
  12.412 +		Elf64_Addr	d_ptr;
  12.413 +		Elf64_Xword	d_val;
  12.414 +	} d_un;
  12.415 +} Elf64_Dyn;
  12.416 +
  12.417 +/* Dynamic Array Tags - d_tag */
  12.418 +#define DT_NULL		0		/* marks end of _DYNAMIC array */
  12.419 +#define DT_NEEDED	1		/* string table offset of needed lib */
  12.420 +#define DT_PLTRELSZ	2		/* size of relocation entries in PLT */
  12.421 +#define DT_PLTGOT	3		/* address PLT/GOT */
  12.422 +#define DT_HASH		4		/* address of symbol hash table */
  12.423 +#define DT_STRTAB	5		/* address of string table */
  12.424 +#define DT_SYMTAB	6		/* address of symbol table */
  12.425 +#define DT_RELA		7		/* address of relocation table */
  12.426 +#define DT_RELASZ	8		/* size of relocation table */
  12.427 +#define DT_RELAENT	9		/* size of relocation entry */
  12.428 +#define DT_STRSZ	10		/* size of string table */
  12.429 +#define DT_SYMENT	11		/* size of symbol table entry */
  12.430 +#define DT_INIT		12		/* address of initialization func. */
  12.431 +#define DT_FINI		13		/* address of termination function */
  12.432 +#define DT_SONAME	14		/* string table offset of shared obj */
  12.433 +#define DT_RPATH	15		/* string table offset of library
  12.434 +					   search path */
  12.435 +#define DT_SYMBOLIC	16		/* start sym search in shared obj. */
  12.436 +#define DT_REL		17		/* address of rel. tbl. w addends */
  12.437 +#define DT_RELSZ	18		/* size of DT_REL relocation table */
  12.438 +#define DT_RELENT	19		/* size of DT_REL relocation entry */
  12.439 +#define DT_PLTREL	20		/* PLT referenced relocation entry */
  12.440 +#define DT_DEBUG	21		/* bugger */
  12.441 +#define DT_TEXTREL	22		/* Allow rel. mod. to unwritable seg */
  12.442 +#define DT_JMPREL	23		/* add. of PLT's relocation entries */
  12.443 +#define DT_BIND_NOW	24		/* Bind now regardless of env setting */
  12.444 +#define DT_NUM		25		/* Number used. */
  12.445 +#define DT_LOPROC	0x70000000	/* reserved range for processor */
  12.446 +#define DT_HIPROC	0x7fffffff	/*  specific dynamic array tags */
  12.447 +	
  12.448 +/* Standard ELF hashing function */
  12.449 +unsigned int elf_hash(const unsigned char *name);
  12.450 +
  12.451 +/*
  12.452 + * Note Definitions
  12.453 + */
  12.454 +typedef struct {
  12.455 +	Elf32_Word namesz;
  12.456 +	Elf32_Word descsz;
  12.457 +	Elf32_Word type;
  12.458 +} Elf32_Note;
  12.459 +
  12.460 +typedef struct {
  12.461 +	Elf64_Half namesz;
  12.462 +	Elf64_Half descsz;
  12.463 +	Elf64_Half type;
  12.464 +} Elf64_Note;
  12.465 +
  12.466 +
  12.467 +#if defined(ELFSIZE)
  12.468 +#define CONCAT(x,y)	__CONCAT(x,y)
  12.469 +#define ELFNAME(x)	CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
  12.470 +#define ELFNAME2(x,y)	CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
  12.471 +#define ELFNAMEEND(x)	CONCAT(x,CONCAT(_elf,ELFSIZE))
  12.472 +#define ELFDEFNNAME(x)	CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
  12.473 +#endif
  12.474 +
  12.475 +#if defined(ELFSIZE) && (ELFSIZE == 32)
  12.476 +#define Elf_Ehdr	Elf32_Ehdr
  12.477 +#define Elf_Phdr	Elf32_Phdr
  12.478 +#define Elf_Shdr	Elf32_Shdr
  12.479 +#define Elf_Sym		Elf32_Sym
  12.480 +#define Elf_Rel		Elf32_Rel
  12.481 +#define Elf_RelA	Elf32_Rela
  12.482 +#define Elf_Dyn		Elf32_Dyn
  12.483 +#define Elf_Word	Elf32_Word
  12.484 +#define Elf_Sword	Elf32_Sword
  12.485 +#define Elf_Addr	Elf32_Addr
  12.486 +#define Elf_Off		Elf32_Off
  12.487 +#define Elf_Nhdr	Elf32_Nhdr
  12.488 +#define Elf_Note	Elf32_Note
  12.489 +
  12.490 +#define ELF_R_SYM	ELF32_R_SYM
  12.491 +#define ELF_R_TYPE	ELF32_R_TYPE
  12.492 +#define ELF_R_INFO	ELF32_R_INFO
  12.493 +#define ELFCLASS	ELFCLASS32
  12.494 +
  12.495 +#define ELF_ST_BIND	ELF32_ST_BIND
  12.496 +#define ELF_ST_TYPE	ELF32_ST_TYPE
  12.497 +#define ELF_ST_INFO	ELF32_ST_INFO
  12.498 +
  12.499 +#define AuxInfo		Aux32Info
  12.500 +#elif defined(ELFSIZE) && (ELFSIZE == 64)
  12.501 +#define Elf_Ehdr	Elf64_Ehdr
  12.502 +#define Elf_Phdr	Elf64_Phdr
  12.503 +#define Elf_Shdr	Elf64_Shdr
  12.504 +#define Elf_Sym		Elf64_Sym
  12.505 +#define Elf_Rel		Elf64_Rel
  12.506 +#define Elf_RelA	Elf64_Rela
  12.507 +#define Elf_Dyn		Elf64_Dyn
  12.508 +#define Elf_Word	Elf64_Word
  12.509 +#define Elf_Sword	Elf64_Sword
  12.510 +#define Elf_Addr	Elf64_Addr
  12.511 +#define Elf_Off		Elf64_Off
  12.512 +#define Elf_Nhdr	Elf64_Nhdr
  12.513 +#define Elf_Note	Elf64_Note
  12.514 +
  12.515 +#define ELF_R_SYM	ELF64_R_SYM
  12.516 +#define ELF_R_TYPE	ELF64_R_TYPE
  12.517 +#define ELF_R_INFO	ELF64_R_INFO
  12.518 +#define ELFCLASS	ELFCLASS64
  12.519 +
  12.520 +#define ELF_ST_BIND	ELF64_ST_BIND
  12.521 +#define ELF_ST_TYPE	ELF64_ST_TYPE
  12.522 +#define ELF_ST_INFO	ELF64_ST_INFO
  12.523 +
  12.524 +#define AuxInfo		Aux64Info
  12.525 +#endif
  12.526 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/xc/lib/xc_netbsd_build.c	Mon Feb 09 13:39:44 2004 +0000
    13.3 @@ -0,0 +1,694 @@
    13.4 +/******************************************************************************
    13.5 + * xc_netbsd_build.c
    13.6 + */
    13.7 +
    13.8 +#include "xc_private.h"
    13.9 +#define ELFSIZE 32		/* XXX */
   13.10 +#include "xc_elf.h"
   13.11 +#include <zlib.h>
   13.12 +
   13.13 +/* #define DEBUG 1 */
   13.14 +
   13.15 +#ifdef DEBUG
   13.16 +#define DPRINTF(x) printf x
   13.17 +#else
   13.18 +#define DPRINTF(x)
   13.19 +#endif
   13.20 +
   13.21 +static int loadelfimage(gzFile, int, unsigned long *, unsigned long,
   13.22 +			unsigned long *, unsigned long *,
   13.23 +			unsigned long *, unsigned long *);
   13.24 +
   13.25 +#define ELFROUND (ELFSIZE / 8)
   13.26 +
   13.27 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   13.28 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   13.29 +
   13.30 +static long get_tot_pages(int xc_handle, int domid)
   13.31 +{
   13.32 +    dom0_op_t op;
   13.33 +    op.cmd = DOM0_GETDOMAININFO;
   13.34 +    op.u.getdomaininfo.domain = domid;
   13.35 +    return (do_dom0_op(xc_handle, &op) < 0) ? 
   13.36 +        -1 : op.u.getdomaininfo.tot_pages;
   13.37 +}
   13.38 +
   13.39 +static int get_pfn_list(int xc_handle,
   13.40 +                        int domid, 
   13.41 +                        unsigned long *pfn_buf, 
   13.42 +                        unsigned long max_pfns)
   13.43 +{
   13.44 +    dom0_op_t op;
   13.45 +    int ret;
   13.46 +    op.cmd = DOM0_GETMEMLIST;
   13.47 +    op.u.getmemlist.domain   = domid;
   13.48 +    op.u.getmemlist.max_pfns = max_pfns;
   13.49 +    op.u.getmemlist.buffer   = pfn_buf;
   13.50 +
   13.51 +    if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 )
   13.52 +        return -1;
   13.53 +
   13.54 +    ret = do_dom0_op(xc_handle, &op);
   13.55 +
   13.56 +    (void)munlock(pfn_buf, max_pfns * sizeof(unsigned long));
   13.57 +
   13.58 +    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   13.59 +}
   13.60 +
   13.61 +static int send_pgupdates(int xc_handle, mmu_update_t *updates, int nr_updates)
   13.62 +{
   13.63 +    int ret = -1;
   13.64 +    privcmd_hypercall_t hypercall;
   13.65 +
   13.66 +    hypercall.op     = __HYPERVISOR_mmu_update;
   13.67 +    hypercall.arg[0] = (unsigned long)updates;
   13.68 +    hypercall.arg[1] = (unsigned long)nr_updates;
   13.69 +
   13.70 +    if ( mlock(updates, nr_updates * sizeof(*updates)) != 0 )
   13.71 +        goto out1;
   13.72 +
   13.73 +    if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
   13.74 +        goto out2;
   13.75 +
   13.76 +    ret = 0;
   13.77 +
   13.78 + out2: (void)munlock(updates, nr_updates * sizeof(*updates));
   13.79 + out1: return ret;
   13.80 +}
   13.81 +
   13.82 +static int setup_guestos(int xc_handle,
   13.83 +                         int dom, 
   13.84 +                         gzFile kernel_gfd, 
   13.85 +                         unsigned long tot_pages,
   13.86 +                         unsigned long *virt_startinfo_addr, 
   13.87 +                         unsigned long *virt_load_addr, 
   13.88 +                         dom0_builddomain_t *builddomain, 
   13.89 +                         const char *cmdline,
   13.90 +                         unsigned long shared_info_frame)
   13.91 +{
   13.92 +    l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
   13.93 +    l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
   13.94 +    unsigned long *page_array = NULL;
   13.95 +    mmu_update_t *pgt_update_arr = NULL, *pgt_updates = NULL;
   13.96 +    int alloc_index, num_pt_pages;
   13.97 +    unsigned long l2tab;
   13.98 +    unsigned long l1tab = 0;
   13.99 +    unsigned long num_pgt_updates = 0;
  13.100 +    unsigned long count, pt_start;
  13.101 +    unsigned long symtab_addr = 0, symtab_len = 0;
  13.102 +    start_info_t *start_info;
  13.103 +    shared_info_t *shared_info;
  13.104 +    unsigned long ksize;
  13.105 +    int pm_handle;
  13.106 +
  13.107 +    memset(builddomain, 0, sizeof(*builddomain));
  13.108 +
  13.109 +    if ( (pm_handle = init_pfn_mapper()) < 0 )
  13.110 +        goto error_out;
  13.111 +
  13.112 +    pgt_updates = malloc((tot_pages + 1024) * 3 * sizeof(mmu_update_t));
  13.113 +    page_array = malloc(tot_pages * sizeof(unsigned long));
  13.114 +    pgt_update_arr = pgt_updates;
  13.115 +    if ( (pgt_update_arr == NULL) || (page_array == NULL) )
  13.116 +    {
  13.117 +        PERROR("Could not allocate memory");
  13.118 +        goto error_out;
  13.119 +    }
  13.120 +
  13.121 +    if ( get_pfn_list(xc_handle, dom, page_array, tot_pages) != tot_pages )
  13.122 +    {
  13.123 +        PERROR("Could not get the page frame list");
  13.124 +        goto error_out;
  13.125 +    }
  13.126 +
  13.127 +    if (loadelfimage(kernel_gfd, pm_handle, page_array, tot_pages,
  13.128 +		     virt_load_addr, &ksize, &symtab_addr, &symtab_len))
  13.129 +	goto error_out;
  13.130 +
  13.131 +    /* ksize is kernel-image size rounded up to a page boundary. */
  13.132 +
  13.133 +    alloc_index = tot_pages - 1;
  13.134 +
  13.135 +    /* Count bottom-level PTs, rounding up. */
  13.136 +    num_pt_pages = (l1_table_offset(*virt_load_addr) + tot_pages + 1023) / 1024;
  13.137 +
  13.138 +    /* We must also count the page directory. */
  13.139 +    num_pt_pages++;
  13.140 +
  13.141 +    /* Index of first PT page. */
  13.142 +    pt_start = tot_pages - num_pt_pages;
  13.143 +
  13.144 +    /*
  13.145 +     * First allocate page for page dir. Allocation goes backwards from the end
  13.146 +     * of the allocated physical address space.
  13.147 +     */
  13.148 +    l2tab = page_array[alloc_index] << PAGE_SHIFT;
  13.149 +    alloc_index--;
  13.150 +    builddomain->ctxt.pt_base = l2tab;
  13.151 +
  13.152 +    /*
  13.153 +     * Pin down l2tab addr as page dir page - causes hypervisor to provide
  13.154 +     * correct protection for the page
  13.155 +     */ 
  13.156 +    pgt_updates->ptr = l2tab | MMU_EXTENDED_COMMAND;
  13.157 +    pgt_updates->val = MMUEXT_PIN_L2_TABLE;
  13.158 +    pgt_updates++;
  13.159 +    num_pgt_updates++;
  13.160 +
  13.161 +    /* Initialise the page tables. */
  13.162 +    if ( (vl2tab = map_pfn(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
  13.163 +        goto error_out;
  13.164 +    memset(vl2tab, 0, PAGE_SIZE);
  13.165 +    vl2e = vl2tab + l2_table_offset(*virt_load_addr);
  13.166 +    for ( count = 0; count < tot_pages; count++ )
  13.167 +    {    
  13.168 +        if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) 
  13.169 +        {
  13.170 +            l1tab = page_array[alloc_index] << PAGE_SHIFT;
  13.171 +            if ( (vl1tab = map_pfn(pm_handle, l1tab >> PAGE_SHIFT)) == NULL )
  13.172 +                goto error_out;
  13.173 +            memset(vl1tab, 0, PAGE_SIZE);
  13.174 +            alloc_index--;
  13.175 +		
  13.176 +            vl1e = vl1tab + l1_table_offset(*virt_load_addr + 
  13.177 +                                            (count << PAGE_SHIFT));
  13.178 +
  13.179 +            /* make apropriate entry in the page directory */
  13.180 +            pgt_updates->ptr = (unsigned long)vl2e;
  13.181 +            pgt_updates->val = l1tab | L2_PROT;
  13.182 +            pgt_updates++;
  13.183 +            num_pgt_updates++;
  13.184 +            vl2e++;
  13.185 +        }
  13.186 +
  13.187 +        if ( count < pt_start )
  13.188 +        {
  13.189 +            pgt_updates->ptr = (unsigned long)vl1e;
  13.190 +            pgt_updates->val = (page_array[count] << PAGE_SHIFT) | L1_PROT;
  13.191 +            pgt_updates++;
  13.192 +            num_pgt_updates++;
  13.193 +            vl1e++;
  13.194 +        }
  13.195 +        else
  13.196 +        {
  13.197 +            pgt_updates->ptr = (unsigned long)vl1e;
  13.198 +            pgt_updates->val = 
  13.199 +                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
  13.200 +            pgt_updates++;
  13.201 +            num_pgt_updates++;
  13.202 +            vl1e++;
  13.203 +        }
  13.204 +
  13.205 +        pgt_updates->ptr = 
  13.206 +            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
  13.207 +        pgt_updates->val = count;
  13.208 +        pgt_updates++;
  13.209 +        num_pgt_updates++;
  13.210 +    }
  13.211 +
  13.212 +    *virt_startinfo_addr =
  13.213 +        *virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
  13.214 +
  13.215 +    start_info = map_pfn(pm_handle, page_array[alloc_index-1]);
  13.216 +    memset(start_info, 0, sizeof(*start_info));
  13.217 +    start_info->pt_base     = *virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
  13.218 +    start_info->mod_start   = symtab_addr;
  13.219 +    start_info->mod_len     = symtab_len;
  13.220 +    start_info->nr_pages    = tot_pages;
  13.221 +    start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  13.222 +    start_info->dom_id      = dom;
  13.223 +    start_info->flags       = 0;
  13.224 +    strncpy(start_info->cmd_line, cmdline, MAX_CMD_LEN);
  13.225 +    start_info->cmd_line[MAX_CMD_LEN-1] = '\0';
  13.226 +
  13.227 +    unmap_pfn(pm_handle, start_info);
  13.228 +
  13.229 +    /* shared_info page starts its life empty. */
  13.230 +    shared_info = map_pfn(pm_handle, shared_info_frame);
  13.231 +    memset(shared_info, 0, PAGE_SIZE);
  13.232 +    unmap_pfn(pm_handle, shared_info);
  13.233 +
  13.234 +    /* Send the page update requests down to the hypervisor. */
  13.235 +    if ( send_pgupdates(xc_handle, pgt_update_arr, num_pgt_updates) < 0 )
  13.236 +        goto error_out;
  13.237 +
  13.238 +    free(page_array);
  13.239 +    free(pgt_update_arr);
  13.240 +    return 0;
  13.241 +
  13.242 + error_out:
  13.243 +    if ( pm_handle >= 0 )
  13.244 +        (void)close_pfn_mapper(pm_handle);
  13.245 +    if ( page_array == NULL )
  13.246 +        free(page_array);
  13.247 +    if ( pgt_update_arr == NULL )
  13.248 +        free(pgt_update_arr);
  13.249 +    return -1;
  13.250 +}
  13.251 +
  13.252 +int xc_netbsd_build(int xc_handle,
  13.253 +		    unsigned int domid,
  13.254 +		    const char *image_name,
  13.255 +		    const char *cmdline)
  13.256 +{
  13.257 +    dom0_op_t launch_op, op;
  13.258 +    unsigned long load_addr;
  13.259 +    long tot_pages;
  13.260 +    int kernel_fd = -1;
  13.261 +    gzFile kernel_gfd = NULL;
  13.262 +    int rc, i;
  13.263 +    full_execution_context_t *ctxt;
  13.264 +    unsigned long virt_startinfo_addr;
  13.265 +
  13.266 +    if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
  13.267 +    {
  13.268 +        PERROR("Could not find total pages for domain");
  13.269 +        return 1;
  13.270 +    }
  13.271 +
  13.272 +    kernel_fd = open(image_name, O_RDONLY);
  13.273 +    if ( kernel_fd < 0 )
  13.274 +    {
  13.275 +        PERROR("Could not open kernel image");
  13.276 +        return 1;
  13.277 +    }
  13.278 +
  13.279 +    if ( (kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL )
  13.280 +    {
  13.281 +        PERROR("Could not allocate decompression state for state file");
  13.282 +        close(kernel_fd);
  13.283 +        return 1;
  13.284 +    }
  13.285 +
  13.286 +    op.cmd = DOM0_GETDOMAININFO;
  13.287 +    op.u.getdomaininfo.domain = domid;
  13.288 +    if ( (do_dom0_op(xc_handle, &op) < 0) || 
  13.289 +         (op.u.getdomaininfo.domain != domid) )
  13.290 +    {
  13.291 +        PERROR("Could not get info on domain");
  13.292 +        goto error_out;
  13.293 +    }
  13.294 +    if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
  13.295 +         (op.u.getdomaininfo.ctxt.pt_base != 0) )
  13.296 +    {
  13.297 +        ERROR("Domain is already constructed");
  13.298 +        goto error_out;
  13.299 +    }
  13.300 +
  13.301 +    if ( setup_guestos(xc_handle, domid, kernel_gfd, tot_pages,
  13.302 +                       &virt_startinfo_addr,
  13.303 +                       &load_addr, &launch_op.u.builddomain, cmdline,
  13.304 +                       op.u.getdomaininfo.shared_info_frame) < 0 )
  13.305 +    {
  13.306 +        ERROR("Error constructing guest OS");
  13.307 +        goto error_out;
  13.308 +    }
  13.309 +
  13.310 +    if ( kernel_fd >= 0 )
  13.311 +        close(kernel_fd);
  13.312 +    if( kernel_gfd )
  13.313 +	gzclose(kernel_gfd);
  13.314 +
  13.315 +    ctxt = &launch_op.u.builddomain.ctxt;
  13.316 +
  13.317 +    ctxt->flags = 0;
  13.318 +
  13.319 +    /*
  13.320 +     * Initial register values:
  13.321 +     *  DS,ES,FS,GS = FLAT_RING1_DS
  13.322 +     *       CS:EIP = FLAT_RING1_CS:start_pc
  13.323 +     *       SS:ESP = FLAT_RING1_DS:start_stack
  13.324 +     *          ESI = start_info
  13.325 +     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
  13.326 +     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
  13.327 +     */
  13.328 +    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
  13.329 +    ctxt->i386_ctxt.es = FLAT_RING1_DS;
  13.330 +    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
  13.331 +    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
  13.332 +    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
  13.333 +    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
  13.334 +    ctxt->i386_ctxt.eip = load_addr;
  13.335 +    ctxt->i386_ctxt.esp = virt_startinfo_addr;
  13.336 +    ctxt->i386_ctxt.esi = virt_startinfo_addr;
  13.337 +    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
  13.338 +
  13.339 +    /* FPU is set up to default initial state. */
  13.340 +    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
  13.341 +
  13.342 +    /* Virtual IDT is empty at start-of-day. */
  13.343 +    for ( i = 0; i < 256; i++ )
  13.344 +    {
  13.345 +        ctxt->trap_ctxt[i].vector = i;
  13.346 +        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
  13.347 +    }
  13.348 +    ctxt->fast_trap_idx = 0;
  13.349 +
  13.350 +    /* No LDT. */
  13.351 +    ctxt->ldt_ents = 0;
  13.352 +    
  13.353 +    /* Use the default Xen-provided GDT. */
  13.354 +    ctxt->gdt_ents = 0;
  13.355 +
  13.356 +    /* Ring 1 stack is the initial stack. */
  13.357 +    ctxt->ring1_ss  = FLAT_RING1_DS;
  13.358 +    ctxt->ring1_esp = virt_startinfo_addr;
  13.359 +
  13.360 +    /* No debugging. */
  13.361 +    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
  13.362 +
  13.363 +    /* No callback handlers. */
  13.364 +    ctxt->event_callback_cs     = FLAT_RING1_CS;
  13.365 +    ctxt->event_callback_eip    = 0;
  13.366 +    ctxt->failsafe_callback_cs  = FLAT_RING1_CS;
  13.367 +    ctxt->failsafe_callback_eip = 0;
  13.368 +
  13.369 +    launch_op.u.builddomain.domain   = domid;
  13.370 +    launch_op.u.builddomain.num_vifs = 1;
  13.371 +
  13.372 +    launch_op.cmd = DOM0_BUILDDOMAIN;
  13.373 +    rc = do_dom0_op(xc_handle, &launch_op);
  13.374 +    
  13.375 +    return rc;
  13.376 +
  13.377 + error_out:
  13.378 +    if ( kernel_fd >= 0 )
  13.379 +        close(kernel_fd);
  13.380 +    if( kernel_gfd )
  13.381 +	gzclose(kernel_gfd);
  13.382 +
  13.383 +    return -1;
  13.384 +}
  13.385 +
  13.386 +#define MYSEEK_BUFSIZE 1024
  13.387 +static off_t
  13.388 +myseek(gzFile gfd, off_t offset, int whence)
  13.389 +{
  13.390 +    unsigned char tmp[MYSEEK_BUFSIZE];
  13.391 +    int c;
  13.392 +
  13.393 +    if (offset < 0) {
  13.394 +	ERROR("seek back not supported");
  13.395 +	return -1;
  13.396 +    }
  13.397 +
  13.398 +    while (offset) {
  13.399 +	c = offset;
  13.400 +	if (c > MYSEEK_BUFSIZE)
  13.401 +	    c = MYSEEK_BUFSIZE;
  13.402 +	if (gzread(gfd, tmp, c) != c) {
  13.403 +	    PERROR("Error seeking in image.");
  13.404 +	    return -1;
  13.405 +	}
  13.406 +	offset -= c;
  13.407 +    }
  13.408 +
  13.409 +    return 0;			/* XXX */
  13.410 +}
  13.411 +
  13.412 +/* 
  13.413 + * NetBSD memory layout:
  13.414 + *
  13.415 + * ---------------- *virt_load_addr = ehdr.e_entry (0xc0100000)
  13.416 + * | kernel text  |
  13.417 + * |              |
  13.418 + * ----------------
  13.419 + * | kernel data  |
  13.420 + * |              |
  13.421 + * ----------------
  13.422 + * | kernel bss   |
  13.423 + * |              |
  13.424 + * ---------------- *symtab_addr
  13.425 + * | symtab size  |   = *symtab_len
  13.426 + * ----------------
  13.427 + * | elf header   |   offsets to symbol sections mangled to be relative
  13.428 + * |              |   to headers location
  13.429 + * ----------------
  13.430 + * | sym section  |
  13.431 + * | headers      |
  13.432 + * ----------------
  13.433 + * | sym sections |
  13.434 + * |              |
  13.435 + * ---------------- *symtab_addr + *symtab_len
  13.436 + * | padding      |
  13.437 + * ---------------- ehdr.e_entry + *ksize << PAGE_SHIFT
  13.438 + */
  13.439 +
  13.440 +#define IS_TEXT(p)	(p.p_flags & PF_X)
  13.441 +#define IS_DATA(p)	(p.p_flags & PF_W)
  13.442 +#define IS_BSS(p)	(p.p_filesz < p.p_memsz)
  13.443 +
  13.444 +static int
  13.445 +loadelfimage(gzFile kernel_gfd, int pm_handle, unsigned long *page_array,
  13.446 +	     unsigned long tot_pages, unsigned long *virt_load_addr,
  13.447 +	     unsigned long *ksize, unsigned long *symtab_addr,
  13.448 +	     unsigned long *symtab_len)
  13.449 +{
  13.450 +    Elf_Ehdr ehdr;
  13.451 +    Elf_Phdr *phdr;
  13.452 +    Elf_Shdr *shdr;
  13.453 +    void *vaddr;
  13.454 +    char page[PAGE_SIZE], *p;
  13.455 +    unsigned long iva, maxva, symva;
  13.456 +    int c, curpos, h, i, ret, s;
  13.457 +
  13.458 +    ret = -1;
  13.459 +    phdr = NULL;
  13.460 +    p = NULL;
  13.461 +    maxva = 0;
  13.462 +
  13.463 +    if (gzread(kernel_gfd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr)) {
  13.464 +	PERROR("Error reading kernel image ELF header.");
  13.465 +	goto out;
  13.466 +    }
  13.467 +    curpos = sizeof(Elf_Ehdr);
  13.468 +
  13.469 +    if (!IS_ELF(ehdr)) {
  13.470 +	PERROR("Image does not have an ELF header.");
  13.471 +	goto out;
  13.472 +    }
  13.473 +
  13.474 +    *virt_load_addr = ehdr.e_entry;
  13.475 +
  13.476 +    if ((*virt_load_addr & (PAGE_SIZE-1)) != 0) {
  13.477 +        ERROR("We can only deal with page-aligned load addresses");
  13.478 +        goto out;
  13.479 +    }
  13.480 +
  13.481 +    if ((*virt_load_addr + (tot_pages << PAGE_SHIFT)) >
  13.482 +	HYPERVISOR_VIRT_START) {
  13.483 +        ERROR("Cannot map all domain memory without hitting Xen space");
  13.484 +        goto out;
  13.485 +    }
  13.486 +
  13.487 +
  13.488 +    phdr = malloc(ehdr.e_phnum * sizeof(Elf_Phdr));
  13.489 +    if (phdr == NULL) {
  13.490 +	ERROR("Cannot allocate memory for Elf_Phdrs");
  13.491 +	goto out;
  13.492 +    }
  13.493 +
  13.494 +    if (myseek(kernel_gfd, ehdr.e_phoff - curpos, SEEK_SET) == -1) {
  13.495 +	ERROR("Seek to program header failed");
  13.496 +	goto out;
  13.497 +    }
  13.498 +    curpos = ehdr.e_phoff;
  13.499 +
  13.500 +    if (gzread(kernel_gfd, phdr, ehdr.e_phnum * sizeof(Elf_Phdr)) !=
  13.501 +	ehdr.e_phnum * sizeof(Elf_Phdr)) {
  13.502 +	PERROR("Error reading kernel image ELF program header.");
  13.503 +	goto out;
  13.504 +    }
  13.505 +    curpos += ehdr.e_phnum * sizeof(Elf_Phdr);
  13.506 +
  13.507 +
  13.508 +    for (h = 0; h < ehdr.e_phnum; h++) {
  13.509 +	if (phdr[h].p_type != PT_LOAD ||
  13.510 +	    (phdr[h].p_flags & (PF_W|PF_X)) == 0)
  13.511 +	    continue;
  13.512 +
  13.513 +	if (IS_TEXT(phdr[h]) || IS_DATA(phdr[h])) {
  13.514 +	    if (myseek(kernel_gfd, phdr[h].p_offset - curpos, SEEK_SET) ==
  13.515 +		-1) {
  13.516 +		ERROR("Seek to section failed");
  13.517 +		goto out;
  13.518 +	    }
  13.519 +	    curpos = phdr[h].p_offset;
  13.520 +
  13.521 +	    for (iva = phdr[h].p_vaddr;
  13.522 +		 iva < phdr[h].p_vaddr + phdr[h].p_filesz; iva += c) {
  13.523 +		c = PAGE_SIZE - (iva & (PAGE_SIZE - 1));
  13.524 +		if (iva + c > phdr[h].p_vaddr + phdr[h].p_filesz)
  13.525 +		    c = phdr[h].p_vaddr + phdr[h].p_filesz - iva;
  13.526 +		if (gzread(kernel_gfd, page, c) != c) {
  13.527 +		    PERROR("Error reading kernel image page.");
  13.528 +		    goto out;
  13.529 +		}
  13.530 +		curpos += c;
  13.531 +		vaddr = map_pfn(pm_handle, page_array[(iva - *virt_load_addr)
  13.532 +						      >> PAGE_SHIFT]);
  13.533 +		if (vaddr == NULL) {
  13.534 +		    ERROR("Couldn't map guest memory");
  13.535 +		    goto out;
  13.536 +		}
  13.537 +		DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)iva,
  13.538 +			 vaddr + (iva & (PAGE_SIZE - 1)), c));
  13.539 +		memcpy(vaddr + (iva & (PAGE_SIZE - 1)), page, c);
  13.540 +		unmap_pfn(pm_handle, vaddr);
  13.541 +	    }
  13.542 +
  13.543 +	    if (phdr[h].p_vaddr + phdr[h].p_filesz > maxva)
  13.544 +		maxva = phdr[h].p_vaddr + phdr[h].p_filesz;
  13.545 +	}
  13.546 +
  13.547 +	if (IS_BSS(phdr[h])) {
  13.548 +	    /* XXX maybe clear phdr[h].p_memsz bytes from
  13.549 +	       phdr[h].p_vaddr + phdr[h].p_filesz ??? */
  13.550 +	    if (phdr[h].p_vaddr + phdr[h].p_memsz > maxva)
  13.551 +		maxva = phdr[h].p_vaddr + phdr[h].p_memsz;
  13.552 +	    DPRINTF(("bss from %p to %p, maxva %p\n",
  13.553 +		     (void *)(phdr[h].p_vaddr + phdr[h].p_filesz),
  13.554 +		     (void *)(phdr[h].p_vaddr + phdr[h].p_memsz),
  13.555 +		     (void *)maxva));
  13.556 +	}
  13.557 +    }
  13.558 +
  13.559 +    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
  13.560 +	       ehdr.e_shnum * sizeof(Elf_Shdr));
  13.561 +    if (p == NULL) {
  13.562 +	ERROR("Cannot allocate memory for Elf_Shdrs");
  13.563 +	goto out;
  13.564 +    }
  13.565 +
  13.566 +    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
  13.567 +
  13.568 +    if (myseek(kernel_gfd, ehdr.e_shoff - curpos, SEEK_SET) == -1) {
  13.569 +	ERROR("Seek to symbol header failed");
  13.570 +	goto out;
  13.571 +    }
  13.572 +    curpos = ehdr.e_shoff;
  13.573 +
  13.574 +    if (gzread(kernel_gfd, shdr, ehdr.e_shnum * sizeof(Elf_Shdr)) !=
  13.575 +	ehdr.e_shnum * sizeof(Elf_Shdr)) {
  13.576 +	PERROR("Error reading kernel image ELF symbol header.");
  13.577 +	goto out;
  13.578 +    }
  13.579 +    curpos += ehdr.e_shnum * sizeof(Elf_Shdr);
  13.580 +
  13.581 +    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
  13.582 +    symva = maxva;
  13.583 +    maxva += sizeof(int);
  13.584 +    *symtab_addr = maxva;
  13.585 +    *symtab_len = 0;
  13.586 +    maxva += sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
  13.587 +    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
  13.588 +
  13.589 +    for (h = 0; h < ehdr.e_shnum; h++) {
  13.590 +	if (shdr[h].sh_type == SHT_STRTAB) {
  13.591 +	    for (i = 0; i < ehdr.e_shnum; i++)
  13.592 +		if (shdr[i].sh_type == SHT_SYMTAB &&
  13.593 +		    shdr[i].sh_link == h)
  13.594 +		    break;
  13.595 +	    if (i == ehdr.e_shnum) {
  13.596 +		shdr[h].sh_offset = 0;
  13.597 +		continue;
  13.598 +	    }
  13.599 +	}
  13.600 +
  13.601 +	if (shdr[h].sh_type == SHT_STRTAB ||
  13.602 +	    shdr[h].sh_type == SHT_SYMTAB) {
  13.603 +	    if (myseek(kernel_gfd, shdr[h].sh_offset - curpos, SEEK_SET) ==
  13.604 +		-1) {
  13.605 +		ERROR("Seek to symbol section failed");
  13.606 +		goto out;
  13.607 +	    }
  13.608 +	    curpos = shdr[h].sh_offset;
  13.609 +
  13.610 +	    shdr[h].sh_offset = maxva - *symtab_addr;
  13.611 +
  13.612 +	    DPRINTF(("copy section %d, size 0x%x\n", h, shdr[h].sh_size));
  13.613 +	    for (i = 0; i < shdr[h].sh_size; i += c, maxva += c) {
  13.614 +		c = PAGE_SIZE - (maxva & (PAGE_SIZE - 1));
  13.615 +		if (c > (shdr[h].sh_size - i))
  13.616 +		    c = shdr[h].sh_size - i;
  13.617 +		if (gzread(kernel_gfd, page, c) != c) {
  13.618 +		    PERROR("Error reading kernel image page.");
  13.619 +		    goto out;
  13.620 +		}
  13.621 +		curpos += c;
  13.622 +
  13.623 +		vaddr = map_pfn(pm_handle, page_array[(maxva - *virt_load_addr)
  13.624 +						      >> PAGE_SHIFT]);
  13.625 +		if (vaddr == NULL) {
  13.626 +		    ERROR("Couldn't map guest memory");
  13.627 +		    goto out;
  13.628 +		}
  13.629 +		DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)maxva,
  13.630 +			 vaddr + (maxva & (PAGE_SIZE - 1)), c));
  13.631 +		memcpy(vaddr + (maxva & (PAGE_SIZE - 1)), page, c);
  13.632 +		unmap_pfn(pm_handle, vaddr);
  13.633 +	    }
  13.634 +
  13.635 +	    *symtab_len += shdr[h].sh_size;
  13.636 +	    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
  13.637 +
  13.638 +	}
  13.639 +	shdr[h].sh_name = 0;
  13.640 +    }
  13.641 +
  13.642 +    if (*symtab_len == 0) {
  13.643 +	DPRINTF(("no symbol table\n"));
  13.644 +	*symtab_addr = 0;
  13.645 +	ret = 0;
  13.646 +	goto out;
  13.647 +    }
  13.648 +
  13.649 +    DPRINTF(("sym header va %p from %p/%p size %x/%x\n", (void *)symva,
  13.650 +	     shdr, p, ehdr.e_shnum * sizeof(Elf_Shdr),
  13.651 +	     ehdr.e_shnum * sizeof(Elf_Shdr) + sizeof(Elf_Ehdr)));
  13.652 +    ehdr.e_phoff = 0;
  13.653 +    ehdr.e_shoff = sizeof(Elf_Ehdr);
  13.654 +    ehdr.e_phentsize = 0;
  13.655 +    ehdr.e_phnum = 0;
  13.656 +    ehdr.e_shstrndx = SHN_UNDEF;
  13.657 +    memcpy(p + sizeof(int), &ehdr, sizeof(Elf_Ehdr));
  13.658 +    *(int *)p = maxva - *symtab_addr;
  13.659 +
  13.660 +    s = sizeof(int) + sizeof(Elf_Ehdr) + ehdr.e_shnum * sizeof(Elf_Shdr);
  13.661 +    for (i = 0; i < s; i += c, symva += c) {
  13.662 +	c = PAGE_SIZE - (symva & (PAGE_SIZE - 1));
  13.663 +	if (c > s - i)
  13.664 +	    c = s - i;
  13.665 +	vaddr = map_pfn(pm_handle, page_array[(symva - *virt_load_addr)
  13.666 +					      >> PAGE_SHIFT]);
  13.667 +	if (vaddr == NULL) {
  13.668 +	    ERROR("Couldn't map guest memory");
  13.669 +	    goto out;
  13.670 +	}
  13.671 +	DPRINTF(("copy page %p to %p, count 0x%x\n", (void *)symva,
  13.672 +		 vaddr + (symva & (PAGE_SIZE - 1)), c));
  13.673 +	memcpy(vaddr + (symva & (PAGE_SIZE - 1)), p + i,
  13.674 +	       c);
  13.675 +	unmap_pfn(pm_handle, vaddr);
  13.676 +    }
  13.677 +
  13.678 +    *symtab_len = maxva - *symtab_addr;
  13.679 +
  13.680 +    ret = 0;
  13.681 +
  13.682 +  out:
  13.683 +    if (ret == 0) {
  13.684 +	maxva = (maxva + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
  13.685 +	*ksize = (maxva - *virt_load_addr) >> PAGE_SHIFT;
  13.686 +
  13.687 +	DPRINTF(("virt_addr %p, kpages 0x%lx, symtab_addr %p, symtab_len %p\n",
  13.688 +		 (void *)*virt_load_addr, *ksize, (void *)*symtab_addr,
  13.689 +		 (void *)*symtab_len));
  13.690 +    }
  13.691 +
  13.692 +    if (phdr)
  13.693 +	free(phdr);
  13.694 +    if (p)
  13.695 +	free(p);
  13.696 +    return ret;
  13.697 +}
    14.1 --- a/tools/xc/py/Xc.c	Sun Feb 08 17:33:37 2004 +0000
    14.2 +++ b/tools/xc/py/Xc.c	Mon Feb 09 13:39:44 2004 +0000
    14.3 @@ -221,6 +221,27 @@ static PyObject *pyxc_linux_build(PyObje
    14.4      return PyInt_FromLong(ret);
    14.5  }
    14.6  
    14.7 +static PyObject *pyxc_netbsd_build(PyObject *self,
    14.8 +                                   PyObject *args,
    14.9 +                                   PyObject *kwds)
   14.10 +{
   14.11 +    XcObject *xc = (XcObject *)self;
   14.12 +
   14.13 +    unsigned int dom;
   14.14 +    char        *image, *ramdisk = NULL, *cmdline = "";
   14.15 +    int          ret;
   14.16 +
   14.17 +    static char *kwd_list[] = { "dom", "image", "ramdisk", "cmdline", NULL };
   14.18 +
   14.19 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|ss", kwd_list, 
   14.20 +                                      &dom, &image, &ramdisk, &cmdline) )
   14.21 +        return NULL;
   14.22 +
   14.23 +    ret = xc_netbsd_build(xc->xc_handle, dom, image, cmdline);
   14.24 +    
   14.25 +    return PyInt_FromLong(ret);
   14.26 +}
   14.27 +
   14.28  static PyObject *pyxc_bvtsched_global_set(PyObject *self,
   14.29                                            PyObject *args,
   14.30                                            PyObject *kwds)
   14.31 @@ -687,6 +708,15 @@ static PyMethodDef pyxc_methods[] = {
   14.32        " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
   14.33        "Returns: [int] new domain identifier on success; -1 on error.\n" },
   14.34  
   14.35 +    { "netbsd_build", 
   14.36 +      (PyCFunction)pyxc_netbsd_build, 
   14.37 +      METH_VARARGS | METH_KEYWORDS, "\n"
   14.38 +      "Build a new NetBSD guest OS.\n"
   14.39 +      " dom     [int]:      Identifier of domain to build into.\n"
   14.40 +      " image   [str]:      Name of kernel image file. May be gzipped.\n"
   14.41 +      " cmdline [str, n/a]: Kernel parameters, if any.\n\n"
   14.42 +      "Returns: [int] new domain identifier on success; -1 on error.\n" },
   14.43 +
   14.44      { "bvtsched_global_set", 
   14.45        (PyCFunction)pyxc_bvtsched_global_set, 
   14.46        METH_VARARGS | METH_KEYWORDS, "\n"