[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] boot windows server 2003: support 8k guest pagesize



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 27ccf13dc3b7c37eadcc84f2682995ab3afc2543
# Parent  00dd5eb7adc123cbbb4aabfafaad191777e1f3c7
[IA64] boot windows server 2003: support 8k guest pagesize

Make HASH VTLB support 8K page size which is used by windows

Signed-off-by: Anthony Xu <anthony.xu@xxxxxxxxx>
[whitespace and masking cleanups]
Signed-off-by: Alex Williamson <alex.williamson@xxxxxx>
---
 xen/arch/ia64/vmx/vmmu.c                     |   19 +++-
 xen/arch/ia64/vmx/vmx_phy_mode.c             |   47 ++++++-----
 xen/arch/ia64/vmx/vmx_process.c              |   32 ++++----
 xen/arch/ia64/vmx/vtlb.c                     |  106 +++++++++++++--------------
 xen/include/asm-ia64/linux-xen/asm/pgtable.h |    3 
 xen/include/asm-ia64/vmx_vcpu.h              |    3 
 6 files changed, 116 insertions(+), 94 deletions(-)

diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 xen/arch/ia64/vmx/vmmu.c
--- a/xen/arch/ia64/vmx/vmmu.c  Mon Jul 31 15:14:47 2006 -0600
+++ b/xen/arch/ia64/vmx/vmmu.c  Tue Aug 01 14:44:04 2006 -0600
@@ -316,7 +316,7 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *cod
     u64     gpip=0;   // guest physical IP
     u64     *vpa;
     thash_data_t    *tlb;
-    u64     mfn;
+    u64     mfn, maddr;
     struct page_info* page;
 
  again:
@@ -333,11 +333,14 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *cod
     if( gpip){
         mfn = gmfn_to_mfn(vcpu->domain, gpip >>PAGE_SHIFT);
         if( mfn == INVALID_MFN )  panic_domain(vcpu_regs(vcpu),"fetch_code: 
invalid memory\n");
+        maddr = (mfn << PAGE_SHIFT) | (gpip & (PAGE_SIZE - 1));
     }else{
         tlb = vhpt_lookup(gip);
         if( tlb == NULL)
             panic_domain(vcpu_regs(vcpu),"No entry found in ITLB and DTLB\n");
         mfn = tlb->ppn >> (PAGE_SHIFT - ARCH_PAGE_SHIFT);
+        maddr = (tlb->ppn >> (tlb->ps - 12) << tlb->ps) |
+                (gip & (PSIZE(tlb->ps) - 1));
     }
 
     page = mfn_to_page(mfn);
@@ -349,7 +352,7 @@ fetch_code(VCPU *vcpu, u64 gip, u64 *cod
         }
         goto again;
     }
-    vpa = (u64 *)__va((mfn << PAGE_SHIFT) | (gip & (PAGE_SIZE - 1)));
+    vpa = (u64 *)__va(maddr);
 
     *code1 = *vpa++;
     *code2 = *vpa;
@@ -371,6 +374,7 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UIN
         return IA64_FAULT;
     }
 #endif //VTLB_DEBUG    
+    pte &= ~PAGE_FLAGS_RV_MASK;
     thash_purge_and_insert(vcpu, pte, itir, ifa);
     return IA64_NO_FAULT;
 }
@@ -390,6 +394,7 @@ IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UIN
         return IA64_FAULT;
     }
 #endif //VTLB_DEBUG
+    pte &= ~PAGE_FLAGS_RV_MASK;
     gpfn = (pte & _PAGE_PPN_MASK)>> PAGE_SHIFT;
     if (VMX_DOMAIN(vcpu) && __gpfn_is_io(vcpu->domain, gpfn))
         pte |= VTLB_PTE_IO;
@@ -418,7 +423,8 @@ IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, u64
         return IA64_FAULT;
     }
     thash_purge_entries(vcpu, va, ps);
-#endif    
+#endif
+    pte &= ~PAGE_FLAGS_RV_MASK;
     vcpu_get_rr(vcpu, va, &rid);
     rid = rid& RR_RID_MASK;
     p_itr = (thash_data_t *)&vcpu->arch.itrs[slot];
@@ -432,8 +438,8 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, u64
 {
 #ifdef VTLB_DEBUG
     int index;
+#endif    
     u64 gpfn;
-#endif    
     u64 ps, va, rid;
     thash_data_t * p_dtr;
     ps = itir_ps(itir);
@@ -445,11 +451,12 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, u64
         panic_domain(vcpu_regs(vcpu),"Tlb conflict!!");
         return IA64_FAULT;
     }
+#endif   
+    pte &= ~PAGE_FLAGS_RV_MASK;
     thash_purge_entries(vcpu, va, ps);
     gpfn = (pte & _PAGE_PPN_MASK)>> PAGE_SHIFT;
-    if(VMX_DOMAIN(vcpu) && _gpfn_is_io(vcpu->domain,gpfn))
+    if (VMX_DOMAIN(vcpu) && __gpfn_is_io(vcpu->domain, gpfn))
         pte |= VTLB_PTE_IO;
-#endif    
     vcpu_get_rr(vcpu, va, &rid);
     rid = rid& RR_RID_MASK;
     p_dtr = (thash_data_t *)&vcpu->arch.dtrs[slot];
diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 xen/arch/ia64/vmx/vmx_phy_mode.c
--- a/xen/arch/ia64/vmx/vmx_phy_mode.c  Mon Jul 31 15:14:47 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_phy_mode.c  Tue Aug 01 14:44:04 2006 -0600
@@ -110,9 +110,14 @@ physical_tlb_miss(VCPU *vcpu, u64 vadr)
 physical_tlb_miss(VCPU *vcpu, u64 vadr)
 {
     u64 pte;
+    ia64_rr rr;
+    rr.rrval = ia64_get_rr(vadr);
     pte =  vadr& _PAGE_PPN_MASK;
-    pte = pte | PHY_PAGE_WB;
-    thash_purge_and_insert(vcpu, pte, (PAGE_SHIFT<<2), vadr);
+    if (vadr >> 63)
+        pte = pte | PHY_PAGE_UC;
+    else
+        pte = pte | PHY_PAGE_WB;
+    thash_vhpt_insert(vcpu, pte, (rr.ps << 2), vadr);
     return;
 }
 
@@ -120,19 +125,14 @@ void
 void
 vmx_init_all_rr(VCPU *vcpu)
 {
-       VMX(vcpu,vrr[VRN0]) = 0x38;
-       VMX(vcpu,vrr[VRN1]) = 0x138;
-       VMX(vcpu,vrr[VRN2]) = 0x238;
-       VMX(vcpu,vrr[VRN3]) = 0x338;
-       VMX(vcpu,vrr[VRN4]) = 0x438;
-       VMX(vcpu,vrr[VRN5]) = 0x538;
-       VMX(vcpu,vrr[VRN6]) = 0x660;
-       VMX(vcpu,vrr[VRN7]) = 0x760;
-#if 0
-       VMX(vcpu,mrr5) = vrrtomrr(vcpu, 0x38);
-       VMX(vcpu,mrr6) = vrrtomrr(vcpu, 0x60);
-       VMX(vcpu,mrr7) = vrrtomrr(vcpu, 0x60);
-#endif
+       VMX(vcpu, vrr[VRN0]) = 0x38;
+       VMX(vcpu, vrr[VRN1]) = 0x38;
+       VMX(vcpu, vrr[VRN2]) = 0x38;
+       VMX(vcpu, vrr[VRN3]) = 0x38;
+       VMX(vcpu, vrr[VRN4]) = 0x38;
+       VMX(vcpu, vrr[VRN5]) = 0x38;
+       VMX(vcpu, vrr[VRN6]) = 0x38;
+       VMX(vcpu, vrr[VRN7]) = 0x738;
 }
 
 extern void * pal_vaddr;
@@ -208,18 +208,19 @@ switch_to_physical_rid(VCPU *vcpu)
 switch_to_physical_rid(VCPU *vcpu)
 {
     UINT64 psr;
-    ia64_rr phy_rr;
-
+    ia64_rr phy_rr, mrr;
 
     /* Save original virtual mode rr[0] and rr[4] */
     psr=ia64_clear_ic();
     phy_rr.rrval = vcpu->domain->arch.metaphysical_rr0;
-//    phy_rr.ps = EMUL_PHY_PAGE_SHIFT;
+    mrr.rrval = ia64_get_rr(VRN0 << VRN_SHIFT);
+    phy_rr.ps = mrr.ps;
     phy_rr.ve = 1;
     ia64_set_rr(VRN0<<VRN_SHIFT, phy_rr.rrval);
     ia64_srlz_d();
     phy_rr.rrval = vcpu->domain->arch.metaphysical_rr4;
-//    phy_rr.ps = EMUL_PHY_PAGE_SHIFT;
+    mrr.rrval = ia64_get_rr(VRN4 << VRN_SHIFT);
+    phy_rr.ps = mrr.ps;
     phy_rr.ve = 1;
     ia64_set_rr(VRN4<<VRN_SHIFT, phy_rr.rrval);
     ia64_srlz_d();
@@ -262,6 +263,8 @@ switch_mm_mode(VCPU *vcpu, IA64_PSR old_
     act = mm_switch_action(old_psr, new_psr);
     switch (act) {
     case SW_V2P:
+//        printf("V -> P mode transition: (0x%lx -> 0x%lx)\n",
+//               old_psr.val, new_psr.val);
         vcpu->arch.old_rsc = regs->ar_rsc;
         switch_to_physical_rid(vcpu);
         /*
@@ -272,6 +275,8 @@ switch_mm_mode(VCPU *vcpu, IA64_PSR old_
         vcpu->arch.mode_flags |= GUEST_IN_PHY;
         break;
     case SW_P2V:
+//        printf("P -> V mode transition: (0x%lx -> 0x%lx)\n",
+//               old_psr.val, new_psr.val);
         switch_to_virtual_rid(vcpu);
         /*
          * recover old mode which is saved when entering
@@ -285,8 +290,8 @@ switch_mm_mode(VCPU *vcpu, IA64_PSR old_
             old_psr.val);
         break;
     case SW_NOP:
-        printf("No action required for mode transition: (0x%lx -> 0x%lx)\n",
-            old_psr.val, new_psr.val);
+//        printf("No action required for mode transition: (0x%lx -> 0x%lx)\n",
+//               old_psr.val, new_psr.val);
         break;
     default:
         /* Sanity check */
diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 xen/arch/ia64/vmx/vmx_process.c
--- a/xen/arch/ia64/vmx/vmx_process.c   Mon Jul 31 15:14:47 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_process.c   Tue Aug 01 14:44:04 2006 -0600
@@ -273,21 +273,24 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* r
 //    prepare_if_physical_mode(v);
 
     if((data=vtlb_lookup(v, vadr,type))!=0){
-//       gppa = 
(vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
-//       if(v->domain!=dom0&&type==DSIDE_TLB && 
__gpfn_is_io(v->domain,gppa>>PAGE_SHIFT)){
-        if(v->domain!=dom0 && data->io && type==DSIDE_TLB ){
-            if(data->pl >= ((regs->cr_ipsr>>IA64_PSR_CPL0_BIT)&3)){
-                gppa = 
(vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
-                emulate_io_inst(v, gppa, data->ma);
-            }else{
-                vcpu_set_isr(v,misr.val);
-                data_access_rights(v, vadr);
-            }
-            return IA64_FAULT;
-        }
-
+        if (v->domain != dom0 && type == DSIDE_TLB) {
+            gppa = (vadr & ((1UL << data->ps) - 1)) +
+                   (data->ppn >> (data->ps - 12) << data->ps);
+            if (__gpfn_is_io(v->domain, gppa >> PAGE_SHIFT)) {
+                if (data->pl >= ((regs->cr_ipsr >> IA64_PSR_CPL0_BIT) & 3))
+                    emulate_io_inst(v, gppa, data->ma);
+                else {
+                    vcpu_set_isr(v, misr.val);
+                    data_access_rights(v, vadr);
+                }
+                return IA64_FAULT;
+            }
+        }
         thash_vhpt_insert(v,data->page_flags, data->itir ,vadr);
+
     }else if(type == DSIDE_TLB){
+        if (misr.sp)
+            return vmx_handle_lds(regs);
         if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
             if(vpsr.ic){
                 vcpu_set_isr(v, misr.val);
@@ -306,7 +309,8 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* r
         } else{
             vmx_vcpu_thash(v, vadr, &vhpt_adr);
             if(!guest_vhpt_lookup(vhpt_adr, &pteval)){
-                if (pteval & _PAGE_P){
+                if ((pteval & _PAGE_P) &&
+                    ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST)) {
                     vcpu_get_rr(v, vadr, &rr);
                     itir = rr&(RR_RID_MASK | RR_PS_MASK);
                     thash_purge_and_insert(v, pteval, itir , vadr);
diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 xen/arch/ia64/vmx/vtlb.c
--- a/xen/arch/ia64/vmx/vtlb.c  Mon Jul 31 15:14:47 2006 -0600
+++ b/xen/arch/ia64/vmx/vtlb.c  Tue Aug 01 14:44:04 2006 -0600
@@ -141,14 +141,18 @@ static void thash_recycle_cch(thash_cb_t
 
 static void vmx_vhpt_insert(thash_cb_t *hcb, u64 pte, u64 itir, u64 ifa)
 {
-    u64 tag;
+    u64 tag ,len;
+    ia64_rr rr;
     thash_data_t *head, *cch;
     pte = pte & ~PAGE_FLAGS_RV_MASK;
-
+    rr.rrval = ia64_get_rr(ifa);
     head = (thash_data_t *)ia64_thash(ifa);
     tag = ia64_ttag(ifa);
     if( INVALID_VHPT(head) ) {
+        len = head->len;
         head->page_flags = pte;
+        head->len = len;
+        head->itir = rr.ps << 2;
         head->etag = tag;
         return;
     }
@@ -160,10 +164,9 @@ static void vmx_vhpt_insert(thash_cb_t *
     else{
         cch = __alloc_chain(hcb);
     }
-    cch->page_flags=head->page_flags;
-    cch->etag=head->etag;
-    cch->next=head->next;
+    *cch = *head;
     head->page_flags=pte;
+    head->itir = rr.ps << 2;
     head->etag=tag;
     head->next = cch;
     head->len = cch->len+1;
@@ -210,7 +213,13 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
 u64 guest_vhpt_lookup(u64 iha, u64 *pte)
 {
     u64 ret;
-    vhpt_lookup(iha);
+    thash_data_t * data;
+    data = vhpt_lookup(iha);
+    if (data == NULL) {
+        data = vtlb_lookup(current, iha, DSIDE_TLB);
+        if (data != NULL)
+            thash_vhpt_insert(current, data->page_flags, data->itir ,iha);
+    }
     asm volatile ("rsm psr.ic|psr.i;;"
                   "srlz.d;;"
                   "ld8.s r9=[%1];;"
@@ -231,10 +240,10 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
  *  purge software guest tlb
  */
 
-static void vtlb_purge(VCPU *v, u64 va, u64 ps)
+void vtlb_purge(VCPU *v, u64 va, u64 ps)
 {
     thash_cb_t *hcb = &v->arch.vtlb;
-    thash_data_t *hash_table, *prev, *next;
+    thash_data_t *cur;
     u64 start, end, size, tag, rid, def_size;
     ia64_rr vrr;
     vcpu_get_rr(v, va, &vrr.rrval);
@@ -244,23 +253,11 @@ static void vtlb_purge(VCPU *v, u64 va, 
     end = start + size;
     def_size = PSIZE(vrr.ps);
     while(start < end){
-        hash_table = vsa_thash(hcb->pta, start, vrr.rrval, &tag);
-        if(!INVALID_TLB(hash_table)){
-            if(hash_table->etag == tag){
-                 hash_table->etag = 1UL<<63;
-            }
-            else{
-                prev=hash_table;
-                next=prev->next;
-                while(next){
-                    if(next->etag == tag){
-                        next->etag = 1UL<<63;
-                        break;
-                    }
-                    prev=next;
-                    next=next->next;
-                }
-            }
+        cur = vsa_thash(hcb->pta, start, vrr.rrval, &tag);
+        while (cur) {
+            if (cur->etag == tag)
+                 cur->etag = 1UL << 63;
+            cur = cur->next;
         }
         start += def_size;
     }
@@ -274,30 +271,23 @@ static void vhpt_purge(VCPU *v, u64 va, 
 static void vhpt_purge(VCPU *v, u64 va, u64 ps)
 {
     //thash_cb_t *hcb = &v->arch.vhpt;
-    thash_data_t *hash_table, *prev, *next;
+    thash_data_t *cur;
     u64 start, end, size, tag;
+    ia64_rr rr;
     size = PSIZE(ps);
     start = va & (-size);
     end = start + size;
+    rr.rrval = ia64_get_rr(va);
+    size = PSIZE(rr.ps);    
     while(start < end){
-        hash_table = (thash_data_t *)ia64_thash(start);
+        cur = (thash_data_t *)ia64_thash(start);
         tag = ia64_ttag(start);
-        if(hash_table->etag == tag ){
-            hash_table->etag = 1UL<<63; 
-        }
-        else{
-            prev=hash_table;
-            next=prev->next;
-            while(next){
-                if(next->etag == tag){
-                    next->etag = 1UL<<63;
-                    break; 
-                }
-                prev=next;
-                next=next->next;
-            }
-        }
-        start += PAGE_SIZE;
+        while (cur) {
+            if (cur->etag == tag)
+                cur->etag = 1UL << 63; 
+            cur = cur->next;
+        }
+        start += size;
     }
     machine_tlb_purge(va, ps);
 }
@@ -349,7 +339,7 @@ void vtlb_insert(thash_cb_t *hcb, u64 pt
     /* int flag; */
     ia64_rr vrr;
     /* u64 gppn, ppns, ppne; */
-    u64 tag;
+    u64 tag, len;
     vcpu_get_rr(current, va, &vrr.rrval);
 #ifdef VTLB_DEBUG    
     if (vrr.ps != itir_ps(itir)) {
@@ -361,7 +351,9 @@ void vtlb_insert(thash_cb_t *hcb, u64 pt
 #endif
     hash_table = vsa_thash(hcb->pta, va, vrr.rrval, &tag);
     if( INVALID_TLB(hash_table) ) {
+        len = hash_table->len;
         hash_table->page_flags = pte;
+        hash_table->len = len;
         hash_table->itir=itir;
         hash_table->etag=tag;
         return;
@@ -425,18 +417,23 @@ void thash_purge_entries(VCPU *v, u64 va
 
 u64 translate_phy_pte(VCPU *v, u64 *pte, u64 itir, u64 va)
 {
-    u64 ps, addr;
+    u64 ps, ps_mask, paddr, maddr;
+//    ia64_rr rr;
     union pte_flags phy_pte;
     ps = itir_ps(itir);
+    ps_mask = ~((1UL << ps) - 1);
     phy_pte.val = *pte;
-    addr = *pte;
-    addr = ((addr & _PAGE_PPN_MASK)>>ps<<ps)|(va&((1UL<<ps)-1));
-    addr = lookup_domain_mpa(v->domain, addr, NULL);
-    if(addr & GPFN_IO_MASK){
+    paddr = *pte;
+    paddr = ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask);
+    maddr = lookup_domain_mpa(v->domain, paddr, NULL);
+    if (maddr & GPFN_IO_MASK) {
         *pte |= VTLB_PTE_IO;
         return -1;
     }
-    phy_pte.ppn = addr >> ARCH_PAGE_SHIFT;
+//    rr.rrval = ia64_get_rr(va);
+//    ps = rr.ps;
+    maddr = ((maddr & _PAGE_PPN_MASK) & PAGE_MASK) | (paddr & ~PAGE_MASK);
+    phy_pte.ppn = maddr >> ARCH_PAGE_SHIFT;
     return phy_pte.val;
 }
 
@@ -449,8 +446,13 @@ void thash_purge_and_insert(VCPU *v, u64
 {
     u64 ps;//, va;
     u64 phy_pte;
+    ia64_rr vrr;
     ps = itir_ps(itir);
-
+    vcpu_get_rr(current, ifa, &vrr.rrval);
+//    if (vrr.ps != itir_ps(itir)) {
+//        printf("not preferred ps with va: 0x%lx vrr.ps=%d ps=%ld\n",
+//               ifa, vrr.ps, itir_ps(itir));
+//    }
     if(VMX_DOMAIN(v)){
         /* Ensure WB attribute if pte is related to a normal mem page,
          * which is required by vga acceleration since qemu maps shared
@@ -460,7 +462,7 @@ void thash_purge_and_insert(VCPU *v, u64
             pte &= ~_PAGE_MA_MASK;
 
         phy_pte = translate_phy_pte(v, &pte, itir, ifa);
-        if(ps==PAGE_SHIFT){
+        if (vrr.ps <= PAGE_SHIFT) {
             if(!(pte&VTLB_PTE_IO)){
                 vhpt_purge(v, ifa, ps);
                 vmx_vhpt_insert(&v->arch.vhpt, phy_pte, itir, ifa);
diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 
xen/include/asm-ia64/linux-xen/asm/pgtable.h
--- a/xen/include/asm-ia64/linux-xen/asm/pgtable.h      Mon Jul 31 15:14:47 
2006 -0600
+++ b/xen/include/asm-ia64/linux-xen/asm/pgtable.h      Tue Aug 01 14:44:04 
2006 -0600
@@ -38,6 +38,9 @@
 
 #define _PAGE_P                        (1 << _PAGE_P_BIT)      /* page present 
bit */
 #define _PAGE_MA_WB            (0x0 <<  2)     /* write back memory attribute 
*/
+#ifdef XEN
+#define _PAGE_MA_ST            (0x1 <<  2)     /* is reserved for software use 
*/
+#endif
 #define _PAGE_MA_UC            (0x4 <<  2)     /* uncacheable memory attribute 
*/
 #define _PAGE_MA_UCE           (0x5 <<  2)     /* UC exported attribute */
 #define _PAGE_MA_WC            (0x6 <<  2)     /* write coalescing memory 
attribute */
diff -r 00dd5eb7adc1 -r 27ccf13dc3b7 xen/include/asm-ia64/vmx_vcpu.h
--- a/xen/include/asm-ia64/vmx_vcpu.h   Mon Jul 31 15:14:47 2006 -0600
+++ b/xen/include/asm-ia64/vmx_vcpu.h   Tue Aug 01 14:44:04 2006 -0600
@@ -467,7 +467,8 @@ vrrtomrr(VCPU *v, unsigned long val)
 
     rr.rrval=val;
     rr.rid = rr.rid + v->arch.starting_rid;
-    rr.ps = PAGE_SHIFT;
+    if (rr.ps > PAGE_SHIFT)
+        rr.ps = PAGE_SHIFT;
     rr.ve = 1;
     return  vmMangleRID(rr.rrval);
 /* Disable this rid allocation algorithm for now */

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.