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.
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"