WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 3/3] Some "make check" tests for xen/common

To: Xen-Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 3/3] Some "make check" tests for xen/common
From: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
Date: Fri, 9 Dec 2005 16:56:25 +1100
Delivery-date: Fri, 09 Dec 2005 05:57:33 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Mail-followup-to: Xen-Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.9i
Signed-off-by: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>

----- Forwarded message from Rusty Russell <rusty@xxxxxxxxxxxxxxx> -----

To: Tony Breeds <tony@xxxxxxxxxxxxxxxxxx>
From: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Subject: [PATCH 3/3] Some "make check" tests for xen/common
Date: Fri, 09 Dec 2005 16:47:43 +1100

Some of these tests could probably be improved, but this is a first cut.
Not all the files are tested yet, just enough to know we're on the right
track.

Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>

diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_ac_timer.c 
xen-unstable.hg-check/xen/common/test/test_ac_timer.c
--- xen-unstable.hg-mainline/xen/common/test/test_ac_timer.c    1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_ac_timer.c       2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,241 @@
+/*  Tests for timers.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "fake-support.h"
+
+#define AC_TIMER_SOFTIRQ                  0
+typedef void (*softirq_handler)(void);
+static softirq_handler _test_handler;
+static inline void open_softirq(int nr, softirq_handler handler)
+{
+       test_cond(nr == AC_TIMER_SOFTIRQ);
+       _test_handler = handler;
+}
+
+#include "../../include/xen/ac_timer.h"
+#include "../ac_timer.c"
+
+#define TEST_NUM_TIMERS 10
+
+struct test_timer
+{
+       struct ac_timer timer;
+       unsigned int timer_count;
+       unsigned long expiry;
+};
+static struct test_timer _test_timers[TEST_NUM_TIMERS];
+
+static void _test_timer(void *data)
+{
+       struct test_timer *t = data;
+
+       t->timer_count++;
+
+       /* Previous timer should have gone off before us. */
+       if (t != _test_timers)
+               test_cond(t[-1].timer_count == t[0].timer_count);
+
+       /* Should be about the right time. */
+       test_cond(t->expiry < NOW() + TIMER_SLOP);
+}
+
+static int _test_reprogram = 1;
+static int _test_reprogram_timeout = 1;
+int reprogram_ac_timer(s_time_t timeout)
+{
+       _test_reprogram_timeout = timeout;
+       return _test_reprogram;
+}
+
+static s_time_t _test_now = 0;
+s_time_t NOW(void)
+{
+       return _test_now;
+}
+
+static int _test_selfadd = 1;
+static void _test_timer_selfadd(void *data)
+{
+       if (_test_selfadd)
+               set_ac_timer(data, _test_now + TIMER_SLOP*2);
+}
+
+static int _test_smp_processor_id = 0;
+int smp_processor_id(void)
+{
+       return _test_smp_processor_id;
+}
+
+void printk(const char *fmt, ...)
+{
+       va_list arglist;
+
+       va_start(arglist, fmt);
+       vfprintf(stderr, fmt, arglist);
+       va_end(arglist);
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned int i;
+       struct ac_timer timer;
+
+       parse_test_args(argc, argv);
+       register_suppression("../ac_timer.c", 128);
+
+       /* Initialize first. */
+       ac_timer_init();
+
+       /* Self-adding timer should work. */
+       _test_now = 0;
+       init_ac_timer(&timer, _test_timer_selfadd, &timer, 0);
+       fake_expect_xmalloc = 1;
+       set_ac_timer(&timer, 1);
+       _test_now = 1;
+       _test_handler();
+       test_cond(active_ac_timer(&timer));
+       /* Timer should still be running. */
+       test_cond(_test_reprogram_timeout != 0);
+       _test_selfadd = 0;
+       _test_now = LONG_MAX;
+       _test_handler();
+       test_cond(!active_ac_timer(&timer));
+       /* Timer should be stopped. */
+       test_cond(_test_reprogram_timeout == 0);
+
+       /* Adding timer on other CPU should work. */
+       _test_now = 0;
+       init_ac_timer(&timer, _test_timer_selfadd, &timer, 1);
+       fake_expect_xmalloc = 1;
+       set_ac_timer(&timer, 1);
+       test_cond(active_ac_timer(&timer));
+       /* Wrong CPU, will do nothing. */
+       _test_handler();
+       test_cond(active_ac_timer(&timer));
+       _test_smp_processor_id = 1;
+       _test_handler();
+       test_cond(!active_ac_timer(&timer));
+       _test_smp_processor_id = 0;
+
+       /* Create them in expiry order, with +/- 1.. */
+       for (i = 0; i < TEST_NUM_TIMERS; i++) {
+               _test_timers[i].timer_count = 0;
+               init_ac_timer(&_test_timers[i].timer, _test_timer,
+                             &_test_timers[i], 0);
+               _test_timers[i].expiry
+                       = LONG_MAX/(TEST_NUM_TIMERS/3+1)*((i+3)/3) + i%3;
+       }
+
+       /* Add them all. */
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               set_ac_timer(&_test_timers[i].timer, _test_timers[i].expiry);
+       /* They can be re-added (noop) */
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               set_ac_timer(&_test_timers[i].timer, _test_timers[i].expiry);
+
+       /* Delete in random order then re-add. */
+       for (i = 0; i < TEST_NUM_TIMERS/2; i++)
+               rem_ac_timer(&_test_timers[i*2].timer);
+       for (i = 0; i < TEST_NUM_TIMERS/2; i++)
+               rem_ac_timer(&_test_timers[i*2+1].timer);
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               test_cond(!active_ac_timer(&_test_timers[i].timer));
+
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               set_ac_timer(&_test_timers[i].timer, _test_timers[i].expiry);
+
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               test_cond(active_ac_timer(&_test_timers[i].timer));
+
+       /* Expire them in order. */
+       _test_now = 0;
+       for (i = 1; i <= TEST_NUM_TIMERS/3; i++) {
+               _test_now = LONG_MAX/(TEST_NUM_TIMERS/3+1)*i;
+               _test_handler();
+       }
+       _test_now = LONG_MAX;
+       _test_handler();
+
+       /* They must have all gone off */
+       for (i = 0; i < TEST_NUM_TIMERS; i++) {
+               test_cond(!active_ac_timer(&_test_timers[i].timer));
+               test_cond(_test_timers[i].timer_count == 1);
+       }
+
+       /* Add them in backwards order. */
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               set_ac_timer(&_test_timers[TEST_NUM_TIMERS-1-i].timer,
+                            _test_timers[TEST_NUM_TIMERS-1-i].expiry);
+
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               test_cond(active_ac_timer(&_test_timers[i].timer));
+
+       /* Expire them in order. */
+       _test_now = 0;
+       for (i = 1; i <= TEST_NUM_TIMERS/3; i++) {
+               _test_now = LONG_MAX/(TEST_NUM_TIMERS/3+1)*i;
+               _test_handler();
+       }
+       _test_now = LONG_MAX;
+       _test_handler();
+
+       /* They must have all gone off */
+       for (i = 0; i < TEST_NUM_TIMERS; i++) {
+               test_cond(!active_ac_timer(&_test_timers[i].timer));
+               test_cond(_test_timers[i].timer_count == 2);
+       }
+
+       /* Add them in "random" order. */
+       test_cond(TEST_NUM_TIMERS%2 == 0);
+       for (i = 0; i < TEST_NUM_TIMERS/2; i++)
+               set_ac_timer(&_test_timers[i*2].timer,
+                            _test_timers[i*2].expiry);
+
+       for (i = 0; i < TEST_NUM_TIMERS/2; i++)
+               set_ac_timer(&_test_timers[i*2+1].timer,
+                            _test_timers[i*2+1].expiry);
+
+       for (i = 0; i < TEST_NUM_TIMERS; i++)
+               test_cond(active_ac_timer(&_test_timers[i].timer));
+
+       /* Expire them in order. */
+       _test_now = 0;
+       for (i = 1; i <= TEST_NUM_TIMERS/3; i++) {
+               _test_now = LONG_MAX/(TEST_NUM_TIMERS/3+1)*i;
+               _test_handler();
+       }
+       _test_now = LONG_MAX;
+       _test_handler();
+
+       /* They must have all gone off */
+       for (i = 0; i < TEST_NUM_TIMERS; i++) {
+               test_cond(!active_ac_timer(&_test_timers[i].timer));
+               test_cond(_test_timers[i].timer_count == 3);
+       }
+
+       return 0;
+}
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_acm_ops.c 
xen-unstable.hg-check/xen/common/test/test_acm_ops.c
--- xen-unstable.hg-mainline/xen/common/test/test_acm_ops.c     1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_acm_ops.c        2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,192 @@
+/*  Tests for acm_ops
+    Copyright (C) 2005 Tony Breeds IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "fake-support.h"
+
+#include "../../include/public/acm.h"
+#include "../../include/public/acm_ops.h"
+
+#define _TEST_ERROR -1
+
+/* BEGIN: Move to fake-include.h / fake .c */
+struct acm_ssid_domain {
+    ssidref_t ssidref;
+};
+/*   END: Move to fake-include.h / fake .c */
+
+static int _test_acm_error = 0;
+static int _test_find_error = 0;
+static struct domain *_test_domain;
+
+static int acm_set_policy(void *buf, u32 buf_size, int isuserbuffer)
+{
+       return !_test_acm_error?ACM_OK:_TEST_ERROR;
+}
+static int acm_get_policy(void *buf, u32 buf_size)
+{
+       return !_test_acm_error?ACM_OK:_TEST_ERROR;
+}
+static int acm_dump_statistics(void *buf, u16 buf_size)
+{
+       return !_test_acm_error?ACM_OK:_TEST_ERROR;
+}
+static int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size)
+{
+       return !_test_acm_error?ACM_OK:_TEST_ERROR;
+}
+static int acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, 
+                            enum acm_hook_type hook)
+{
+       return !_test_acm_error?ACM_OK:_TEST_ERROR;
+}
+
+/* FIXME: Use fake.c's version. */
+struct domain *find_domain_by_id(domid_t dom)
+{
+       return !_test_find_error?_test_domain:NULL;
+}
+
+/* Kill printks */
+#define printkd(fmt, args...)
+#define printk(fmt, args...)   
+
+/* Force the non-trivial case */
+#define ACM_SECURITY
+
+/* Defined in "../acm_ops.c" */
+long do_acm_op(struct acm_op * u_acm_op);
+enum acm_operation;
+int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops);
+
+/* Avoid ref counting */
+#define put_domain(d)  do { } while (0)
+
+#include "../acm_ops.c"
+
+int main(int argc, char *argv[])
+{
+       enum acm_operation acm_op;
+       struct acm_op *user_acm_op;
+
+       parse_test_args(argc, argv);
+
+       current = calloc(sizeof(struct vcpu), 1);
+       current->domain = calloc(sizeof(struct domain), 1);
+       user_acm_op = calloc(sizeof(struct acm_op), 1);
+
+       _test_domain = calloc(sizeof(struct domain), 1);
+       _test_domain->ssid = calloc(sizeof(struct acm_ssid_domain), 1);
+
+       /* Test acm_authorize_acm_ops */
+       fake_IS_PRIV_out = 0;
+       test_cond(acm_authorize_acm_ops(current->domain, acm_op) == 
+              -EPERM);
+
+       fake_IS_PRIV_out = 1;
+       test_cond(!acm_authorize_acm_ops(current->domain, acm_op));
+
+       /* Test do_acm_op */
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -EACCES);
+       user_acm_op->interface_version = ACM_INTERFACE_VERSION;
+
+       /* Arbtrary invalid command */
+       user_acm_op->cmd = -1;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->cmd = ACM_SETPOLICY;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+       user_acm_op->cmd = ACM_GETPOLICY;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+       user_acm_op->cmd = ACM_DUMPSTATS;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+
+       _test_acm_error=1;
+       user_acm_op->cmd = ACM_SETPOLICY;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -EPERM);
+       user_acm_op->cmd = ACM_GETPOLICY;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -EPERM);
+       user_acm_op->cmd = ACM_DUMPSTATS;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -EPERM);
+       _test_acm_error=0;
+
+       user_acm_op->cmd = ACM_GETSSID;
+       user_acm_op->u.getssid.get_ssid_by = UNSET;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->u.getssid.get_ssid_by = SSIDREF;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+
+       user_acm_op->u.getssid.get_ssid_by = DOMAINID;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+       _test_find_error = 1;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+       _test_find_error = 0;
+       free(_test_domain->ssid);
+       _test_domain->ssid = NULL;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->u.getssid.get_ssid_by = SSIDREF;
+       _test_acm_error = 1;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == _TEST_ERROR);
+       _test_acm_error = 0;
+
+       _test_domain->ssid = calloc(sizeof(struct acm_ssid_domain), 1);
+
+       user_acm_op->cmd = ACM_GETDECISION;
+       user_acm_op->u.getdecision.get_decision_by1 = UNSET;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->u.getdecision.get_decision_by1 = SSIDREF;
+       user_acm_op->u.getdecision.get_decision_by2 = UNSET;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->u.getdecision.get_decision_by2 = SSIDREF;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+
+       user_acm_op->u.getdecision.get_decision_by1 = DOMAINID;
+       user_acm_op->u.getdecision.get_decision_by2 = DOMAINID;
+       test_cond(!do_acm_op(fake_to_user(user_acm_op)));
+
+       _test_find_error = 1;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       _test_find_error = 0;
+       free(_test_domain->ssid);
+       _test_domain->ssid = NULL;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+
+       user_acm_op->u.getdecision.get_decision_by1 = SSIDREF;
+       user_acm_op->u.getdecision.get_decision_by2 = SSIDREF;
+       _test_acm_error = 1;
+       test_cond(do_acm_op(fake_to_user(user_acm_op)) == -ESRCH);
+       _test_acm_error = 0;
+
+       free(_test_domain);
+       free(user_acm_op);
+       free(current->domain);
+       free(current);
+
+       return 0;
+}
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_bitmap.c 
xen-unstable.hg-check/xen/common/test/test_bitmap.c
--- xen-unstable.hg-mainline/xen/common/test/test_bitmap.c      1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_bitmap.c 2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,344 @@
+/*  Tests for bitmap ops.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "fake-support.h"
+
+#include "../../include/xen/bitmap.h"
+#include "../bitmap.c"
+
+static void _test_set_bit(unsigned long *bitmap, int bit)
+{
+       bitmap[bit/BITS_PER_LONG] |= (1UL << (bit%BITS_PER_LONG));
+}
+
+static void _test_clear_bit(unsigned long *bitmap, int bit)
+{
+       bitmap[bit/BITS_PER_LONG] ^= (1UL << (bit%BITS_PER_LONG));
+}
+
+static void _test_bitmap_clone(unsigned long *dst, unsigned long *src, 
+                               int length)
+{
+       test_cond(length>0);
+       memcpy(dst, src, length);
+}
+
+static int _test_hweight(unsigned long *bitmap, int bits)
+{
+       int i;
+       int count = 0;
+
+       for(i=0; i<bits; i++) {
+               if (bitmap[i/BITS_PER_LONG] & (1UL << (i%BITS_PER_LONG))) {
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+int main(int argc, char *argv[])
+{
+       unsigned long *bitmap1 = calloc(sizeof(long), 2);
+       unsigned long *bitmap2 = calloc(sizeof(long), 2);
+       long i;
+       /* Used in testing the *region() functions. Effectively 
+        * lg(BITS_PER_LONG) */
+       int order = 0; 
+
+       parse_test_args(argc, argv);
+
+       /* Test __bitmap_empty. */
+       test_cond(__bitmap_empty(bitmap1, BITS_PER_LONG*2));
+       for (i = BITS_PER_LONG*2-1; i >= 0; i--) {
+               _test_set_bit(bitmap1, i);
+               test_cond(__bitmap_empty(bitmap1, i));
+               test_cond(!__bitmap_empty(bitmap1, i+1));
+       }
+       /* Test __bitmap_full. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+
+       test_cond(__bitmap_full(bitmap1, BITS_PER_LONG*2));
+       for (i = BITS_PER_LONG*2-1; i >= 0; i--) {
+               _test_clear_bit(bitmap1, i);
+               test_cond(__bitmap_full(bitmap1, i));
+               test_cond(!__bitmap_full(bitmap1, i+1));
+       }
+
+       /* Test __bitmap_equal. */
+       bitmap1[0] = 0xaa; /* 0+2+0+8+ 0+32+ 0+128 */
+       bitmap1[1] = 0UL;
+       bitmap2[0] = 0x55; /* 1+0+4+0+16+ 0+64+  0 */
+       bitmap2[1] = 0UL;
+
+       /* Setup alternatng bit pattern bitmaps */
+       for(i=0; i< 2; i++) {
+               int j;
+
+               for(j=0; j< sizeof(long); j++) {
+                       bitmap1[i] = (bitmap1[i] << CHAR_BIT) | 0xaa;
+                       bitmap2[i] = (bitmap2[i] << CHAR_BIT) | 0x55;
+               }
+       }
+
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               test_cond(!__bitmap_equal(bitmap1, bitmap2, i+1));
+               _test_set_bit(bitmap1, i);
+               _test_set_bit(bitmap2, i);
+               test_cond(__bitmap_equal(bitmap1, bitmap2, i+1));
+       }
+
+       /* Test __bitmap_compliment. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+
+       __bitmap_complement(bitmap2, bitmap1, BITS_PER_LONG*2);
+       test_cond(__bitmap_empty(bitmap2,  BITS_PER_LONG*2));
+       for (i = BITS_PER_LONG*2-1; i >= 0; i--) {
+               _test_clear_bit(bitmap1, i);
+
+               __bitmap_complement(bitmap2, bitmap1, i);
+               test_cond(__bitmap_empty(bitmap2, i));
+
+               __bitmap_complement(bitmap1, bitmap2, i);
+               test_cond(__bitmap_full(bitmap1, i));
+       }
+
+       /* Test __bitmap_shift_right. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+
+       _test_set_bit(bitmap1, BITS_PER_LONG*2-1);
+       for (i = BITS_PER_LONG*2-1; i > 0; i--) {
+               unsigned long *shifttest = calloc(sizeof(long), 2);
+
+               __bitmap_shift_right(bitmap2, bitmap1, 1, BITS_PER_LONG*2);
+               test_cond(__bitmap_empty(bitmap2, i-1));
+               test_cond(!__bitmap_empty(bitmap2, i));
+
+               _test_bitmap_clone(bitmap1, bitmap2, sizeof(long)*2);
+
+               /* Shift bitmap2 by the number of itterations of this loop
+                * executed so far.  The result should be the same as bitmap1
+                */
+               bitmap2[0] = 0;
+               bitmap2[1] = 0;
+               _test_set_bit(bitmap2, BITS_PER_LONG*2-1);
+               __bitmap_shift_right(shifttest, bitmap2, (BITS_PER_LONG*2)-i, 
+                                    BITS_PER_LONG*2);
+
+               test_cond(__bitmap_equal(shifttest, bitmap1, BITS_PER_LONG*2));
+               free(shifttest);
+       }
+
+       /* Test __bitmap_shift_left. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+
+       _test_set_bit(bitmap1, 0);
+       for (i = 1; i < BITS_PER_LONG*2; i++) {
+               unsigned long *shifttest = calloc(sizeof(long), 2);
+
+               __bitmap_shift_left(bitmap2, bitmap1, 1, BITS_PER_LONG*2);
+               test_cond(__bitmap_empty(bitmap2, i));
+               test_cond(!__bitmap_empty(bitmap2, i+1));
+
+               _test_bitmap_clone(bitmap1, bitmap2, sizeof(long)*2);
+
+               bitmap2[0] = 0;
+               bitmap2[1] = 0;
+               _test_set_bit(bitmap2, 0);
+               __bitmap_shift_left(shifttest, bitmap2, i, BITS_PER_LONG*2);
+               test_cond(__bitmap_equal(shifttest, bitmap1, BITS_PER_LONG*2));
+               free(shifttest);
+       }
+
+       /* Test __bitmap_and. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+       bitmap2[0] = 0UL;
+       bitmap2[1] = 0UL;
+
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               unsigned long *andtest = calloc(sizeof(long), 2);
+
+               _test_set_bit(bitmap2, i);
+               __bitmap_and(andtest, bitmap1, bitmap2, i+1);
+               test_cond(__bitmap_equal(andtest, bitmap2, i));
+
+               free(andtest);
+       }
+
+       /* Test __bitmap_or. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               unsigned long *ortest = calloc(sizeof(long), 2);
+
+               bitmap2[0] = 0UL;
+               bitmap2[1] = 0UL;
+               _test_set_bit(bitmap2, i);
+
+               __bitmap_or(ortest, bitmap2, bitmap2, i+1);
+               test_cond(__bitmap_equal(ortest, bitmap2, i+1));
+               __bitmap_or(ortest, bitmap2, bitmap1, i+1);
+               test_cond(__bitmap_equal(ortest, bitmap1, i+1));
+
+               free(ortest);
+       }
+
+       /* Test __bitmap_xor. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               unsigned long *xortest = calloc(sizeof(long), 2);
+               unsigned long *complement = calloc(sizeof(long), 2);
+
+               bitmap2[0] = 0UL;
+               bitmap2[1] = 0UL;
+               _test_set_bit(bitmap2, i);
+               __bitmap_complement(complement, bitmap2, i+1);
+               __bitmap_xor(xortest, bitmap1, bitmap2, i+1);
+
+               test_cond(__bitmap_equal(xortest, complement, i+1));
+
+               free(complement);
+               free(xortest);
+       }
+
+       /* Test __bitmap_andnot. */
+       bitmap1[0] = ULONG_MAX;
+       bitmap1[1] = ULONG_MAX;
+       bitmap2[0] = 0UL;
+       bitmap2[1] = 0UL;
+
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               unsigned long *andnottest = calloc(sizeof(long), 2);
+
+               __bitmap_andnot(andnottest, bitmap1, bitmap2, i+1);
+               test_cond(__bitmap_full(andnottest, i+1));
+
+               free(andnottest);
+       }
+
+       /* Test __bitmap_intersects. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+       bitmap2[0] = 0UL;
+       bitmap2[1] = 0UL;
+
+       test_cond(!__bitmap_intersects(bitmap1, bitmap2, BITS_PER_LONG*2));
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               _test_set_bit(bitmap1, i);
+               __bitmap_complement(bitmap2, bitmap1, i+1);
+               test_cond(!__bitmap_intersects(bitmap1, bitmap2, i+1));
+       }
+
+       /* Test __bitmap_subset. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+       bitmap2[0] = 0UL;
+       bitmap2[1] = 0UL;
+
+       test_cond(__bitmap_subset(bitmap1, bitmap2, BITS_PER_LONG*2));
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               _test_set_bit(bitmap1, i);
+               __bitmap_complement(bitmap2, bitmap1, i+1);
+               test_cond(!__bitmap_subset(bitmap1, bitmap2, i+1));
+
+       }
+
+       /* Test __bitmap_weight. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+       for(i = 0; i < BITS_PER_LONG*2; i++) {
+               _test_set_bit(bitmap1, i);
+
+               test_cond(_test_hweight(bitmap1, BITS_PER_LONG*2) == i+1);
+               test_cond(__bitmap_weight(bitmap1, BITS_PER_LONG*2) ==
+                      _test_hweight(bitmap1, BITS_PER_LONG*2));
+       }
+
+       /* Test bitmap_find_free_region. */
+       i = BITS_PER_LONG;
+       while (i>1) {
+               i >>=1;
+               order++;
+       }
+
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+       bitmap2[0] = ULONG_MAX;
+       bitmap2[1] = ULONG_MAX;
+
+       for(i=0; i<=order; i++) {
+               unsigned long *freetest = calloc(sizeof(long), 2);
+               int pos;
+
+               pos = bitmap_find_free_region(bitmap1, BITS_PER_LONG*2, i);
+               test_cond(pos >= 0);
+
+               __bitmap_shift_right(freetest, bitmap1, pos ,BITS_PER_LONG*2);
+               test_cond(__bitmap_full(freetest, i));
+
+               /* bitmap2 is busy this must fail */
+               pos = bitmap_find_free_region(bitmap2, BITS_PER_LONG*2, i);
+               test_cond(pos < 0);
+
+               free(freetest);
+       }
+       /* check for ((1<<order) > BITS_PER_LONG)  which results in -EINVAL */
+       test_cond(bitmap_find_free_region(bitmap1, BITS_PER_LONG*2, order+1) < 
0); 
+
+       /* Test bitmap_release_region and bitmap_allocate_region. */
+       bitmap1[0] = 0UL;
+       bitmap1[1] = 0UL;
+       bitmap2[0] = ULONG_MAX;
+       bitmap2[1] = ULONG_MAX;
+
+       for(i=0; i<=order; i++) {
+               int j;
+               for(j=0; j < BITS_PER_LONG*2; j++) {
+                       test_cond(!bitmap_allocate_region(bitmap1, j, i));
+                       test_cond(!__bitmap_empty(bitmap1, BITS_PER_LONG*2));
+
+                       bitmap_release_region(bitmap1, j, i);
+                       test_cond(__bitmap_empty(bitmap1, BITS_PER_LONG*2));
+
+                       /* bitmap2 is busy this must fail */
+                       test_cond(bitmap_allocate_region(bitmap2, j, i) <0);
+               }
+       }
+       
+
+       bitmap1[0] = 0UL;
+       
+       free(bitmap1);
+       free(bitmap2);
+       return 0;
+}
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_dom0_ops.c 
xen-unstable.hg-check/xen/common/test/test_dom0_ops.c
--- xen-unstable.hg-mainline/xen/common/test/test_dom0_ops.c    1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_dom0_ops.c       2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,644 @@
+/*  Tests for dom0 ops.
+    Copyright (C) 2005 Rusty Russell IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#define _GNU_SOURCE
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <fake-support.h>
+
+
+#include "../../include/public/dom0_ops.h"
+
+static int _test_acm_pre_dom0_op = 0;
+static int acm_pre_dom0_op(dom0_op_t *op, void **ssid) 
+{
+       return _test_acm_pre_dom0_op;
+}
+
+static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid) 
+{ return; }
+
+static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid) 
+{ return; }
+
+static int _test_set_info_guest_out;
+static int set_info_guest(struct domain *d,
+                         dom0_setdomaininfo_t *setdomaininfo)
+{
+       return _test_set_info_guest_out;
+}
+
+static int _test_count_domain_pause_by_systemcontroller;
+void domain_pause_by_systemcontroller(struct domain *d);
+void domain_pause_by_systemcontroller(struct domain *d)
+{
+       _test_count_domain_pause_by_systemcontroller++;
+}
+
+static int _test_count_domain_unpause_by_systemcontroller;
+void domain_unpause_by_systemcontroller(struct domain *d);
+void domain_unpause_by_systemcontroller(struct domain *d)
+{
+       _test_count_domain_unpause_by_systemcontroller++;
+}
+
+static struct domain *_test_domain_kill;
+void domain_kill(struct domain *d);
+void domain_kill(struct domain *d)
+{
+       _test_domain_kill = d;
+}
+       
+#define for_each_vcpu(_d,_v)                    \
+ for ( (_v) = (_d)->vcpu[0];                    \
+       (_v) != NULL;                            \
+       (_v) = (_v)->next_in_list )
+
+ /* Has the FPU been initialised? */
+#define _VCPUF_fpu_initialised 0
+#define VCPUF_fpu_initialised  (1UL<<_VCPUF_fpu_initialised)
+ /* Has the FPU been used since it was last saved? */
+#define _VCPUF_fpu_dirtied     1
+#define VCPUF_fpu_dirtied      (1UL<<_VCPUF_fpu_dirtied)
+ /* Domain is blocked waiting for an event. */
+#define _VCPUF_blocked         2
+#define VCPUF_blocked          (1UL<<_VCPUF_blocked)
+ /* Currently running on a CPU? */
+#define _VCPUF_running         3
+#define VCPUF_running          (1UL<<_VCPUF_running)
+ /* Disables auto-migration between CPUs. */
+#define _VCPUF_cpu_pinned      4
+#define VCPUF_cpu_pinned       (1UL<<_VCPUF_cpu_pinned)
+ /* Domain migrated between CPUs. */
+#define _VCPUF_cpu_migrated    5
+#define VCPUF_cpu_migrated     (1UL<<_VCPUF_cpu_migrated)
+ /* Initialization completed. */
+#define _VCPUF_initialised     6
+#define VCPUF_initialised      (1UL<<_VCPUF_initialised)
+ /* VCPU is not-runnable */
+#define _VCPUF_down            7
+#define VCPUF_down             (1UL<<_VCPUF_down)
+
+/*
+ * Per-domain flags (domain_flags).
+ */
+ /* Is this one of the per-CPU idle domains? */
+#define _DOMF_idle_domain      0
+#define DOMF_idle_domain       (1UL<<_DOMF_idle_domain)
+ /* Is this domain privileged? */
+#define _DOMF_privileged       1
+#define DOMF_privileged        (1UL<<_DOMF_privileged)
+ /* May this domain do IO to physical devices? */
+#define _DOMF_physdev_access   2
+#define DOMF_physdev_access    (1UL<<_DOMF_physdev_access)
+ /* Guest shut itself down for some reason. */
+#define _DOMF_shutdown         3
+#define DOMF_shutdown          (1UL<<_DOMF_shutdown)
+ /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
+#define _DOMF_shuttingdown     4
+#define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
+ /* Death rattle. */
+#define _DOMF_dying            5
+#define DOMF_dying             (1UL<<_DOMF_dying)
+ /* Domain is paused by controller software. */
+#define _DOMF_ctrl_pause       6
+#define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
+
+#define ACM_DEFAULT_SSID  0x0
+
+typedef uint32_t ssidref_t;
+struct acm_ssid_domain {
+    ssidref_t ssidref;   /* combined security reference */
+};
+
+#define __pa(x) ((unsigned long)(x) + 1001)
+#define __va(x) ((unsigned long)(x) - 1001)
+#define PAGE_SHIFT 10
+#define for_each_domain(_d)                     \
+ for ( (_d) = current->domain;                  \
+       (_d) != NULL;                            \
+       (_d) = NULL )
+#define smp_num_siblings 1
+#define num_online_cpus() 1
+rwlock_t domlist_lock = RW_LOCK_UNLOCKED;
+
+static struct vcpu *_test_alloc_vcpu_out;
+static struct vcpu *alloc_vcpu(struct domain *d, unsigned int vcpu_id,
+                              unsigned int cpu_id)
+{
+       return _test_alloc_vcpu_out;
+}
+
+static struct vcpu *_test_new_vcpu(void)
+{
+       struct vcpu *vcpu = malloc(sizeof(struct vcpu));
+
+       vcpu->processor = 0;
+       vcpu->next_in_list = NULL;
+       return vcpu;
+}
+
+static struct domain *_test_new_domain(void)
+{
+       struct domain *d = malloc(sizeof(struct domain));
+       atomic_set(&d->refcnt, 0);
+       memset(d->vcpu, 0, sizeof(d->vcpu));
+       d->vcpu[0] = _test_new_vcpu();
+       return d;
+}
+
+static struct domain *_test_do_createdomain_out;
+static domid_t _test_do_createdomain_domid;
+static unsigned int _test_do_createdomain_cpu;
+static struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       _test_do_createdomain_domid = dom_id;
+       _test_do_createdomain_cpu = cpu;
+       if (_test_do_createdomain_out)
+               _test_do_createdomain_out->domain_id = dom_id;
+       return _test_do_createdomain_out;
+}
+
+static long test_arch_do_dom0_op_out;
+static long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       return test_arch_do_dom0_op_out;
+}
+
+static unsigned int find_first_set_bit(unsigned long word)
+{
+       return ffsl(word);
+}
+
+static struct vcpu *test_vcpu_pause_in_v;
+static void vcpu_pause(struct vcpu *v)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       test_vcpu_pause_in_v = v;
+}
+
+static struct vcpu *test_arch_getdomaininfo_ctxt_in_vcpu;
+static void arch_getdomaininfo_ctxt(struct vcpu *vcpu,
+                                   struct vcpu_guest_context *ctx)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       test_arch_getdomaininfo_ctxt_in_vcpu = vcpu;
+}
+
+static int test_vcpu_migrate_cpu_in_newcpu;
+static void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       assert(v == test_vcpu_pause_in_v);
+       test_vcpu_migrate_cpu_in_newcpu = newcpu;
+}
+
+static void vcpu_unpause(struct vcpu *v)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       assert(v == test_vcpu_pause_in_v);
+}
+
+static long sched_ctl(struct sched_ctl_cmd *cmd)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       memset(cmd, 0, sizeof(cmd));
+       return 102;
+}
+
+static long sched_adjdom(struct sched_adjdom_cmd *cmd)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       memset(cmd, 0, sizeof(cmd));
+       return 103;
+}
+
+static unsigned long test_do_settime_in_secs;
+static unsigned long test_do_settime_in_nsecs;
+static unsigned long test_do_settime_in_system_time_base;
+static void do_settime(unsigned long secs, unsigned long nsecs,
+                      u64 system_time_base)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       test_do_settime_in_secs = secs;
+       test_do_settime_in_nsecs = nsecs;
+       test_do_settime_in_system_time_base = system_time_base;
+}
+
+static int test_tb_control_out;
+static int tb_control(dom0_tbufcontrol_t *tbc)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       return test_tb_control_out;
+}
+
+static long test_read_console_ring_out;
+static int test_read_console_ring_in_clear;
+static long read_console_ring(char **pstr, u32 *pcount, int clear)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       (*pstr)++;
+       **pstr = 'A';
+       *pcount = 1;
+       test_read_console_ring_in_clear = clear;
+       return test_read_console_ring_out;
+}
+
+static int test_sched_id_out;
+static int sched_id(void)
+{
+       fake_must_have_spinlock("&dom0_lock");
+       return test_sched_id_out;
+}
+
+/* Prototype to suppress warning (usually only called from asm) */
+long do_dom0_op(dom0_op_t *u_dom0_op);
+
+#include "../../include/public/dom0_ops.h"
+#include "../dom0_ops.c"
+
+/* Use dynamic allocation so valgrind can find problems. */
+static dom0_op_t *_test_op(int cmd)
+{
+       dom0_op_t *op = malloc(sizeof(*op));
+       op->interface_version = DOM0_INTERFACE_VERSION;
+       op->cmd = cmd;
+       return op;
+}
+
+int main(int argc, char *argv[])
+{
+       struct domain *me;
+       dom0_op_t *op;
+
+       parse_test_args(argc, argv);
+
+       me = _test_new_domain();
+       current = me->vcpu[0];
+       current->domain = me;
+       me->domain_flags = 0;
+       atomic_inc(&me->refcnt);
+
+       /* Unpriv'd domains should be immediately shown the door. */
+       fake_IS_PRIV_out = 0;
+       test_cond(do_dom0_op(fake_to_user(NULL)) == -EPERM);
+       test_cond(fake_lock_count == 0);
+
+       /* Wrong version should be failed without looking at command. */
+       fake_IS_PRIV_out = 1;
+       op = malloc(sizeof(*op));
+       op->interface_version = DOM0_INTERFACE_VERSION - 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EACCES);
+       test_cond(fake_lock_count == 0);
+
+       /* ACM hook should result in immediate refusal, too. */
+       op->interface_version = DOM0_INTERFACE_VERSION;
+       _test_acm_pre_dom0_op = 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EPERM);
+       test_cond(fake_lock_count == 0);
+       _test_acm_pre_dom0_op = 0;
+
+       op = _test_op(DOM0_SETDOMAININFO);
+       op->u.setdomaininfo.domain = 100;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = current->domain;
+       _test_set_info_guest_out = -1000;
+       test_cond(do_dom0_op(fake_to_user(op)) == -1000);
+       test_cond(fake_lock_count == 0);
+
+       op = _test_op(DOM0_PAUSEDOMAIN);
+       op->u.pausedomain.domain = 101;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = current->domain;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(_test_count_domain_pause_by_systemcontroller == 1);
+       test_cond(fake_lock_count == 0);
+
+       op = _test_op(DOM0_UNPAUSEDOMAIN);
+       op->u.unpausedomain.domain = 101;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = current->domain;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       fake_find_domain_out->vcpu[0]->vcpu_flags = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       fake_find_domain_out->vcpu[0]->vcpu_flags = (1 << _VCPUF_initialised);
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(fake_lock_count == 0);
+
+       op = _test_op(DOM0_CREATEDOMAIN);
+       op->u.createdomain.domain = 101;
+       fake_find_domain_out = current->domain;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       fake_find_domain_out = NULL;
+       _test_do_createdomain_out = _test_new_domain();
+       /* Not fair to test failing very first allocation. */
+       op->u.createdomain.domain = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(op->u.createdomain.domain == 1);
+       test_cond(_test_do_createdomain_domid == 1);
+       fake_find_domain_out = current->domain;
+       op->u.createdomain.domain = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ENOMEM);
+       fake_find_domain_out = current->domain;
+       fake_find_domain_out = NULL;
+       _test_do_createdomain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ENOMEM);
+       _test_do_createdomain_out = _test_new_domain();
+       /* It copies back to us, so we must set valid bits. */
+       memset(op, 0, sizeof(*op));
+       op->cmd = DOM0_CREATEDOMAIN;
+       op->interface_version = DOM0_INTERFACE_VERSION;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       fake_check_memory(op, sizeof(*op));
+       test_cond(_test_do_createdomain_domid != 0);
+       test_cond(_test_do_createdomain_domid == op->u.createdomain.domain);
+       test_cond(_test_do_createdomain_cpu == 0);
+       op->u.createdomain.domain = 101;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       fake_check_memory(op, sizeof(*op));
+       test_cond(_test_do_createdomain_domid == 101);
+       test_cond(op->u.createdomain.domain == 101);
+       test_cond(_test_do_createdomain_cpu == 0);
+
+       op = _test_op(DOM0_MAX_VCPUS);
+       op->u.max_vcpus.max = MAX_VIRT_CPUS+1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       op->u.max_vcpus.max = MAX_VIRT_CPUS;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       fake_find_domain_out->vcpu[0]->vcpu_flags = (1 << _VCPUF_initialised);
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       fake_find_domain_out->vcpu[0]->vcpu_flags = 0;
+       _test_alloc_vcpu_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ENOMEM);
+       test_cond(fake_lock_count == 0);
+       _test_alloc_vcpu_out = _test_new_vcpu();
+       fake_find_domain_out = _test_new_domain();
+       atomic_inc(&fake_find_domain_out->refcnt);
+       fake_find_domain_out->vcpu[0] = _test_new_vcpu();
+       fake_find_domain_out->vcpu[0]->vcpu_flags = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(fake_lock_count == 0);
+       op->u.max_vcpus.max = 0;
+       _test_alloc_vcpu_out = _test_new_vcpu();
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+
+       op = _test_op(DOM0_DESTROYDOMAIN);
+       op->u.destroydomain.domain = 101;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = current->domain;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       test_cond(fake_lock_count == 0);
+       fake_find_domain_out = _test_new_domain();
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(fake_lock_count == 0);
+       test_cond(_test_domain_kill == fake_find_domain_out);
+
+       op = _test_op(DOM0_PINCPUDOMAIN);
+       op->u.pincpudomain.domain = 101;
+       op->u.pincpudomain.vcpu = 0;
+       op->u.pincpudomain.cpumap = 1;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       op->u.pincpudomain.vcpu = MAX_VIRT_CPUS;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       op->u.pincpudomain.vcpu = 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       /* FIXME: Unreachable ESRCH return --RR */
+       op->u.pincpudomain.vcpu = 0;
+       current->domain->vcpu[0] = current;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       current->domain->vcpu[0] = _test_new_vcpu();
+       current->domain->vcpu[0]->vcpu_flags = (1<<_VCPUF_cpu_pinned);
+       op->u.pincpudomain.cpumap = CPUMAP_RUNANYWHERE;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(current->domain->vcpu[0]->vcpu_flags == 0);
+       op->u.pincpudomain.cpumap = 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(current->domain->vcpu[0]->vcpu_flags
+                 == (1<<_VCPUF_cpu_pinned));
+       test_cond(test_vcpu_pause_in_v == current->domain->vcpu[0]);
+       test_cond(test_vcpu_migrate_cpu_in_newcpu == 0);
+       
+       op = _test_op(DOM0_SCHEDCTL);
+       test_cond(do_dom0_op(fake_to_user(op)) == 102);
+
+       op = _test_op(DOM0_ADJUSTDOM);
+       test_cond(do_dom0_op(fake_to_user(op)) == 103);
+
+       op = _test_op(DOM0_GETDOMAININFO);
+       current->domain->vcpu[0] = current;
+       current->domain->domain_id = 1;
+       op->u.getdomaininfo.domain = 2;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       op->u.getdomaininfo.domain = 1;
+       fake_get_domain_out = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       test_cond(fake_get_domain_in_d == current->domain);
+       fake_get_domain_out = 1;
+       memset(&op->u.getdomaininfo, 0, sizeof(op->u.getdomaininfo));
+       current->domain->tot_pages = 104;
+       current->domain->max_pages = 105;
+       current->domain->shared_info = (void *)__va(106 << PAGE_SHIFT);
+       current->cpu_time = 107;
+       current->vcpu_id = 1;
+       current->vcpu_flags = VCPUF_running;
+       current->domain->ssid = NULL;
+       current->domain->shutdown_code = 0;
+       memset(current->domain->handle, 0, sizeof(current->domain->handle));
+       strcpy((char *)current->domain->handle, "handle");
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       fake_check_memory(&op->u.getdomaininfo, sizeof(op->u.getdomaininfo));
+       test_cond(op->u.getdomaininfo.domain == 1);
+       test_cond(op->u.getdomaininfo.flags == DOMFLAGS_RUNNING);
+       test_cond(op->u.getdomaininfo.tot_pages == 104);
+       test_cond(op->u.getdomaininfo.max_pages == 105);
+       test_cond(op->u.getdomaininfo.nr_online_vcpus == 1);
+       test_cond(op->u.getdomaininfo.shared_info_frame == 106);
+       test_cond(op->u.getdomaininfo.cpu_time == 107);
+       test_cond(op->u.getdomaininfo.nr_online_vcpus == 1);
+       test_cond(op->u.getdomaininfo.max_vcpu_id == 1);
+       test_cond(op->u.getdomaininfo.ssidref == ACM_DEFAULT_SSID);
+       test_cond(strcmp((char *)op->u.getdomaininfo.handle, "handle") == 0);
+
+       op = _test_op(DOM0_GETDOMAININFOLIST);
+       {
+               dom0_getdomaininfo_t *buffer = malloc(sizeof(*buffer));
+
+               op->u.getdomaininfolist.buffer = fake_to_user(buffer);
+               op->u.getdomaininfolist.first_domain = 0;
+               op->u.getdomaininfolist.max_domains = 0;
+               /* FIXME: Redundant NULL test in for_each_domain(). */
+               test_cond(do_dom0_op(fake_to_user(op)) == 0);
+               test_cond(op->u.getdomaininfolist.num_domains == 0);
+               op->u.getdomaininfolist.max_domains = 1;
+               test_cond(do_dom0_op(fake_to_user(op)) == 0);
+               test_cond(op->u.getdomaininfolist.num_domains == 1);
+               /* FIXME: Contains 2 uninitialized bytes, but we're dom0. */
+               /* fake_check_memory(buffer, sizeof(*buffer)); */
+               test_cond(buffer->domain == 1);
+               test_cond(buffer->flags == DOMFLAGS_RUNNING);
+               test_cond(buffer->tot_pages == 104);
+               test_cond(buffer->max_pages == 105);
+               test_cond(buffer->shared_info_frame == 106);
+               test_cond(buffer->cpu_time == 107);
+               test_cond(buffer->nr_online_vcpus == 1);
+               test_cond(buffer->max_vcpu_id == 1);
+               test_cond(buffer->ssidref == ACM_DEFAULT_SSID);
+               test_cond(memcmp(buffer->handle, current->domain->handle,
+                                sizeof(buffer->handle)) == 0);
+       }
+
+       op = _test_op(DOM0_GETVCPUCONTEXT);
+       op->u.getvcpucontext.domain = 101;
+       op->u.getvcpucontext.vcpu = 0;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       op->u.getvcpucontext.vcpu = MAX_VIRT_CPUS;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       op->u.getvcpucontext.vcpu = 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       op->u.getvcpucontext.vcpu = 0;
+       test_vcpu_pause_in_v = NULL;
+       {
+               vcpu_guest_context_t *ctxt = malloc(sizeof *ctxt);
+               op->u.getvcpucontext.ctxt = fake_to_user(ctxt);
+               test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       }
+       test_cond(test_arch_getdomaininfo_ctxt_in_vcpu == current);
+       test_cond(test_vcpu_pause_in_v == NULL);
+       /* Non-current vcpu must be paused. */
+       fake_find_domain_out = _test_new_domain();
+       atomic_inc(&fake_find_domain_out->refcnt);
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(test_arch_getdomaininfo_ctxt_in_vcpu
+                 == fake_find_domain_out->vcpu[0]);
+       test_cond(test_vcpu_pause_in_v == fake_find_domain_out->vcpu[0]);
+
+       
+       op = _test_op(DOM0_GETVCPUINFO);
+       op->u.getvcpuinfo.domain = 101;
+       op->u.getvcpuinfo.vcpu = 0;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       op->u.getvcpuinfo.vcpu = MAX_VIRT_CPUS;
+       test_cond(do_dom0_op(fake_to_user(op)) == -EINVAL);
+       op->u.getvcpuinfo.vcpu = 1;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       op->u.getvcpuinfo.vcpu = 0;
+       current->cpu_time = 108;
+       current->processor = 1;
+       current->cpumap = 7;
+       current->vcpu_flags = (1 << _VCPUF_running);
+       op->u.getvcpuinfo.vcpu = 0;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(op->u.getvcpuinfo.online);
+       test_cond(!op->u.getvcpuinfo.blocked);
+       test_cond(op->u.getvcpuinfo.running);
+       test_cond(op->u.getvcpuinfo.cpu_time == 108);
+       test_cond(op->u.getvcpuinfo.cpu == 1);
+       test_cond(op->u.getvcpuinfo.cpumap == 7);
+
+       op = _test_op(DOM0_SETTIME);
+       op->u.settime.secs = 109;
+       op->u.settime.nsecs = 110;
+       op->u.settime.system_time = 111;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(test_do_settime_in_secs == 109);
+       test_cond(test_do_settime_in_nsecs == 110);
+       test_cond(test_do_settime_in_system_time_base == 111);
+
+       op = _test_op(DOM0_TBUFCONTROL);
+       test_tb_control_out = 112;
+       test_cond(do_dom0_op(fake_to_user(op)) == 112);
+
+       op = _test_op(DOM0_READCONSOLE);
+       {
+               char buf[2];
+               test_read_console_ring_out = 113; 
+               op->u.readconsole.buffer = buf;
+               op->u.readconsole.count = 100;
+               op->u.readconsole.clear = 1;
+               test_cond(do_dom0_op(fake_to_user(op)) == 113);
+               test_cond(test_read_console_ring_in_clear == 1);
+               test_cond(buf[1] == 'A');
+               test_cond(op->u.readconsole.buffer == buf+1);
+               test_cond(op->u.readconsole.count == 1);
+       }
+
+       op = _test_op(DOM0_SCHED_ID);
+       test_sched_id_out = 114;
+       /* FIXME: Doesn't return -EFAULT on copy_to_user failing. */
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(op->u.sched_id.sched_id == 114);
+
+       op = _test_op(DOM0_SETDOMAINMAXMEM);
+       op->u.setdomainmaxmem.domain = 115;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       op->u.setdomainmaxmem.max_memkb = 116;
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(current->domain->max_pages == 116*1024/(1<<PAGE_SHIFT));
+
+       op = _test_op(DOM0_SETDOMAINHANDLE);
+       op->u.setdomainhandle.domain = 117;
+       fake_find_domain_out = NULL;
+       test_cond(do_dom0_op(fake_to_user(op)) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       strcpy((char *)op->u.setdomainhandle.handle, "handle2");
+       test_cond(do_dom0_op(fake_to_user(op)) == 0);
+       test_cond(strcmp((char *)current->domain->handle, "handle2") == 0);
+
+       op = _test_op(10001);
+       test_arch_do_dom0_op_out = 118;
+       test_cond(do_dom0_op(fake_to_user(op)) == 118);
+       return 0;
+}
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_domain.c 
xen-unstable.hg-check/xen/common/test/test_domain.c
--- xen-unstable.hg-mainline/xen/common/test/test_domain.c      1970-01-01 
10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_domain.c 2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,832 @@
+/*  Tests for domain.c
+    Copyright (C) 2005 Tony Breeds IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "fake-support.h"
+
+/* BEGIN: Stuff for fake */
+/* Attribute tags */
+
+#define DOMAIN_HASH_SIZE 256
+#define DOMAIN_HASH(_id) ((int)(_id)&(DOMAIN_HASH_SIZE-1))
+
+/*
+ * Commands to HYPERVISOR_vm_assist().
+ */
+#define VMASST_CMD_enable                0
+#define VMASST_CMD_disable               1
+#define VMASST_TYPE_4gb_segments         0
+#define VMASST_TYPE_4gb_segments_notify  1
+#define VMASST_TYPE_writable_pagetables  2
+#define MAX_VMASST_TYPE 2
+
+#define for_each_domain(_d)                     \
+ for ( (_d) = domain_list;                      \
+       (_d) != NULL;                            \
+       (_d) = (_d)->next_in_list )
+
+#define for_each_vcpu(_d,_v)                    \
+ for ( (_v) = (_d)->vcpu[0];                    \
+       (_v) != NULL;                            \
+       (_v) = (_v)->next_in_list )
+
+/*
+ * Per-VCPU flags (vcpu_flags).
+ */
+ /* Has the FPU been initialised? */
+#define _VCPUF_fpu_initialised 0
+#define VCPUF_fpu_initialised  (1UL<<_VCPUF_fpu_initialised)
+ /* Has the FPU been used since it was last saved? */
+#define _VCPUF_fpu_dirtied     1
+#define VCPUF_fpu_dirtied      (1UL<<_VCPUF_fpu_dirtied)
+ /* Domain is blocked waiting for an event. */
+#define _VCPUF_blocked         2
+#define VCPUF_blocked          (1UL<<_VCPUF_blocked)
+ /* Currently running on a CPU? */
+#define _VCPUF_running         3
+#define VCPUF_running          (1UL<<_VCPUF_running)
+ /* Disables auto-migration between CPUs. */
+#define _VCPUF_cpu_pinned      4
+#define VCPUF_cpu_pinned       (1UL<<_VCPUF_cpu_pinned)
+ /* Domain migrated between CPUs. */
+#define _VCPUF_cpu_migrated    5
+#define VCPUF_cpu_migrated     (1UL<<_VCPUF_cpu_migrated)
+ /* Initialization completed. */
+#define _VCPUF_initialised     6
+#define VCPUF_initialised      (1UL<<_VCPUF_initialised)
+ /* VCPU is not-runnable */
+#define _VCPUF_down            7
+#define VCPUF_down             (1UL<<_VCPUF_down)
+
+#define VCPUOP_initialise           0
+#define VCPUOP_up                   1
+#define VCPUOP_down                 2
+#define VCPUOP_is_up                3
+
+
+#define cpus_empty(src) __cpus_empty(&(src), NR_CPUS)
+static inline int __cpus_empty(const cpumask_t *srcp, int nbits)
+{
+       return *srcp == 0UL;
+}
+
+#define LOCK_BIGLOCK(_d) spin_lock_recursive(&(_d)->big_lock)
+#define UNLOCK_BIGLOCK(_d) spin_unlock_recursive(&(_d)->big_lock)
+static void cleanup_writable_pagetable(struct domain *d) {}
+#define sync_pagetable_state(d)                 \
+    do {                                        \
+        LOCK_BIGLOCK(d);                        \
+        cleanup_writable_pagetable(d);          \
+        UNLOCK_BIGLOCK(d);                      \
+    } while ( 0 )
+
+/* 
+ * VIRTUAL INTERRUPTS
+ * 
+ * Virtual interrupts that a guest OS may receive from Xen.
+ */
+#define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
+#define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
+#define NR_VIRQS        7
+
+
+/*
+ * Per-domain flags (domain_flags).
+ */
+ /* Is this one of the per-CPU idle domains? */
+#define _DOMF_idle_domain      0
+#define DOMF_idle_domain       (1UL<<_DOMF_idle_domain)
+ /* Is this domain privileged? */
+#define _DOMF_privileged       1
+#define DOMF_privileged        (1UL<<_DOMF_privileged)
+ /* May this domain do IO to physical devices? */
+#define _DOMF_physdev_access   2
+#define DOMF_physdev_access    (1UL<<_DOMF_physdev_access)
+ /* Guest shut itself down for some reason. */
+#define _DOMF_shutdown         3
+#define DOMF_shutdown          (1UL<<_DOMF_shutdown)
+ /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
+#define _DOMF_shuttingdown     4
+#define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
+ /* Death rattle. */
+#define _DOMF_dying            5
+#define DOMF_dying             (1UL<<_DOMF_dying)
+ /* Domain is paused by controller software. */
+#define _DOMF_ctrl_pause       6
+#define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
+
+
+/*
+ * Reason codes for SCHEDOP_shutdown. These may be interpreted by controller
+ * software to determine the appropriate action. For the most part, Xen does
+ * not care about the shutdown code.
+ */
+#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
+#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
+#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
+#define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
+/*   END: Stuff for fake */
+
+#define _TEST_DOMAIN_DESTRUCTED_POWER 31 /* Keep these 2 in sync */
+#define DOMAIN_DESTRUCTED (1<<31)        /* assumes atomic_t is >= 32 bits */
+
+/* Empty functions */
+static void debugger_trap_immediate(void) {}
+static void sched_rem_domain(struct vcpu *v) {}
+static void vcpu_sleep_sync(struct vcpu *v) {}
+static void vcpu_sleep_nosync(struct vcpu *v) {}
+static void vcpu_wake(struct vcpu *v) {}
+static void show_registers(struct cpu_user_regs *regs) {}
+
+static void domain_relinquish_resources(struct domain *d) {}
+static inline void send_guest_virq(struct vcpu *v, int virq) {}
+static void free_perdomain_pt(struct domain *d) {}
+#define free_xenheap_page(v) (free_xenheap_pages(v,0))
+static void free_xenheap_pages(void *v, unsigned int order) {}
+static void arch_do_createdomain(struct vcpu *v) {}
+
+/* Override fake printk (it abort()s) */
+void printk(const char *format, ...) {}
+
+/* Only one softirq used in domain.c. */
+#define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ  6
+
+typedef void (*softirq_handler)(void);
+softirq_handler  _test_handler;
+
+static inline void open_softirq(int nr, softirq_handler handler)
+{
+       test_cond(nr == DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ);
+        _test_handler = handler;
+}
+
+static void do_softirq(void)
+{
+       _test_handler();
+}
+
+static inline void raise_softirq(unsigned int nr) {}
+
+typedef struct {
+    /* IN variables. */
+    domid_t               domain;
+    uint16_t              vcpu;
+    /* IN/OUT parameters */
+    vcpu_guest_context_t *ctxt;
+} dom0_setdomaininfo_t;
+
+/* Forward declarations for functions from ../domain.c */
+/* FIXME: Move prototypes from sched.h to domain.h */
+struct domain *do_createdomain(domid_t dom_id, unsigned int cpu);
+struct domain *find_domain_by_id(domid_t dom);
+void domain_kill(struct domain *d);
+void domain_crash(struct domain *d);
+void domain_crash_synchronous(void);
+static void domain_shutdown_finalise(void);
+static __init int domain_shutdown_finaliser_init(void);
+void domain_shutdown(struct domain *d, u8 reason);
+void domain_pause_for_debugger(void);
+void domain_destruct(struct domain *d);
+void vcpu_pause(struct vcpu *v);
+void domain_pause(struct domain *d);
+void vcpu_unpause(struct vcpu *v);
+void domain_unpause(struct domain *d);
+void domain_pause_by_systemcontroller(struct domain *d);
+void domain_unpause_by_systemcontroller(struct domain *d);
+int set_info_guest(struct domain *d, dom0_setdomaininfo_t *setdomaininfo);
+int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt);
+long do_vcpu_op(int cmd, int vcpuid, void *arg);
+long vm_assist(struct domain *p, unsigned int cmd, unsigned int type);
+
+/* FIXME: Use a list to track allocation/frees of domains and vcpus */
+static int _test_alloc_domain_error = 0;
+static struct domain *alloc_domain(void)
+{
+       struct domain *d;
+
+
+       if (_test_alloc_domain_error)
+               return NULL;
+
+       d = malloc(sizeof(struct domain));
+       test_cond(d != NULL);
+       /* FIXME: don't use memset it will defeat valgrind's memcheck */
+       memset(d, 0, sizeof(struct domain));
+       return d;
+}
+
+static void free_domain(struct domain *d)
+{
+    int i;
+    struct vcpu *v;
+
+    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- ) {
+        if ( d->vcpu[i] != NULL ) {
+               v = d->vcpu[i];
+               test_cond(v->next_in_list == NULL);
+
+               if ( v->vcpu_id != 0 ) {
+                       v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
+               }
+               free(v);
+       }
+    }
+
+    free(d);
+}
+
+static int _test_alloc_vcpu_error = 0;
+static struct vcpu *alloc_vcpu(struct domain *d, unsigned int vcpu_id, 
+                               unsigned int cpu_id)
+{
+       struct vcpu *v;
+
+       if (_test_alloc_vcpu_error)
+               return NULL;
+
+       test_cond(d->vcpu[vcpu_id] == NULL);
+
+       v = malloc(sizeof(struct vcpu));
+       test_cond(v != NULL);
+       /* FIXME: don't use memset it will defeat valgrind's memcheck */
+       memset(v, 0, sizeof(struct vcpu));
+
+       v->domain = d;
+       v->vcpu_id = vcpu_id;
+       v->processor = cpu_id;
+       atomic_set(&v->pausecnt, 0);
+       d->vcpu[vcpu_id] = v;
+
+       /* from sched_add_domain */
+       if ( is_idle_task(d) ) {
+                set_bit(_VCPUF_running, &v->vcpu_flags);
+       }
+
+       if ( vcpu_id != 0 ) {
+               d->vcpu[v->vcpu_id-1]->next_in_list = v;
+               set_bit(_VCPUF_down, &v->vcpu_flags);
+       }
+
+       return v;
+}
+
+
+/* from common/event_channel.c */
+static int _test_evtchn[DOMAIN_HASH_SIZE] =
+       { [0 ... DOMAIN_HASH_SIZE-1] = 42 };
+static int _test_evtchn_error = 0;
+static int evtchn_init(struct domain *d)
+{
+       int retval;
+       int slot = d->domain_id;
+
+       /* Event Channels are not created for IDLE_DOMAIN_ID */
+       test_cond(d->domain_id != IDLE_DOMAIN_ID);
+
+       if (slot >= DOMAIN_HASH_SIZE) {
+               slot /= DOMAIN_HASH_SIZE;
+       }
+
+       test_cond(slot <= DOMAIN_HASH_SIZE-1);
+
+       if (!_test_evtchn_error) {
+               _test_evtchn[slot] = 24;
+               retval = 0;
+       } else {
+               _test_evtchn[slot] = 42;
+               retval = -EINVAL;
+       }
+
+       return retval;
+}
+
+static void evtchn_destroy(struct domain *d)
+{
+       int slot  = d->domain_id;
+
+       /* Event Channels are not created for IDLE_DOMAIN_ID
+        * so destorying them makes no sense.
+        * event_channel.c handles this better than this test suite */
+       if (d->domain_id == IDLE_DOMAIN_ID)
+               return;
+
+       if (slot >= DOMAIN_HASH_SIZE) {
+               slot /= DOMAIN_HASH_SIZE;
+       }
+
+       test_cond(slot <= DOMAIN_HASH_SIZE-1);
+
+       _test_evtchn[slot] = 42;
+}
+
+/* from common/grant_table.c */
+static int _test_granttable[DOMAIN_HASH_SIZE] = 
+       { [0 ... DOMAIN_HASH_SIZE-1] = 42 };
+static int _test_granttable_error = 0;
+static int grant_table_create(struct domain *d)
+{
+       int retval;
+       int slot = d->domain_id;
+
+       /* Grant tables are not created for IDLE_DOMAIN_ID */
+       test_cond(d->domain_id != IDLE_DOMAIN_ID);
+
+       if (slot >= DOMAIN_HASH_SIZE) {
+               slot /= DOMAIN_HASH_SIZE;
+       }
+
+       test_cond(slot <= DOMAIN_HASH_SIZE-1);
+
+       if (!_test_granttable_error) {
+               _test_granttable[slot] = 24;
+               retval = 0;
+       } else {
+               _test_granttable[slot] = 42;
+               retval = -ENOMEM;
+       }
+
+       return retval;
+}
+
+static void grant_table_destroy(struct domain *d)
+{
+       int slot = d->domain_id;
+
+       /* Grant tables are not created for IDLE_DOMAIN_ID
+        * so destorying them makes no sense.
+        * grant_table.c handles this better than this test suite */
+       if (d->domain_id == IDLE_DOMAIN_ID)
+               return;
+
+       if (slot >= DOMAIN_HASH_SIZE) {
+               slot /= DOMAIN_HASH_SIZE;
+       }
+
+       test_cond(slot <= DOMAIN_HASH_SIZE-1);
+
+       _test_granttable[slot] = 42;
+}
+
+int _test_arch_set_info_guest_result = 0;
+static int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
+{
+       return _test_arch_set_info_guest_result;
+}
+
+#define guest_cpu_user_regs() (NULL)
+
+/* FIXME: The real versions of machine_halt/machine_restart are
+ * noreturns, which means that the tail end of domain_shutdown
+ * is never executed in the domain_id == 0 case.
+ * #define'ing them to return will not work becuase there is no symbol
+ * for the extern to match */
+static int _test_machine_state = 0;
+static void machine_restart(char __attribute__((unused)) *addr)
+{
+       _test_machine_state = 1;
+}
+
+static void machine_halt(void)
+{
+       _test_machine_state = 2;
+}
+
+#include "../domain.c"
+
+/* FIXME: do not re-use allocations.  malloc again! */
+int main(int argc, char *argv[])
+{
+       int i;
+       struct domain *_test_domains[DOMAIN_HASH_SIZE] = 
+                                      {[0 ... DOMAIN_HASH_SIZE-1] = NULL};
+       struct vcpu *_test_vcpus[10] = {[0 ... 9] = NULL};
+       domid_t domain_id;
+       struct domain *d;
+       struct vcpu_guest_context *_test_guest_context;
+       dom0_setdomaininfo_t *_test_setdomaininfo;
+
+       parse_test_args(argc, argv);
+
+       /* build current() */
+       current = malloc(sizeof(struct vcpu));
+       current->domain = malloc(sizeof(struct domain));
+
+       current->domain->vcpu[0] = current;
+       dom0 = current->domain;
+       spin_lock_init(&current->domain->big_lock);
+
+       /* Test domain_shutdown_finaliser_init */
+       test_cond(_test_handler == NULL);
+       domain_shutdown_finaliser_init();
+       test_cond(_test_handler == domain_shutdown_finalise);
+
+       /* Test vm_assist */
+       test_cond(vm_assist(current->domain, -1, MAX_VMASST_TYPE) == -ENOSYS);
+       test_cond(vm_assist(current->domain, VMASST_CMD_enable, 
MAX_VMASST_TYPE+1)
+                         == -EINVAL);
+
+       current->domain->vm_assist = 0UL;
+       test_cond(!vm_assist(current->domain, VMASST_CMD_enable, 
+                         VMASST_TYPE_4gb_segments));
+       test_cond(current->domain->vm_assist != 0);
+
+       test_cond(!vm_assist(current->domain, VMASST_CMD_disable, 
+                         VMASST_TYPE_4gb_segments));
+       test_cond(current->domain->vm_assist == 0);
+
+       test_cond(!vm_assist(current->domain, VMASST_CMD_enable, 
+                         VMASST_TYPE_4gb_segments_notify));
+       test_cond(current->domain->vm_assist != 0);
+
+       test_cond(!vm_assist(current->domain, VMASST_CMD_disable, 
+                         VMASST_TYPE_4gb_segments_notify));
+       test_cond(current->domain->vm_assist == 0);
+
+       test_cond(!vm_assist(current->domain, VMASST_CMD_enable, 
+                         VMASST_TYPE_writable_pagetables));
+       test_cond(current->domain->vm_assist != 0);
+
+       test_cond(!vm_assist(current->domain, VMASST_CMD_disable, 
+                         VMASST_TYPE_writable_pagetables));
+       test_cond(current->domain->vm_assist == 0);
+
+       /* Nothing to test for boot_vcpu(), it will either BUG_ON or
+        * pass back the result of arch_set_info_guest() */
+
+       /* Test do_createdomain failure paths */
+       _test_alloc_domain_error = 1;
+       _test_domains[0] = do_createdomain(0, 0);
+       test_cond(_test_domains[0] == NULL);
+       _test_alloc_domain_error = 0;
+
+       _test_granttable_error = 1;
+       _test_domains[0] = do_createdomain(0, 0);
+       test_cond(_test_domains[0] == NULL);
+       test_cond(_test_evtchn[0] == 42);
+       _test_granttable_error = 0;
+
+       _test_evtchn_error = 1;
+       _test_domains[0] = do_createdomain(0, 0);
+       test_cond(_test_domains[0] == NULL);
+       /* check event channel was destroyed */
+       test_cond(_test_evtchn[0] == 42);
+       _test_evtchn_error = 0;
+
+       _test_alloc_vcpu_error = 1;
+       _test_evtchn[0] = 99;
+       _test_granttable[0] = 99;
+       _test_domains[0] = do_createdomain(IDLE_DOMAIN_ID, 0);
+       test_cond(_test_domains[0] == NULL);
+       test_cond(_test_evtchn[0] == 99);
+       test_cond(_test_granttable[0] == 99);
+
+       _test_evtchn[0] = 42;
+       _test_granttable[0] = 42;
+       _test_domains[0] = do_createdomain(0, 0);
+       test_cond(_test_domains[0] == NULL);
+       /* check granttable was destroyed */
+       test_cond(_test_granttable[0] == 42);
+       _test_alloc_vcpu_error = 0;
+
+       /* Test do_createdomain and domain_destruct */
+       for(i=DOMAIN_HASH_SIZE-1; i>=0; i--) {
+               _test_domains[i] = do_createdomain(i, 0);
+               test_cond(_test_domains[i] != NULL);
+               test_cond(_test_domains[i]->next_in_hashbucket == NULL);
+               test_cond(_atomic_read(_test_domains[i]->refcnt) == 1);
+               test_cond(_test_evtchn[i] == 24);
+       }
+
+
+       /* Walk the list checking sorted by domain_id, and all domains are 
+        * found */
+       domain_id =  domain_list->domain_id;
+       d = domain_list;
+       i=0;
+
+       while (d->next_in_list != NULL) {
+               test_cond(domain_id <= d->domain_id);
+               d = d->next_in_list;
+               domain_id = d->domain_id;
+               i++;
+       }
+       test_cond(i == DOMAIN_HASH_SIZE-1);
+
+       /* check each hasbucket got excactly one domain */
+       for(i = 0; i< DOMAIN_HASH_SIZE; i++) {
+               int hash_val = DOMAIN_HASH(_test_domains[i]->domain_id);
+
+               test_cond(domain_hash[hash_val] == _test_domains[i]);
+               test_cond(domain_hash[hash_val]->next_in_hashbucket == NULL);
+       }
+
+       for(i = 0; i< DOMAIN_HASH_SIZE; i++) {
+               domid_t old_domainid = _test_domains[i]->domain_id;
+
+               test_cond(domain_list->domain_id == 
_test_domains[i]->domain_id);
+               test_cond(_atomic_read(domain_list->refcnt) == 1);
+
+               set_bit(_DOMF_dying, &_test_domains[i]->domain_flags);
+               domain_destruct(_test_domains[i]);
+
+               test_cond(domain_list->domain_id == 
_test_domains[i]->domain_id);
+
+               _atomic_set(domain_list->refcnt, 0); 
+               domain_destruct(_test_domains[i]);
+
+               if (i == DOMAIN_HASH_SIZE-1) {
+                       test_cond(domain_list == NULL);
+               } else {
+                       test_cond(domain_list->domain_id != old_domainid);
+               }
+
+               test_cond(_test_evtchn[i] == 42);
+               _test_domains[i] = NULL;
+       }
+
+       /* Test find_domain_by_id (Uses hashbucket ops) */
+       /* Interleave domain creation requests */
+       for(i=1; i<=2; i++) {
+               int j;
+               for(j=(DOMAIN_HASH_SIZE/4)-i; j>=0; j-=2) {
+                       int k = j*DOMAIN_HASH_SIZE;
+                       _test_domains[j] = do_createdomain(k, 0);
+                       test_cond(_test_domains[j] != NULL);
+               }
+       }
+
+       domain_id =  domain_list->domain_id;
+       d = domain_list;
+       i=0;
+
+       while (d->next_in_hashbucket != NULL) {
+               test_cond(domain_id <= d->domain_id);
+               d = d->next_in_hashbucket;
+               domain_id = d->domain_id;
+               i++;
+       }
+       test_cond(i == (DOMAIN_HASH_SIZE/4)-1);
+
+       /* find_domain_by_id will fail if the domain is DOMAIN_DESTRUCTED */
+       fake_get_domain_out = 0;
+       test_cond(get_domain(_test_domains[0]) == 0);
+       test_cond(find_domain_by_id(_test_domains[0]->domain_id) == NULL);
+       fake_get_domain_out = 1;
+
+       /* Check ref counts work as expected */
+       for(i = 0; i< (DOMAIN_HASH_SIZE/4); i++) {
+               int refcnt = _atomic_read(_test_domains[i]->refcnt);
+
+               test_cond(refcnt == 1);
+               test_cond(find_domain_by_id(_test_domains[i]->domain_id) != 
NULL);
+               test_cond(_atomic_read(_test_domains[i]->refcnt) == refcnt+1);
+
+               put_domain(_test_domains[i]);
+               test_cond(_atomic_read(_test_domains[i]->refcnt) == refcnt);
+       }
+
+       /* destroty the created domains and structures */
+       for(i = 0; i< (DOMAIN_HASH_SIZE/4); i++) {
+               set_bit(_DOMF_dying, &_test_domains[i]->domain_flags);
+               _atomic_set(domain_list->refcnt, 0);
+               domain_destruct(_test_domains[i]);
+
+               test_cond(_test_evtchn[i] == 42);
+       }
+
+       /* Test do_vcpu_op */
+       current->domain->vcpu[0] = NULL;
+       test_cond(do_vcpu_op(-1, -1, NULL) == -EINVAL);
+       test_cond(do_vcpu_op(-1, MAX_VIRT_CPUS-1, NULL) == -ENOENT);
+
+       current->domain->vcpu[0] = current;
+
+       /* What protects against invalid cmds? */
+       test_cond(!do_vcpu_op(-1, 0, NULL));
+
+       /* Need instrumentation to fail copy_to/from_user */
+       _test_guest_context = malloc(sizeof(struct vcpu_guest_context));
+       /* FIXME: don't use memset it will defeat valgrind's memcheck */
+       memset(_test_guest_context, 0, sizeof(struct vcpu_guest_context));
+
+       set_bit(_VCPUF_initialised, &current->vcpu_flags);
+       test_cond(do_vcpu_op(VCPUOP_initialise, 0, 
+              fake_to_user(_test_guest_context)) == -EEXIST);
+       clear_bit(_VCPUF_initialised, &current->vcpu_flags);
+
+       /* do_vcpu_op(VCPUOP_initialise,...) should pass back the result of
+        * boot_vcpu, which passes back the arch_set_info_guest() result */
+       _test_arch_set_info_guest_result = -EINVAL;
+       test_cond(do_vcpu_op(VCPUOP_initialise, 0, 
+              fake_to_user(_test_guest_context)) ==
+              _test_arch_set_info_guest_result);
+       _test_arch_set_info_guest_result = 0;
+       test_cond(do_vcpu_op(VCPUOP_initialise, 0, 
+               fake_to_user(_test_guest_context)) == 
+               _test_arch_set_info_guest_result);
+
+       current->vcpu_flags = 0UL;
+       test_cond(do_vcpu_op(VCPUOP_up, 0, NULL) == -EINVAL);
+
+       set_bit(_VCPUF_initialised, &current->vcpu_flags);
+       test_cond(!do_vcpu_op(VCPUOP_up, 0, NULL));
+
+       set_bit(_VCPUF_down, &current->vcpu_flags);
+       test_cond(!do_vcpu_op(VCPUOP_up, 0, NULL));
+       test_cond(!test_bit(_VCPUF_down, &current->vcpu_flags));
+
+       test_cond(do_vcpu_op(VCPUOP_is_up, 0, NULL) ==
+              !test_bit(_VCPUF_down, &current->vcpu_flags));
+
+       test_cond(!do_vcpu_op(VCPUOP_down, 0, NULL));
+       test_cond(test_bit(_VCPUF_down, &current->vcpu_flags));
+
+       /* Test set_info_guest */
+       _test_setdomaininfo = malloc(sizeof(dom0_setdomaininfo_t));
+
+       current->domain->vcpu[0] = NULL;
+       _test_setdomaininfo->vcpu = MAX_VIRT_CPUS;
+       current->domain->domain_flags = 0UL;
+       _test_setdomaininfo->ctxt = fake_from_user(_test_guest_context);
+
+       test_cond(set_info_guest(current->domain, _test_setdomaininfo) == 
-EINVAL);
+       _test_setdomaininfo->vcpu = 0;
+       test_cond(set_info_guest(current->domain, _test_setdomaininfo) == 
-EINVAL);
+       current->domain->vcpu[0] = current;
+
+       test_cond(set_info_guest(current->domain, _test_setdomaininfo) == 
-EINVAL);
+       set_bit(_DOMF_ctrl_pause, &current->domain->domain_flags);
+
+       _test_arch_set_info_guest_result = -ENOSYS;
+       test_cond(set_info_guest(current->domain, _test_setdomaininfo) ==
+              _test_arch_set_info_guest_result);
+       _test_arch_set_info_guest_result = 0;
+
+       /* Test domain_unpause_by_systemcontroller and 
+        *      domain_unpause_by_systemcontroller */
+       _test_domains[0] = do_createdomain(0, 0);
+       _test_domains[0]->domain_flags = 0UL;
+       current->domain->domain_flags = 0UL;
+       set_bit(_DOMF_ctrl_pause, &_test_domains[0]->domain_flags );
+
+       domain_unpause_by_systemcontroller(_test_domains[0]);
+       test_cond(!test_bit(_DOMF_ctrl_pause, &_test_domains[0]->domain_flags));
+       domain_pause_by_systemcontroller(_test_domains[0]);
+       test_cond(test_bit(_DOMF_ctrl_pause, &_test_domains[0]->domain_flags));
+
+       free_domain(_test_domains[0]);
+
+       /* Test vcpu_pause/vcpu_unpause and domain_pause/domain_unpause */
+       for(i=0;i<10;i++) {
+               _test_vcpus[i] = malloc(sizeof(struct vcpu));
+               test_cond(_test_vcpus[i] != NULL);
+               _test_vcpus[i]->domain = malloc(sizeof(struct domain));
+               test_cond(_test_vcpus[i]->domain != NULL);
+
+               atomic_set(&_test_vcpus[i]->pausecnt, 0);
+               _test_vcpus[i]->domain->vcpu[0] = _test_vcpus[i];
+               spin_lock_init(&_test_vcpus[i]->domain->big_lock);
+       }
+
+       for(i=0;i<10;i++) {
+               int j;
+               for(j=1;j<=9;j++) {
+                       vcpu_pause(_test_vcpus[i]);
+                       test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == j);
+               }
+
+               test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 9);
+
+               for(j=9;j>=1;j--) {
+                       vcpu_unpause(_test_vcpus[i]);
+                       test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 
j-1);
+               }
+
+               test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 0);
+       }
+
+       for(i=0;i<10;i++) {
+               int j;
+               for(j=1;j<=9;j++) {
+                       domain_pause(_test_vcpus[i]->domain);
+                       test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == j);
+               }
+
+               test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 9);
+
+               for(j=9;j>=1;j--) {
+                       domain_unpause(_test_vcpus[i]->domain);
+                       test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 
j-1);
+               }
+
+               test_cond(atomic_read(&_test_vcpus[i]->pausecnt) == 0);
+       }
+
+       for(i=0;i<10;i++) {
+               test_cond(_test_vcpus[i]->domain->big_lock._l == 88);
+               free(_test_vcpus[i]->domain);
+               free(_test_vcpus[i]);
+       }
+
+       /* Test domain_pause_for_debugger */
+       current->domain->domain_flags = 0UL;
+       domain_pause_for_debugger();
+       test_cond(test_bit(_DOMF_ctrl_pause, &current->domain->domain_flags));
+
+       /* Test domain_shutdown */
+       _test_vcpus[0] = malloc(sizeof(struct vcpu));
+       test_cond(_test_vcpus[0] != NULL);
+       _test_vcpus[0]->domain = malloc(sizeof(struct domain));
+       test_cond(_test_vcpus[0]->domain != NULL);
+       _test_vcpus[0]->domain->vcpu[0] = _test_vcpus[0];
+       _test_domains[0] = _test_vcpus[0]->domain;
+
+       atomic_set(&_test_vcpus[0]->pausecnt, 0);
+       spin_lock_init(&_test_vcpus[0]->domain->big_lock);
+
+       _test_domains[0]->domain_id = 1;
+       set_bit(_DOMF_shuttingdown, &_test_domains[0]->domain_flags);
+       test_cond(domain_shuttingdown[smp_processor_id()] != _test_domains[0]);
+
+       domain_shutdown(_test_domains[0], 255);
+       test_cond(_test_domains[0]->shutdown_code == 255);
+       test_cond(test_bit(_DOMF_shuttingdown, 
&_test_domains[0]->domain_flags));
+
+       clear_bit(_DOMF_shuttingdown, &_test_domains[0]->domain_flags);
+       domain_shutdown(_test_domains[0], 254);
+       test_cond(_test_domains[0]->shutdown_code == 254);
+       test_cond(domain_shuttingdown[smp_processor_id()] == _test_domains[0]);
+
+       /* Now test the dodgy domain_id = 0 cases */
+       _test_domains[0]->domain_id = 0;
+       _test_domains[0]->shutdown_code = 0;
+       set_bit(_DOMF_shuttingdown, &_test_domains[0]->domain_flags);
+       domain_shuttingdown[smp_processor_id()] = NULL;
+
+       domain_shutdown(_test_domains[0], 254);
+       test_cond(_test_machine_state == 1);
+       _test_machine_state = 0;
+
+       domain_shutdown(_test_domains[0], SHUTDOWN_poweroff);
+       test_cond(_test_machine_state == 2);
+       _test_machine_state = 0;
+       
+       /* Test domain_shutdown_finalise */
+       _test_domains[0]->domain_flags = 0UL;
+       set_bit(_DOMF_shuttingdown, &_test_domains[0]->domain_flags);
+       domain_shuttingdown[smp_processor_id()] = _test_domains[0];
+
+       domain_shutdown_finalise();
+       test_cond(!test_bit(_DOMF_shuttingdown, 
&_test_domains[0]->domain_flags));
+       test_cond(test_bit(_DOMF_shutdown, &_test_domains[0]->domain_flags));
+
+       /* domain_crash/domain_crash_synchronous call previously tested
+        * functions */
+
+       /* Test domain_kill */
+       atomic_set(&_test_vcpus[0]->pausecnt, 0);
+       atomic_set(&_test_domains[0]->refcnt, 2);
+       _test_domains[0]->domain_flags = 0UL;
+       set_bit(_DOMF_dying, &_test_domains[0]->domain_flags);
+       domain_kill(_test_domains[0]);
+       test_cond(atomic_read(&_test_vcpus[0]->pausecnt) == 1);
+       test_cond(test_bit(_DOMF_dying, &_test_domains[0]->domain_flags));
+
+       clear_bit(_DOMF_dying, &_test_domains[0]->domain_flags);
+
+       domain_kill(_test_domains[0]);
+       test_cond(atomic_read(&_test_vcpus[0]->pausecnt) == 2);
+       test_cond(atomic_read(&_test_domains[0]->refcnt) == 1);
+
+       free(_test_vcpus[0]->domain);
+       free(_test_vcpus[0]);
+
+       free(_test_setdomaininfo);
+       free(_test_guest_context);
+
+       free(current->domain);
+       free(current);
+
+       return 0;
+}
diff -urN --exclude=.hg --exclude='*~' --exclude='*.aux' 
xen-unstable.hg-mainline/xen/common/test/test_event_channel.c 
xen-unstable.hg-check/xen/common/test/test_event_channel.c
--- xen-unstable.hg-mainline/xen/common/test/test_event_channel.c       
1970-01-01 10:00:00.000000000 +1000
+++ xen-unstable.hg-check/xen/common/test/test_event_channel.c  2005-12-09 
16:33:19.000000000 +1100
@@ -0,0 +1,768 @@
+/*  Tests for event_channel.c
+ *
+    Copyright (C) 2005 Tony Breeds IBM Corporation
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "fake-support.h"
+
+#define        BUG()
+#define DPRINTK(...)
+
+#define for_each_vcpu(_d,_v)                    \
+ for ( (_v) = (_d)->vcpu[0];                    \
+       (_v) != NULL;                            \
+       (_v) =  NULL)
+
+/* Override fake printk (it abort()s) */
+void printk(const char *format, ...) {}
+
+static struct vcpu *_test_evtchn_set_pending_in_v;
+static int _test_evtchn_set_pending_in_port;
+static void evtchn_set_pending(struct vcpu *v, int port)
+{
+       _test_evtchn_set_pending_in_v = v;
+       _test_evtchn_set_pending_in_port = port;
+}
+
+static struct vcpu *_test_pirq_guest_bind_in_v;
+static int _test_pirq_guest_bind_in_irq;
+static int _test_pirq_guest_bind_in_will_share;
+static int _test_pirq_guest_bind_out = 0;
+static int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
+{
+       _test_pirq_guest_bind_in_v = v;
+       _test_pirq_guest_bind_in_irq = irq;
+       _test_pirq_guest_bind_in_will_share = will_share;
+
+       return _test_pirq_guest_bind_out;
+}
+
+static struct domain *_test_pirq_guest_unbind_in_d;
+static int _test_pirq_guest_unbind_in_irq;
+static int _test_pirq_guest_unbind_out = 0;
+static int pirq_guest_unbind(struct domain *d, int irq)
+{
+       _test_pirq_guest_unbind_in_d = d;
+       _test_pirq_guest_unbind_in_irq = irq;
+       
+       return _test_pirq_guest_unbind_out;
+}
+
+/* Setup a minimal vcpu/domain pair, ensuring that commonly used fields
+ * contain sensible defaults */
+static struct vcpu *test_alloc_vcpu(void)
+{
+       struct vcpu *v;
+
+       v = malloc(sizeof(struct vcpu));
+       v->domain = malloc(sizeof(struct domain));
+
+       v->domain->vcpu[0] = v;
+       v->domain->domain_id = 0;
+       atomic_set(&v->domain->refcnt, 0);
+       spin_lock_init(&v->domain->evtchn_lock);
+
+       /* Ensure that all event channels are empty */
+       memset(v->domain->evtchn, 0, 
+              NR_EVTCHN_BUCKETS * sizeof(v->domain->evtchn[0]));
+
+       return v;
+}
+
+#include "../../include/public/event_channel.h"
+
+/* needs evtchn_op_t from public/event_channel.h */
+
+static evtchn_op_t *test_alloc_evtchn_op(int cmd)
+{
+       evtchn_op_t *op;
+
+       op = malloc(sizeof(evtchn_op_t));
+       op->cmd = cmd;
+
+       return op;
+}
+
+
+static evtchn_op_t *_test_acm_pre_event_channel_in_op;
+static int _test_acm_pre_event_channel_out = 0;
+static inline int acm_pre_event_channel(evtchn_op_t *op) 
+{ 
+       _test_acm_pre_event_channel_in_op = op;
+       return _test_acm_pre_event_channel_out;
+}
+
+
+/* Forward declarations for event_channel.c */
+long evtchn_send(int lport);
+void send_guest_pirq(struct domain *d, int pirq);
+long do_event_channel_op(evtchn_op_t *uop);
+int evtchn_init(struct domain *d);
+void evtchn_destroy(struct domain *d);
+
+
+#include "../event_channel.c"
+
+int main(int argc, char *argv[])
+{
+       int i;
+
+       struct vcpu *remote_vcpu = NULL;
+       evtchn_close_t *close_opts;
+       evtchn_op_t *uop;
+       evtchn_alloc_unbound_t *unbound_alloc;
+       evtchn_bind_interdomain_t *interdomain_bind;
+       evtchn_bind_virq_t *virq_bind;
+       evtchn_bind_ipi_t *ipi_bind;
+       evtchn_bind_pirq_t *pirq_bind;
+       evtchn_status_t  *status;
+       evtchn_bind_vcpu_t *vcpu_bind;
+
+       current = test_alloc_vcpu();
+
+       parse_test_args(argc, argv);
+
+       /* Test get_free_port */
+       for(i=0; i<MAX_EVTCHNS; i++) {
+               int port = get_free_port(current->domain);
+
+               if ((port%EVTCHNS_PER_BUCKET) == 0) 
+                       fake_expect_xmalloc = 1;
+               test_cond(port == i);
+               test_cond(evtchn_from_port(current->domain, port)->state == 
+                      ECS_FREE);
+               evtchn_from_port(current->domain, port)->state = ECS_RESERVED;
+       }
+
+       test_cond(get_free_port(current->domain) == -ENOSPC);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+               current->domain->evtchn[i] = NULL;
+       }
+       fake_xmalloc_expected = 0;
+
+       /* Test evtchn_init */
+       current = test_alloc_vcpu();
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_RESERVED);
+       test_cond(evtchn_init(current->domain) == -EINVAL);
+
+       /* evtchn_init relies on evtchn_destroy to free the allocated memory */
+       xfree(current->domain->evtchn[0]);
+       current->domain->evtchn[0] = NULL;
+       fake_xmalloc_expected = 0;
+
+       /* Test __evtchn_close */
+       current = test_alloc_vcpu();
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+
+       test_cond(__evtchn_close(current->domain, -1) == -EINVAL);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       test_cond(__evtchn_close(current->domain, 0) == -EINVAL);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_RESERVED;
+       test_cond(__evtchn_close(current->domain, 0) == -EINVAL);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_PIRQ;
+       evtchn_from_port(current->domain, 0)->u.pirq = 0;
+       _test_pirq_guest_unbind_out = 0;
+       test_cond(__evtchn_close(current->domain, 0) ==  0);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_PIRQ;
+       evtchn_from_port(current->domain, 0)->u.pirq = ~0;
+       _test_pirq_guest_unbind_out = -1;
+       test_cond(__evtchn_close(current->domain, 0) ==  -1);
+       _test_pirq_guest_unbind_out = 0;
+
+       evtchn_from_port(current->domain, 0)->state = ECS_VIRQ;
+       evtchn_from_port(current->domain, 0)->u.virq = 0;
+       current->virq_to_evtchn[0] = 1;
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+       test_cond(current->virq_to_evtchn[0] == 1);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_FREE);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_VIRQ;
+       evtchn_from_port(current->domain, 0)->u.virq = 0;
+       current->virq_to_evtchn[0] = 0;
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+       test_cond(current->virq_to_evtchn[0] == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_FREE);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_IPI;
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_FREE);
+
+       remote_vcpu = test_alloc_vcpu();
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(remote_vcpu->domain) == 0);
+
+       /* bump refcnt to avoid domain_destruct from freeing the memory */
+       atomic_set(&current->domain->refcnt, 10);
+       atomic_set(&remote_vcpu->domain->refcnt, 10);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_INTERDOMAIN;
+
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_dom = 
+               remote_vcpu->domain;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_port = 0;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.interdomain.remote_dom = 
+               current->domain;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.interdomain.remote_port = 0;
+
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_FREE);
+
+       /* Check alternate locking order */
+
+       evtchn_from_port(current->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_dom = 
+                        remote_vcpu->domain;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.interdomain.remote_dom = 
+                        current->domain;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.interdomain.remote_port = 0;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_port = 0;
+       test_cond(__evtchn_close(remote_vcpu->domain, 0) == 0);
+       test_cond(evtchn_from_port(remote_vcpu->domain, 0)->state == ECS_FREE);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_INTERDOMAIN;
+
+       /* Fail  to get_domain() */
+       fake_get_domain_out = 0;
+       test_cond(__evtchn_close(current->domain, 0) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == 
+                       ECS_INTERDOMAIN);
+       fake_get_domain_out = 1;
+
+       /* Clear out the allocated event_ channels */
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(remote_vcpu->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+
+       /* Test evtchn_close */
+       current = test_alloc_vcpu();
+       close_opts = malloc(sizeof(evtchn_close_t));
+       close_opts->port = 0;
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(evtchn_close(close_opts) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->state == ECS_FREE);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+
+       free(close_opts);
+
+       /* Test evtchn_destroy */
+       current = test_alloc_vcpu();
+       fake_xfree_in_ptr = NULL;
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+
+       fake_check_status(__FILE__, __LINE__);
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+       test_cond(fake_xfree_in_ptr != NULL);
+
+       /* Test evtchn_send */
+       current = test_alloc_vcpu();
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       test_cond(evtchn_send(-1) == -EINVAL);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       test_cond(evtchn_send(0) == -EINVAL);
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(evtchn_send(0) == 0);
+       evtchn_from_port(current->domain, 0)->state = ECS_IPI;
+       evtchn_from_port(current->domain, 0)->notify_vcpu_id = 0;
+       test_cond(evtchn_send(0) == 0);
+
+       remote_vcpu = test_alloc_vcpu();
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(remote_vcpu->domain) == 0);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_dom = 
+                       remote_vcpu->domain;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_port = 0;
+
+       evtchn_from_port(remote_vcpu->domain, 0)->notify_vcpu_id = 0;
+       test_cond(evtchn_send(0) == 0);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       evtchn_destroy(remote_vcpu->domain);
+       fake_xmalloc_expected = 0;
+
+       /* Test evtchn_alloc_unbound */
+       current = test_alloc_vcpu();
+       unbound_alloc = malloc(sizeof(evtchn_alloc_unbound_t));
+       unbound_alloc->dom = DOMID_SELF-1;
+
+       fake_IS_PRIV_out = 0;
+       fake_find_domain_out = NULL;
+
+       test_cond(evtchn_alloc_unbound(unbound_alloc) == -EPERM);
+       fake_IS_PRIV_out = 1;
+
+       unbound_alloc->dom = DOMID_SELF;
+       test_cond(evtchn_alloc_unbound(unbound_alloc) == -ESRCH);
+       fake_find_domain_out = current->domain;
+
+       /* Bump the refcnt to avoid put_domain() freeing the domain */
+       atomic_set(&current->domain->refcnt, 10);
+
+       /* Not testing for get_free_port failures here */
+
+       current->domain->domain_id = 1;
+       unbound_alloc->remote_dom = DOMID_SELF;
+       unbound_alloc->dom = DOMID_SELF;
+       unbound_alloc->port = -1;
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_alloc_unbound(unbound_alloc) == 0);
+       test_cond(unbound_alloc->port != -1);
+       
+       test_cond(evtchn_from_port(current->domain, 
+                                  unbound_alloc->port)->state == ECS_UNBOUND);
+       test_cond(evtchn_from_port(current->domain, 
+                                  unbound_alloc->port)->u.unbound.remote_domid 
+                       == current->domain->domain_id);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+       free(unbound_alloc);
+
+       /* Test evtchn_bind_interdomain */
+       current = test_alloc_vcpu();
+       interdomain_bind = malloc(sizeof(evtchn_bind_interdomain_t));
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       test_cond(get_free_port(current->domain) == 1);
+
+       interdomain_bind->remote_dom = DOMID_SELF;
+
+       fake_find_domain_out = NULL;
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == -ESRCH);
+       fake_find_domain_out = current->domain;
+
+       atomic_set(&current->domain->refcnt, 10);
+       /* not testing get_free_port failures here */
+
+       interdomain_bind->remote_port = -1;
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == -EINVAL);
+
+       interdomain_bind->remote_port = 1;
+       evtchn_from_port(current->domain, 1)->state = ECS_RESERVED;
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == -EINVAL);
+
+       remote_vcpu = test_alloc_vcpu();
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(remote_vcpu->domain) == 0);
+       atomic_set(&remote_vcpu->domain->refcnt, 10);
+
+       fake_find_domain_out = remote_vcpu->domain;
+       remote_vcpu->domain->domain_id = 42;
+       interdomain_bind->remote_dom = 42;
+       interdomain_bind->remote_port = 0;
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_UNBOUND;
+       current->domain->domain_id = 1;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.unbound.remote_domid = 0;
+
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == -EINVAL);
+
+       current->domain->domain_id = 1;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.unbound.remote_domid = 1;
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == 0);
+
+       test_cond(evtchn_from_port(remote_vcpu->domain, 0)->state == 
+                       ECS_INTERDOMAIN);
+       test_cond(evtchn_from_port(current->domain, 
+                                  interdomain_bind->local_port)->state == 
+                       ECS_INTERDOMAIN);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(remote_vcpu->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+
+       /* Test the current > remote case */
+       remote_vcpu = test_alloc_vcpu();
+       current = test_alloc_vcpu();
+
+       /* This /should/ be good enough to ensure the correct ordering */
+       if (current < remote_vcpu) {
+               struct vcpu *tmp = remote_vcpu;
+               remote_vcpu = current;
+               current = tmp;
+       }
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(remote_vcpu->domain) == 0);
+
+       atomic_set(&current->domain->refcnt, 10);
+       atomic_set(&remote_vcpu->domain->refcnt, 10);
+
+       current->domain->domain_id = 1;
+       remote_vcpu->domain->domain_id = 2;
+
+       interdomain_bind->remote_dom = 2;
+       interdomain_bind->remote_port = 0;
+       fake_find_domain_out = remote_vcpu->domain;
+
+       evtchn_from_port(remote_vcpu->domain, 0)->state = ECS_UNBOUND;
+       evtchn_from_port(remote_vcpu->domain, 0)->u.unbound.remote_domid = 1;
+       test_cond(evtchn_bind_interdomain(interdomain_bind) == 0);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(remote_vcpu->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+       free(interdomain_bind);
+
+       /* Test evtchn_bind_virq */
+       current = test_alloc_vcpu();
+       virq_bind = malloc(sizeof(evtchn_bind_virq_t));
+
+       virq_bind->virq = ARRAY_SIZE(current->virq_to_evtchn) +1;
+       virq_bind->vcpu = ARRAY_SIZE(current->domain->vcpu) +1;
+       current->domain->vcpu[0] = NULL;
+       current->virq_to_evtchn[0] = 1;
+
+       test_cond(evtchn_bind_virq(virq_bind) == -EINVAL);
+
+       virq_bind->virq = 0;
+       test_cond(evtchn_bind_virq(virq_bind) == -ENOENT);
+       virq_bind->vcpu = 0;
+       test_cond(evtchn_bind_virq(virq_bind) == -ENOENT);
+       current->domain->vcpu[0] = current;
+       test_cond(evtchn_bind_virq(virq_bind) == -EEXIST);
+       current->virq_to_evtchn[0] = 0;
+       /* not testing get_free_port failures here */
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_bind_virq(virq_bind) == 0);
+       fake_check_status(__FILE__, __LINE__);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+       free(virq_bind);
+
+       /* Test evtchn_bind_ipi */
+       current = test_alloc_vcpu();
+       ipi_bind = malloc(sizeof(evtchn_bind_ipi_t));
+
+       ipi_bind->vcpu = ARRAY_SIZE(current->domain->vcpu) +1;
+       current->domain->vcpu[0] = NULL;
+       
+       test_cond(evtchn_bind_ipi(ipi_bind) == -ENOENT);
+       ipi_bind->vcpu = 0;
+       test_cond(evtchn_bind_ipi(ipi_bind) == -ENOENT);
+       current->domain->vcpu[0] = current;
+       /* not testing get_free_port failures here */
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_bind_ipi(ipi_bind) == 0);
+       fake_check_status(__FILE__, __LINE__);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+       free(ipi_bind); 
+
+       /* Test evtchn_bind_pirq */
+       current = test_alloc_vcpu();
+       pirq_bind = malloc(sizeof(evtchn_bind_pirq_t));
+
+       pirq_bind->pirq = ARRAY_SIZE(current->domain->pirq_to_evtchn) +1;
+       current->domain->pirq_to_evtchn[0] = 1;
+
+       test_cond(evtchn_bind_pirq(pirq_bind) == -EINVAL);
+       pirq_bind->pirq = 0;
+       test_cond(evtchn_bind_pirq(pirq_bind) == -EEXIST);
+       current->domain->pirq_to_evtchn[0] = 0;
+       /* not testing get_free_port failures here */
+
+       _test_pirq_guest_bind_out = -1;
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_bind_pirq(pirq_bind) == _test_pirq_guest_bind_out);
+       _test_pirq_guest_bind_out = 0;
+       test_cond(evtchn_bind_pirq(pirq_bind) == 0);
+       fake_check_status(__FILE__, __LINE__);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+
+       free(pirq_bind);
+
+       /* FIXME: Not testing send_guest_pirq */
+
+       /* Testing evtchn_status */
+       current = test_alloc_vcpu();
+       status= malloc(sizeof(evtchn_status_t));
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       atomic_set(&current->domain->refcnt, 10);
+
+       status->dom = 0;
+       status->port = -1;
+       fake_find_domain_out = NULL;
+
+       fake_IS_PRIV_out = 0;
+       test_cond(evtchn_status(status) == -EPERM);
+       fake_IS_PRIV_out = 1;
+       status->dom = DOMID_SELF;
+
+       test_cond(evtchn_status(status) == -ESRCH);
+       fake_find_domain_out = current->domain;
+       test_cond(evtchn_status(status) == -EINVAL);
+
+       status->port = 0;
+       status->status = EVTCHNSTAT_closed+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_closed);
+
+       status->status = EVTCHNSTAT_unbound+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_unbound);
+
+       status->status = EVTCHNSTAT_interdomain+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_INTERDOMAIN;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_dom = 
+                       current->domain;
+       evtchn_from_port(current->domain, 0)->u.interdomain.remote_port = 1;
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_interdomain);
+       test_cond(status->u.interdomain.port == 1);
+
+       status->status = EVTCHNSTAT_pirq+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_PIRQ;
+       evtchn_from_port(current->domain, 0)->u.pirq = 1;
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_pirq);
+       test_cond(status->u.pirq == 1);
+
+       status->status = EVTCHNSTAT_virq+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_VIRQ;
+       evtchn_from_port(current->domain, 0)->u.virq = 10; 
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_virq);
+       test_cond(status->u.pirq == 10);
+
+       status->status = EVTCHNSTAT_ipi+1;
+       evtchn_from_port(current->domain, 0)->state = ECS_IPI;
+       test_cond(evtchn_status(status) == 0);
+       test_cond(status->status == EVTCHNSTAT_ipi);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+
+       free(status);
+
+       /* Test evtchn_bind_vcpu */
+       current = test_alloc_vcpu();
+       vcpu_bind = malloc(sizeof(evtchn_bind_vcpu_t));
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+
+       vcpu_bind->port = -1;
+       vcpu_bind->vcpu=ARRAY_SIZE(current->domain->vcpu) +1;
+       current->domain->vcpu[0] = NULL;
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_from_port(current->domain, 0)->notify_vcpu_id = 10;
+
+       test_cond(evtchn_bind_vcpu(vcpu_bind) == -ENOENT);
+       vcpu_bind->vcpu=0;
+       test_cond(evtchn_bind_vcpu(vcpu_bind) == -ENOENT);
+
+       current->domain->vcpu[0] = current;
+       test_cond(evtchn_bind_vcpu(vcpu_bind) == -EINVAL);
+
+       vcpu_bind->port = 0;
+       test_cond(evtchn_bind_vcpu(vcpu_bind) == -EINVAL);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(evtchn_bind_vcpu(vcpu_bind) == 0);
+       test_cond(evtchn_from_port(current->domain, 0)->notify_vcpu_id == 0);
+
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       evtchn_destroy(current->domain);
+       fake_xmalloc_expected = 0;
+
+       free(vcpu_bind);
+
+       /* Test do_event_channel_op */
+       current = test_alloc_vcpu();
+       uop = test_alloc_evtchn_op(15);
+
+       fake_expect_xmalloc = 1;
+       test_cond(evtchn_init(current->domain) == 0);
+       atomic_set(&current->domain->refcnt, 10);
+
+       _test_acm_pre_event_channel_out = 1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -EACCES);
+       _test_acm_pre_event_channel_out = 0;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ENOSYS);
+
+       /* Setup helper functions to fail to test an overall failure of
+        * do_event_channel_op */
+       fake_IS_PRIV_out = 1;
+       fake_find_domain_out = NULL;
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_alloc_unbound);
+       uop->u.alloc_unbound.dom = DOMID_SELF +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ESRCH);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_interdomain);
+       uop->u.bind_interdomain.remote_dom = DOMID_SELF +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ESRCH);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_virq);
+       uop->u.bind_virq.virq = NR_VIRQS +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -EINVAL);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_ipi);
+       uop->u.bind_ipi.vcpu = MAX_VIRT_CPUS +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ENOENT);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_pirq);
+       uop->u.bind_pirq.pirq = NR_PIRQS +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -EINVAL);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_close);
+       uop->cmd = EVTCHNOP_close;
+       uop->u.close.port = -1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -EINVAL);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_send);
+       uop->u.send.port = -1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -EINVAL);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_status);
+       uop->u.status.dom = DOMID_SELF +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ESRCH);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_vcpu);
+       uop->u.bind_vcpu.vcpu = MAX_VIRT_CPUS +1;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == -ENOENT);
+
+       /* Setup helper functions to succeed to test an overall success of
+        * do_event_channel_op */
+       fake_IS_PRIV_out = 1;
+       fake_find_domain_out = current->domain;
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_alloc_unbound);
+       uop->u.alloc_unbound.remote_dom = DOMID_SELF;
+       uop->u.alloc_unbound.dom = DOMID_SELF;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_interdomain);
+       uop->u.bind_interdomain.remote_dom = DOMID_SELF;
+       uop->u.bind_interdomain.remote_port = 0;
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       evtchn_from_port(current->domain, 0)->u.unbound.remote_domid = 
+               current->domain->domain_id;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_virq);
+       uop->u.bind_virq.virq = 0;
+       uop->u.bind_virq.vcpu = 0;
+       current->virq_to_evtchn[0] = 0;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_ipi);
+       uop->u.bind_ipi.vcpu = 0;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_pirq);
+       uop->u.bind_pirq.pirq = 0;
+       current->domain->pirq_to_evtchn[0] = 0;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_close);
+       uop->u.close.port = 0;
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_send);
+       uop->u.send.port = 0;
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_status);
+       uop->u.status.dom = DOMID_SELF;
+       uop->u.status.port = 0;
+       evtchn_from_port(current->domain, 0)->state = ECS_FREE;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       uop = test_alloc_evtchn_op(EVTCHNOP_bind_vcpu);
+       uop->u.bind_vcpu.vcpu = 0;
+       uop->u.bind_vcpu.port = 0;
+       evtchn_from_port(current->domain, 0)->state = ECS_UNBOUND;
+       test_cond(do_event_channel_op(fake_from_user(uop)) == 0);
+
+       free(uop);
+
+       for(i=0; i<NR_EVTCHN_BUCKETS; i++) {
+               xfree(current->domain->evtchn[i]);
+       }
+       fake_xmalloc_expected = 0;
+
+       fake_check_status(__FILE__, __LINE__);
+       return 0;
+}

-- 
 ccontrol: http://freshmeat.net/projects/ccontrol

----- End forwarded message -----

Yours Tony

   linux.conf.au       http://linux.conf.au/ || http://lca2006.linux.org.au/
   Jan 23-28 2006      The Australian Linux Technical Conference!


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>