[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [IA64] SetVirtualAddressMap emulation support
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID 9de9ad0685bf8b4f0ba6d3997cfcb362f98a6afd # Parent e2fba672928171f3718f45d3487887257b195ee5 [IA64] SetVirtualAddressMap emulation support Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx> --- linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S | 2 xen/arch/ia64/xen/Makefile | 1 xen/arch/ia64/xen/dom_fw.c | 9 - xen/arch/ia64/xen/efi_emul.c | 180 +++++++++++++++++++++++++ xen/arch/ia64/xen/hypercall.c | 61 ++------ xen/arch/ia64/xen/process.c | 12 - xen/include/asm-ia64/dom_fw.h | 14 + xen/include/asm-ia64/domain.h | 2 8 files changed, 224 insertions(+), 57 deletions(-) diff -r e2fba6729281 -r 9de9ad0685bf linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Tue May 09 16:56:45 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypercall.S Wed May 10 15:29:48 2006 -0600 @@ -345,7 +345,7 @@ GLOBAL_ENTRY(xen_send_ipi) GLOBAL_ENTRY(xen_send_ipi) mov r14=r32 mov r15=r33 - mov r2=0x380 + mov r2=0x400 break 0x1000 ;; br.ret.sptk.many rp diff -r e2fba6729281 -r 9de9ad0685bf xen/arch/ia64/xen/Makefile --- a/xen/arch/ia64/xen/Makefile Tue May 09 16:56:45 2006 -0600 +++ b/xen/arch/ia64/xen/Makefile Wed May 10 15:29:48 2006 -0600 @@ -2,6 +2,7 @@ obj-y += dom0_ops.o obj-y += dom0_ops.o obj-y += domain.o obj-y += dom_fw.o +obj-y += efi_emul.o obj-y += hpsimserial.o obj-y += hypercall.o obj-y += hyperprivop.o diff -r e2fba6729281 -r 9de9ad0685bf xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Tue May 09 16:56:45 2006 -0600 +++ b/xen/arch/ia64/xen/dom_fw.c Wed May 10 15:29:48 2006 -0600 @@ -798,6 +798,9 @@ dom_fw_init (struct domain *d, const cha pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn); cmd_line = (void *) cp; + /* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */ + d->arch.efi_runtime = efi_runtime; + if (args) { if (arglen >= 1024) arglen = 1023; @@ -959,7 +962,7 @@ dom_fw_init (struct domain *d, const cha MAKE_MD(EFI_LOADER_DATA,EFI_MEMORY_WB,0*MB,1*MB, 0);//XXX #endif /* hypercall patches live here, masquerade as reserved PAL memory */ - MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB,HYPERCALL_START,HYPERCALL_END, 0); + MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 0); MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,HYPERCALL_END,maxmem-IA64_GRANULE_SIZE, 0);//XXX make sure this doesn't overlap on i/o, runtime area. #ifndef CONFIG_XEN_IA64_DOM0_VP /* hack */ MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,last_start,last_end,1); @@ -993,7 +996,7 @@ dom_fw_init (struct domain *d, const cha MAKE_MD(EFI_LOADER_DATA,EFI_MEMORY_WB,0*MB,1*MB, 1); #endif /* hypercall patches live here, masquerade as reserved PAL memory */ - MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB,HYPERCALL_START,HYPERCALL_END, 1); + MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 1); MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,HYPERCALL_END,maxmem, 1); /* Create a dummy entry for IO ports, so that IO accesses are trapped by Xen. */ @@ -1009,7 +1012,7 @@ dom_fw_init (struct domain *d, const cha BUG_ON(i > NUM_MEM_DESCS); bp->efi_memmap_size = i * sizeof(efi_memory_desc_t); bp->efi_memdesc_size = sizeof(efi_memory_desc_t); - bp->efi_memdesc_version = 1; + bp->efi_memdesc_version = EFI_MEMDESC_VERSION; bp->command_line = dom_pa((unsigned long) cmd_line); bp->console_info.num_cols = 80; bp->console_info.num_rows = 25; diff -r e2fba6729281 -r 9de9ad0685bf xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Tue May 09 16:56:45 2006 -0600 +++ b/xen/arch/ia64/xen/hypercall.c Wed May 10 15:29:48 2006 -0600 @@ -26,7 +26,6 @@ #include <public/physdev.h> #include <xen/domain.h> -extern unsigned long translate_domain_mpaddr(unsigned long); static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop); static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); /* FIXME: where these declarations should be there ? */ @@ -103,7 +102,7 @@ uint32_t nr_hypercalls = uint32_t nr_hypercalls = sizeof(ia64_hypercall_table) / sizeof(hypercall_t); -static int +static IA64FAULT xen_hypercall (struct pt_regs *regs) { uint32_t cmd = (uint32_t)regs->r2; @@ -119,7 +118,7 @@ xen_hypercall (struct pt_regs *regs) else regs->r8 = -ENOSYS; - return 1; + return IA64_NO_FAULT; } @@ -182,14 +181,16 @@ fw_hypercall_ipi (struct pt_regs *regs) return; } -static int +static IA64FAULT fw_hypercall (struct pt_regs *regs) { struct vcpu *v = current; struct sal_ret_values x; - unsigned long *tv, *tc; - - switch (regs->r2) { + efi_status_t efi_ret_value; + IA64FAULT fault; + unsigned long index = regs->r2 & FW_HYPERCALL_NUM_MASK_HIGH; + + switch (index) { case FW_HYPERCALL_PAL_CALL: //printf("*** PAL hypercall: index=%d\n",regs->r28); //FIXME: This should call a C routine @@ -247,40 +248,10 @@ fw_hypercall (struct pt_regs *regs) regs->r8 = x.r8; regs->r9 = x.r9; regs->r10 = x.r10; regs->r11 = x.r11; break; - case FW_HYPERCALL_EFI_RESET_SYSTEM: - printf("efi.reset_system called "); - if (current->domain == dom0) { - printf("(by dom0)\n "); - (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL); - } - else - domain_shutdown (current->domain, SHUTDOWN_reboot); - regs->r8 = EFI_UNSUPPORTED; - break; - case FW_HYPERCALL_EFI_GET_TIME: - tv = (unsigned long *) vcpu_get_gr(v,32); - tc = (unsigned long *) vcpu_get_gr(v,33); - //printf("efi_get_time(%p,%p) called...",tv,tc); - tv = (unsigned long *) __va(translate_domain_mpaddr((unsigned long) tv)); - if (tc) tc = (unsigned long *) __va(translate_domain_mpaddr((unsigned long) tc)); - regs->r8 = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc); - //printf("and returns %lx\n",regs->r8); - break; - case FW_HYPERCALL_EFI_SET_TIME: - case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: - case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: - // FIXME: WARNING!! IF THIS EVER GETS IMPLEMENTED - // SOME OF THE OTHER EFI EMULATIONS WILL CHANGE AS - // POINTER ARGUMENTS WILL BE VIRTUAL!! - case FW_HYPERCALL_EFI_GET_VARIABLE: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: - case FW_HYPERCALL_EFI_SET_VARIABLE: - case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: - // FIXME: need fixes in efi.h from 2.6.9 - regs->r8 = EFI_UNSUPPORTED; + case FW_HYPERCALL_EFI_CALL: + efi_ret_value = efi_emulator (regs, &fault); + if (fault != IA64_NO_FAULT) return fault; + regs->r8 = efi_ret_value; break; case FW_HYPERCALL_IPI: fw_hypercall_ipi (regs); @@ -289,7 +260,7 @@ fw_hypercall (struct pt_regs *regs) printf("unknown ia64 fw hypercall %lx\n", regs->r2); regs->r8 = do_ni_hypercall(); } - return 1; + return IA64_NO_FAULT; } /* opt_unsafe_hypercall: If true, unsafe debugging hypercalls are allowed. @@ -297,7 +268,7 @@ static int opt_unsafe_hypercall = 0; static int opt_unsafe_hypercall = 0; boolean_param("unsafe_hypercall", opt_unsafe_hypercall); -int +IA64FAULT ia64_hypercall (struct pt_regs *regs) { struct vcpu *v = current; @@ -327,7 +298,7 @@ ia64_hypercall (struct pt_regs *regs) printf("unknown user xen/ia64 hypercall %lx\n", index); regs->r8 = do_ni_hypercall(); } - return 1; + return IA64_NO_FAULT; } /* Hypercalls are only allowed by kernel. @@ -336,7 +307,7 @@ ia64_hypercall (struct pt_regs *regs) /* FIXME: Return a better error value ? Reflection ? Illegal operation ? */ regs->r8 = -1; - return 1; + return IA64_NO_FAULT; } if (index >= FW_HYPERCALL_FIRST_ARCH) diff -r e2fba6729281 -r 9de9ad0685bf xen/arch/ia64/xen/process.c --- a/xen/arch/ia64/xen/process.c Tue May 09 16:56:45 2006 -0600 +++ b/xen/arch/ia64/xen/process.c Wed May 10 15:29:48 2006 -0600 @@ -15,7 +15,6 @@ #include <asm/ptrace.h> #include <xen/delay.h> -#include <linux/efi.h> /* FOR EFI_UNIMPLEMENTED */ #include <asm/sal.h> /* FOR struct ia64_sal_retval */ #include <asm/system.h> @@ -40,7 +39,7 @@ extern void panic_domain(struct pt_regs extern void panic_domain(struct pt_regs *, const char *, ...); extern long platform_is_hp_ski(void); extern int ia64_hyperprivop(unsigned long, REGS *); -extern int ia64_hypercall(struct pt_regs *regs); +extern IA64FAULT ia64_hypercall(struct pt_regs *regs); extern void vmx_do_launch(struct vcpu *); extern unsigned long lookup_domain_mpa(struct domain *,unsigned long); @@ -680,6 +679,7 @@ ia64_handle_break (unsigned long ifa, st { struct domain *d = current->domain; struct vcpu *v = current; + IA64FAULT vector; if (first_break) { if (platform_is_hp_ski()) running_on_sim = 1; @@ -700,9 +700,11 @@ ia64_handle_break (unsigned long ifa, st /* by default, do not continue */ v->arch.hypercall_continuation = 0; - if (ia64_hypercall(regs) && - !PSCBX(v, hypercall_continuation)) - vcpu_increment_iip(current); + if ((vector = ia64_hypercall(regs)) == IA64_NO_FAULT) { + if (!PSCBX(v, hypercall_continuation)) + vcpu_increment_iip(current); + } + else reflect_interruption(isr, regs, vector); } else if (!PSCB(v,interrupt_collection_enabled)) { if (ia64_hyperprivop(iim,regs)) diff -r e2fba6729281 -r 9de9ad0685bf xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Tue May 09 16:56:45 2006 -0600 +++ b/xen/include/asm-ia64/dom_fw.h Wed May 10 15:29:48 2006 -0600 @@ -5,7 +5,7 @@ * Dan Magenheimer (dan.magenheimer@xxxxxx) */ -extern unsigned long dom_fw_setup(struct domain *, const char *, int); +#include <linux/efi.h> #ifndef MB #define MB (1024*1024) @@ -55,7 +55,7 @@ extern unsigned long dom_fw_setup(struct #define FW_HYPERCALL_SAL_CALL_INDEX 0x82UL #define FW_HYPERCALL_SAL_CALL_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_SAL_CALL_INDEX) -#define FW_HYPERCALL_SAL_CALL 0x1001UL +#define FW_HYPERCALL_SAL_CALL 0x1100UL /* * EFI is accessed via the EFI system table, which contains: @@ -94,6 +94,7 @@ extern unsigned long dom_fw_setup(struct #define FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX 9UL /* these are hypercall numbers */ +#define FW_HYPERCALL_EFI_CALL 0x300UL #define FW_HYPERCALL_EFI_GET_TIME 0x300UL #define FW_HYPERCALL_EFI_SET_TIME 0x301UL #define FW_HYPERCALL_EFI_GET_WAKEUP_TIME 0x302UL @@ -125,7 +126,7 @@ extern unsigned long dom_fw_setup(struct */ #define FW_HYPERCALL_FIRST_ARCH 0x300UL -#define FW_HYPERCALL_IPI 0x380UL +#define FW_HYPERCALL_IPI 0x400UL /* Xen/ia64 user hypercalls. Only used for debugging. */ #define FW_HYPERCALL_FIRST_USER 0xff00UL @@ -133,9 +134,16 @@ extern unsigned long dom_fw_setup(struct /* Interrupt vector used for os boot rendez vous. */ #define XEN_SAL_BOOT_RENDEZ_VEC 0xF3 +#define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL +#define FW_HYPERCALL_NUM_MASK_LOW 0xffUL + +#define EFI_MEMDESC_VERSION 1 + extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64); extern struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7); extern struct ia64_pal_retval pal_emulator_static (unsigned long); +extern unsigned long dom_fw_setup (struct domain *, const char *, int); +extern efi_status_t efi_emulator (struct pt_regs *regs, unsigned long *fault); extern void build_pal_hypercall_bundles(unsigned long *imva, unsigned long brkimm, unsigned long hypnum); extern void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, UINT64 ret); diff -r e2fba6729281 -r 9de9ad0685bf xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Tue May 09 16:56:45 2006 -0600 +++ b/xen/include/asm-ia64/domain.h Wed May 10 15:29:48 2006 -0600 @@ -54,6 +54,8 @@ struct arch_domain { unsigned long initrd_start; unsigned long initrd_len; char *cmdline; + int efi_virt_mode; /* phys : 0 , virt : 1 */ + void *efi_runtime; }; #define xen_vastart arch.xen_vastart #define xen_vaend arch.xen_vaend diff -r e2fba6729281 -r 9de9ad0685bf xen/arch/ia64/xen/efi_emul.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/ia64/xen/efi_emul.c Wed May 10 15:29:48 2006 -0600 @@ -0,0 +1,180 @@ +/* + * efi_emul.c: + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include <xen/config.h> +#include <xen/compile.h> +#include <asm/pgalloc.h> +#include <asm/vcpu.h> +#include <asm/dom_fw.h> +#include <public/sched.h> + +extern unsigned long translate_domain_mpaddr(unsigned long); +extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr); + +// given a current domain (virtual or metaphysical) address, return the virtual address +static unsigned long +efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault) +{ + struct vcpu *v = current; + unsigned long mpaddr = domain_addr; + *fault = IA64_NO_FAULT; + + if (v->domain->arch.efi_virt_mode) { + *fault = vcpu_tpa(v, domain_addr, &mpaddr); + if (*fault != IA64_NO_FAULT) return 0; + } + + return ((unsigned long) __va(translate_domain_mpaddr(mpaddr))); +} + +static efi_status_t +efi_emulate_get_time( + unsigned long tv_addr, unsigned long tc_addr, + IA64FAULT *fault) +{ + unsigned long tv = 0, tc = 0; + efi_status_t status; + + //printf("efi_get_time(%016lx,%016lx) called\n", tv_addr, tc_addr); + tv = efi_translate_domain_addr(tv_addr, fault); + if (*fault != IA64_NO_FAULT) return 0; + if (tc_addr) { + tc = efi_translate_domain_addr(tc_addr, fault); + if (*fault != IA64_NO_FAULT) return 0; + } + //printf("efi_get_time(%016lx,%016lx) translated to xen virtual address\n", tv, tc); + status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc); + //printf("efi_get_time returns %lx\n", status); + return status; +} + +static efi_status_t +efi_emulate_set_virtual_address_map( + unsigned long memory_map_size, unsigned long descriptor_size, + u32 descriptor_version, efi_memory_desc_t *virtual_map) +{ + void *efi_map_start, *efi_map_end, *p; + efi_memory_desc_t entry, *md = &entry; + u64 efi_desc_size; + + unsigned long *vfn; + struct domain *d = current->domain; + efi_runtime_services_t *efi_runtime = d->arch.efi_runtime; + + if (descriptor_version != EFI_MEMDESC_VERSION) { + printf ("efi_emulate_set_virtual_address_map: memory descriptor version unmatched\n"); + return EFI_INVALID_PARAMETER; + } + + if (descriptor_size != sizeof(efi_memory_desc_t)) { + printf ("efi_emulate_set_virtual_address_map: memory descriptor size unmatched\n"); + return EFI_INVALID_PARAMETER; + } + + if (d->arch.efi_virt_mode) return EFI_UNSUPPORTED; + + efi_map_start = virtual_map; + efi_map_end = efi_map_start + memory_map_size; + efi_desc_size = sizeof(efi_memory_desc_t); + + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) { + printf ("efi_emulate_set_virtual_address_map: copy_from_user() fault. addr=0x%p\n", p); + return EFI_UNSUPPORTED; + } + + /* skip over non-PAL_CODE memory descriptors; EFI_RUNTIME is included in PAL_CODE. */ + if (md->type != EFI_PAL_CODE) + continue; + +#define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \ + do { \ + vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \ + *vfn++ = FW_HYPERCALL_##call##_INDEX * 16UL + md->virt_addr; \ + *vfn++ = 0; \ + } while (0) + + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_time,EFI_GET_TIME); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_time,EFI_SET_TIME); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_variable,EFI_GET_VARIABLE); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT); + EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM); + } + + /* The virtual address map has been applied. */ + d->arch.efi_virt_mode = 1; + + return EFI_SUCCESS; +} + +efi_status_t +efi_emulator (struct pt_regs *regs, IA64FAULT *fault) +{ + struct vcpu *v = current; + efi_status_t status; + + *fault = IA64_NO_FAULT; + + switch (regs->r2) { + case FW_HYPERCALL_EFI_RESET_SYSTEM: + printf("efi.reset_system called "); + if (current->domain == dom0) { + printf("(by dom0)\n "); + (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL); + } + else + domain_shutdown (current->domain, SHUTDOWN_reboot); + status = EFI_UNSUPPORTED; + break; + case FW_HYPERCALL_EFI_GET_TIME: + status = efi_emulate_get_time ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + fault); + break; + case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: + status = efi_emulate_set_virtual_address_map ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + (u32) vcpu_get_gr(v,34), + (efi_memory_desc_t *) vcpu_get_gr(v,35)); + break; + case FW_HYPERCALL_EFI_SET_TIME: + case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: + case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: + // FIXME: need fixes in efi.h from 2.6.9 + case FW_HYPERCALL_EFI_GET_VARIABLE: + // FIXME: need fixes in efi.h from 2.6.9 + case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: + case FW_HYPERCALL_EFI_SET_VARIABLE: + case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: + // FIXME: need fixes in efi.h from 2.6.9 + status = EFI_UNSUPPORTED; + break; + default: + printf("unknown ia64 fw hypercall %lx\n", regs->r2); + status = EFI_UNSUPPORTED; + } + + return status; +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |