[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1 1/2] libxl: add PV display device driver interface
From: Oleksandr Grytsov <oleksandr_grytsov@xxxxxxxx> Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@xxxxxxxx> --- tools/libxl/Makefile | 2 +- tools/libxl/libxl.h | 21 ++++ tools/libxl/libxl_create.c | 3 + tools/libxl/libxl_device.c | 206 ++++++++++++++++++++++++++++++++++ tools/libxl/libxl_internal.h | 24 ++++ tools/libxl/libxl_types.idl | 22 +++- tools/libxl/libxl_types_internal.idl | 1 + tools/libxl/libxl_usb.c | 2 + tools/libxl/libxl_utils.h | 4 + tools/libxl/libxl_vdispl.c | 209 +++++++++++++++++++++++++++++++++++ 10 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 tools/libxl/libxl_vdispl.c diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index 566b706..3a932e1 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -138,7 +138,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \ libxl_dom_suspend.o libxl_dom_save.o libxl_usb.o \ libxl_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \ libxl_cpupool.o libxl_mem.o libxl_sched.o libxl_tmem.o \ - libxl_domain.o \ + libxl_domain.o libxl_vdispl.o \ $(LIBXL_OBJS-y) LIBXL_OBJS += libxl_genid.o LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 72ec39d..4eff121 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1833,6 +1833,27 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm *vtpm, libxl_vtpminfo *vtpminfo); +/* Virtual displays */ +int libxl_device_vdispl_add(libxl_ctx *ctx, uint32_t domid, + libxl_device_vdispl *displ, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_device_vdispl_remove(libxl_ctx *ctx, uint32_t domid, + libxl_device_vdispl *vdispl, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_device_vdispl_destroy(libxl_ctx *ctx, uint32_t domid, + libxl_device_vdispl *vdispl, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; + +libxl_device_vdispl *libxl_device_vdispl_list(libxl_ctx *ctx, uint32_t domid, + int *num); +void libxl_device_vdispl_list_free(libxl_device_vdispl* list, int num); +int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_vdispl *vdispl, + libxl_vdisplinfo *vdisplinfo); + /* Keyboard */ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb, const libxl_asyncop_how *ao_how) diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 25389e1..b36383f 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -1422,6 +1422,8 @@ out: #define libxl_device_dtdev_list NULL #define libxl_device_dtdev_compare NULL +#define libxl__device_from_dtdev NULL +#define libxl__device_dtdev_setdefault NULL static DEFINE_DEVICE_TYPE_STRUCT(dtdev); const struct libxl_device_type *device_type_tbl[] = { @@ -1432,6 +1434,7 @@ const struct libxl_device_type *device_type_tbl[] = { &libxl__usbdev_devtype, &libxl__pcidev_devtype, &libxl__dtdev_devtype, + &libxl__vdispl_devtype, NULL }; diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 5e96676..def1859 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -1776,6 +1776,212 @@ out: return AO_CREATE_FAIL(rc); } +static int device_add_domain_config(libxl__gc *gc, uint32_t domid, + const struct libxl_device_type *dt, + void *type) +{ + int rc; + libxl_domain_config d_config; + libxl__domain_userdata_lock *lock = NULL; + int *num_dev; + int i; + void *item = NULL; + + libxl_domain_config_init(&d_config); + + lock = libxl__lock_domain_userdata(gc, domid); + if (!lock) { + rc = ERROR_LOCK_FAIL; goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + + num_dev = libxl__device_type_get_num(dt, &d_config); + + /* Check for existing device */ + for (i = 0; i < *num_dev; i++) { + if (dt->compare(libxl__device_type_get_elem(dt, &d_config, i), type)) { + item = libxl__device_type_get_elem(dt, &d_config, i); + } + } + + if (!item) { + void **devs= libxl__device_type_get_ptr(dt, &d_config); + *devs = libxl__realloc(NOGC, *devs, + dt->dev_elem_size * (*num_dev + 1)); + item = libxl__device_type_get_elem(dt, &d_config, *num_dev); + (*num_dev)++; + } else { + dt->dispose(item); + } + + dt->init(item); + dt->copy(CTX, item, type); + + rc = libxl__dm_check_start(gc, &d_config, domid); + if (rc) goto out; + + rc = libxl__set_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + + rc = 0; + +out: + if (lock) libxl__unlock_domain_userdata(lock); + libxl_domain_config_dispose(&d_config); + return rc; +} + +static int device_add_xen_store(libxl__gc *gc, libxl__device *device, + char **bents, char **fents, char **ro_fents) +{ + xs_transaction_t t = XBT_NULL; + int rc; + + for (;;) { + rc = libxl__xs_transaction_start(gc, &t); + if (rc) goto out; + + libxl__device_generic_add(gc, t, device, bents, fents, ro_fents); + + rc = libxl__xs_transaction_commit(gc, &t); + if (!rc) break; + if (rc < 0) goto out; + } + + rc = 0; + +out: + libxl__xs_transaction_abort(gc, &t); + return rc; +} + +void libxl__device_add(libxl__egc *egc, uint32_t domid, + const struct libxl_device_type *dt, void *type, + libxl__ao_device *aodev) +{ + STATE_AO_GC(aodev->ao); + libxl__device *device; + int rc; + flexarray_t *front = NULL; + flexarray_t *back = NULL; + + rc = dt->set_default(gc, domid, type); + if (rc) goto out; + + GCNEW(device); + rc = dt->to_device(gc, domid, type, device); + if ( rc != 0 ) goto out; + + rc = libxl__device_exists(gc, XBT_NULL, device); + if (rc < 0) goto out; + if (rc == 1) { /* already exists in xenstore */ + LOGD(ERROR, domid, "device already exists in xenstore"); + aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */ + rc = ERROR_DEVICE_EXISTS; + goto out; + } + + if (aodev->update_json) { + rc = device_add_domain_config(gc, domid, dt, type); + if (rc) goto out; + } + + if (dt->set_xenstore_config) { + dt->set_xenstore_config(gc, domid, type, &front, &back); + rc = device_add_xen_store(gc, device, + libxl__xs_kvs_of_flexarray(gc, back), + libxl__xs_kvs_of_flexarray(gc, front), + NULL); + if (rc) goto out; + } + + aodev->dev = device; + aodev->action = LIBXL__DEVICE_ACTION_ADD; + libxl__wait_device_connection(egc, aodev); + + rc = 0; + +out: + aodev->rc = rc; + if(rc) aodev->callback(egc, aodev); + return; +} + +void* libxl__device_list(const struct libxl_device_type *dt, + libxl_ctx *ctx, uint32_t domid, int *num) +{ + GC_INIT(ctx); + + void *r = NULL; + void *list = NULL; + void *item = NULL; + char *libxl_path; + char *be_path; + char** dir = NULL; + unsigned int ndirs = 0; + int rc; + + *num = 0; + + libxl_path = GCSPRINTF("%s/device/%s", + libxl__xs_libxl_path(gc, domid), dt->type); + + dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs); + + if (dir && ndirs) { + list = malloc(dt->dev_elem_size * ndirs); + void *end = (uint8_t*)list + ndirs * dt->dev_elem_size; + item = list; + + while(item < end) { + be_path = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/%s/backend", + libxl_path, *dir)); + + dt->init(item); + + rc = dt->from_xenstore(gc, be_path, atoi(*dir), item); + if (rc) goto out; + + item = (uint8_t*)item + dt->dev_elem_size; + ++dir; + } + } + + *num = ndirs; + r = list; + list = NULL; + +out: + + if (list) { + *num = 0; + while(item >= list) { + item = (uint8_t*)item - dt->dev_elem_size; + dt->dispose(item); + } + free(list); + } + + GC_FREE; + + return r; +} + +void libxl__device_list_free(const struct libxl_device_type *dt, + void *list, int num) +{ + int i; + + for (i = 0; i < num; i++) { + dt->dispose((uint8_t*)list + i * dt->dev_elem_size); + } + + free(list); +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 25cb08a..c07e280 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -3473,11 +3473,18 @@ struct libxl_device_type { void (*add)(libxl__egc *, libxl__ao *, uint32_t, libxl_domain_config *, libxl__multidev *); void *(*list)(libxl_ctx *, uint32_t, int *); + int (*set_default)(libxl__gc *, uint32_t, void *); + int (*to_device)(libxl__gc *, uint32_t, void *, libxl__device *); + void (*init)(void *); + void (*copy)(libxl_ctx *, void *, void *); void (*dispose)(void *); int (*compare)(void *, void *); void (*merge)(libxl_ctx *, void *, void *); int (*dm_needed)(void *, unsigned); void (*update_config)(libxl__gc *, void *, void *); + int (*from_xenstore)(libxl__gc *, const char *, uint32_t, void *); + void (*set_xenstore_config)(libxl__gc *, uint32_t, void *, + flexarray_t **, flexarray_t **); }; #define DEFINE_DEVICE_TYPE_STRUCT_X(name, sname, ...) \ @@ -3489,6 +3496,14 @@ struct libxl_device_type { .add = libxl__add_ ## name ## s, \ .list = (void *(*)(libxl_ctx *, uint32_t, int *)) \ libxl_device_ ## sname ## _list, \ + .set_default = (int (*)(libxl__gc *, uint32_t, void *)) \ + libxl__device_ ## sname ## _setdefault, \ + .to_device = (int (*)(libxl__gc *, uint32_t, \ + void *, libxl__device *)) \ + libxl__device_from_ ## name, \ + .init = (void (*)(void *))libxl_device_ ## sname ## _init, \ + .copy = (void (*)(libxl_ctx *, void *, void *)) \ + libxl_device_ ## sname ## _copy, \ .dispose = (void (*)(void *))libxl_device_ ## sname ## _dispose, \ .compare = (int (*)(void *, void *)) \ libxl_device_ ## sname ## _compare, \ @@ -3523,6 +3538,7 @@ extern const struct libxl_device_type libxl__vtpm_devtype; extern const struct libxl_device_type libxl__usbctrl_devtype; extern const struct libxl_device_type libxl__usbdev_devtype; extern const struct libxl_device_type libxl__pcidev_devtype; +extern const struct libxl_device_type libxl__vdispl_devtype; extern const struct libxl_device_type *device_type_tbl[]; @@ -4339,6 +4355,14 @@ static inline bool libxl__acpi_defbool_val(const libxl_domain_build_info *b_info return libxl_defbool_val(b_info->acpi) && libxl_defbool_val(b_info->u.hvm.acpi); } + +void libxl__device_add(libxl__egc *egc, uint32_t domid, + const struct libxl_device_type *dt, void *type, + libxl__ao_device *aodev); +void* libxl__device_list(const struct libxl_device_type *dt, + libxl_ctx *ctx, uint32_t domid, int *num); +void libxl__device_list_free(const struct libxl_device_type *dt, + void *list, int num); #endif /* diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 2475a4d..a4ff837 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -738,7 +738,14 @@ libxl_device_vtpm = Struct("device_vtpm", [ ("backend_domname", string), ("devid", libxl_devid), ("uuid", libxl_uuid), -]) + ]) + +libxl_device_vdispl = Struct("device_vdispl", [ + ("backend_domid", libxl_domid), + ("backend_domname", string), + ("devid", libxl_devid), + ("be_alloc", bool), + ]) libxl_device_channel = Struct("device_channel", [ ("backend_domid", libxl_domid), @@ -750,7 +757,7 @@ libxl_device_channel = Struct("device_channel", [ ("pty", None), ("socket", Struct(None, [("path", string)])), ])), -]) + ]) libxl_domain_config = Struct("domain_config", [ ("c_info", libxl_domain_create_info), @@ -764,6 +771,7 @@ libxl_domain_config = Struct("domain_config", [ ("vfbs", Array(libxl_device_vfb, "num_vfbs")), ("vkbs", Array(libxl_device_vkb, "num_vkbs")), ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), + ("vdispls", Array(libxl_device_vdispl, "num_vdispls")), # a channel manifests as a console with a name, # see docs/misc/channels.txt ("channels", Array(libxl_device_channel, "num_channels")), @@ -860,6 +868,16 @@ libxl_physinfo = Struct("physinfo", [ ("cap_hvm_directio", bool), ], dir=DIR_OUT) +libxl_vdisplinfo = Struct("vdisplinfo", [ + ("backend", string), + ("backend_id", uint32), + ("frontend", string), + ("frontend_id", uint32), + ("devid", libxl_devid), + ("state", integer), + ("be_alloc", bool), + ], dir=DIR_OUT) + # NUMA node characteristics: size and free are how much memory it has, and how # much of it is free, respectively. dists is an array of distances from this # node to each other node. diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl index 82e5c07..cdef4d3 100644 --- a/tools/libxl/libxl_types_internal.idl +++ b/tools/libxl/libxl_types_internal.idl @@ -25,6 +25,7 @@ libxl__device_kind = Enumeration("device_kind", [ (8, "VTPM"), (9, "VUSB"), (10, "QUSB"), + (11, "VDISPL") ]) libxl__console_backend = Enumeration("console_backend", [ diff --git a/tools/libxl/libxl_usb.c b/tools/libxl/libxl_usb.c index d8948d5..d1ec28f 100644 --- a/tools/libxl/libxl_usb.c +++ b/tools/libxl/libxl_usb.c @@ -1968,6 +1968,8 @@ void libxl_device_usbdev_list_free(libxl_device_usbdev *list, int nr) DEFINE_DEVICE_TYPE_STRUCT(usbctrl, .dm_needed = libxl_device_usbctrl_dm_needed ); + +#define libxl__device_from_usbdev NULL DEFINE_DEVICE_TYPE_STRUCT(usbdev); /* diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h index 25773d8..9e743dc 100644 --- a/tools/libxl/libxl_utils.h +++ b/tools/libxl/libxl_utils.h @@ -78,6 +78,10 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid, int devid, libxl_device_vtpm *vtpm); int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid, int devid, libxl_device_usbctrl *usbctrl); + +int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vdispl *vdispl); + int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx, uint32_t domid, int ctrl, int port, libxl_device_usbdev *usbdev); diff --git a/tools/libxl/libxl_vdispl.c b/tools/libxl/libxl_vdispl.c new file mode 100644 index 0000000..85b20db --- /dev/null +++ b/tools/libxl/libxl_vdispl.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2016 EPAM Systems Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * 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 Lesser General Public License for more details. + */ + +#include "libxl_osdeps.h" + +#include "libxl_internal.h" + +static int libxl__device_vdispl_setdefault(libxl__gc *gc, uint32_t domid, + libxl_device_vdispl *vdispl) +{ + int rc; + + rc = libxl__resolve_domid(gc, vdispl->backend_domname, + &vdispl->backend_domid); + + if (vdispl->devid == -1) { + vdispl->devid = libxl__device_nextid(gc, domid, "vdispl"); + } + + return rc; +} + +static int libxl__from_xenstore_vdispl(libxl__gc *gc, const char *be_path, + uint32_t devid, + libxl_device_vdispl *vdispl) +{ + vdispl->devid = devid; + + return libxl__backendpath_parse_domid(gc, be_path, &vdispl->backend_domid); +} + +static int libxl__device_from_vdispl(libxl__gc *gc, uint32_t domid, + libxl_device_vdispl *vdispl, + libxl__device *device) +{ + device->backend_devid = vdispl->devid; + device->backend_domid = vdispl->backend_domid; + device->backend_kind = LIBXL__DEVICE_KIND_VDISPL; + device->devid = vdispl->devid; + device->domid = domid; + device->kind = LIBXL__DEVICE_KIND_VDISPL; + + return 0; +} + +static void libxl__set_xenstore_vdispl(libxl__gc *gc, uint32_t domid, + libxl_device_vdispl *vdispl, + flexarray_t **front, flexarray_t **back) +{ + *front = flexarray_make(gc, 16, 1); + *back = flexarray_make(gc, 16, 1); + + flexarray_append(*back, "frontend-id"); + flexarray_append(*back, GCSPRINTF("%d", domid)); + flexarray_append(*back, "online"); + flexarray_append(*back, "1"); + flexarray_append(*back, "state"); + flexarray_append(*back, GCSPRINTF("%d", XenbusStateInitialising)); + flexarray_append(*back, "handle"); + flexarray_append(*back, GCSPRINTF("%d", vdispl->devid)); + + flexarray_append(*front, "backend-id"); + flexarray_append(*front, GCSPRINTF("%d", vdispl->backend_domid)); + flexarray_append(*front, "state"); + flexarray_append(*front, GCSPRINTF("%d", XenbusStateInitialising)); + flexarray_append(*front, "handle"); + flexarray_append(*front, GCSPRINTF("%d", vdispl->devid)); + flexarray_append(*front, "be_alloc"); + flexarray_append(*front, GCSPRINTF("%d", vdispl->be_alloc)); +} + +static void libxl__update_config_vdispl(libxl__gc *gc, + libxl_device_vdispl *dst, + libxl_device_vdispl *src) +{ + dst->devid = src->devid; + dst->be_alloc = src->be_alloc; +} + +static int libxl_device_vdispl_compare(libxl_device_vdispl *d1, + libxl_device_vdispl *d2) +{ + return COMPARE_DEVID(d1, d2); +} + +static void libxl__device_vdispl_add(libxl__egc *egc, uint32_t domid, + libxl_device_vdispl *vdispl, + libxl__ao_device *aodev) +{ + libxl__device_add(egc, domid, &libxl__vdispl_devtype, vdispl, aodev); +} + +libxl_device_vdispl *libxl_device_vdispl_list(libxl_ctx *ctx, uint32_t domid, + int *num) +{ + return libxl__device_list(&libxl__vdispl_devtype, ctx, domid, num); +} + +void libxl_device_vdispl_list_free(libxl_device_vdispl* list, int num) +{ + libxl__device_list_free(&libxl__vdispl_devtype, list, num); +} + +int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_vdispl *vdispl, + libxl_vdisplinfo *info) +{ + GC_INIT(ctx); + char *libxl_path, *dompath, *devpath; + char *val; + int rc; + + libxl_vdisplinfo_init(info); + dompath = libxl__xs_get_dompath(gc, domid); + info->devid = vdispl->devid; + + devpath = GCSPRINTF("%s/device/vdispl/%d", dompath, info->devid); + libxl_path = GCSPRINTF("%s/device/vdispl/%d", + libxl__xs_libxl_path(gc, domid), + info->devid); + info->backend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/backend", libxl_path), + NULL); + if (!info->backend) { rc = ERROR_FAIL; goto out; } + + rc = libxl__backendpath_parse_domid(gc, info->backend, &info->backend_id); + if (rc) { goto out; } + + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", devpath)); + info->state = val ? strtoul(val, NULL, 10) : -1; + + info->frontend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/frontend", libxl_path), + NULL); + info->frontend_id = domid; + + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/be_alloc", libxl_path)); + info->be_alloc = val ? strtoul(val, NULL, 10) : 0; + + rc = 0; + +out: + GC_FREE; + return rc; +} + +int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vdispl *vdispl) +{ + libxl_device_vdispl *vdispls = NULL; + int n, i; + int rc; + + libxl_device_vdispl_init(vdispl); + + vdispls = libxl_device_vdispl_list(ctx, domid, &n); + + if (!vdispls) { rc = ERROR_NOTFOUND; goto out; } + + for (i = 0; i < n; ++i) { + if (devid == vdispls[i].devid) { + libxl_device_vdispl_copy(ctx, vdispl, &vdispls[i]); + rc = 0; + goto out; + } + } + + rc = ERROR_NOTFOUND; + +out: + + if (vdispls) { + libxl_device_vdispl_list_free(vdispls, n); + } + return rc; +} + +LIBXL_DEFINE_DEVICE_ADD(vdispl) +static LIBXL_DEFINE_DEVICES_ADD(vdispl) +LIBXL_DEFINE_DEVICE_REMOVE(vdispl) + +DEFINE_DEVICE_TYPE_STRUCT(vdispl, + .update_config = (void (*)(libxl__gc *, void *, void *)) + libxl__update_config_vdispl, + .from_xenstore = (int (*)(libxl__gc *, const char *, uint32_t, void *)) + libxl__from_xenstore_vdispl, + .set_xenstore_config = (void (*)(libxl__gc *, uint32_t, void *, + flexarray_t **, flexarray_t **)) + libxl__set_xenstore_vdispl +); + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |