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

[Xen-changelog] [xen-unstable] [XEN] Get rid of gva_to_gpa translation



# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1171985823 0
# Node ID 6746873997b5441ed875ec17b626d2863dc5255c
# Parent  e4ddec3dffb0b0dbd1fdc4dc51e1aafcba05bfb7
[XEN] Get rid of gva_to_gpa translation
It didn't have any sensible error checking.  Make all callers
use gva_to_gfn translation and check the result.  MMIO and PIO
callers inject pagefaults to the guest iof the non-IO address is
not mapped.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/io.c          |   30 ++++++++++++++-
 xen/arch/x86/hvm/platform.c    |   77 ++++++++++++++++++++++++++---------------
 xen/arch/x86/hvm/svm/svm.c     |   48 +++++++++++++++++++++----
 xen/arch/x86/hvm/vmx/vmx.c     |   39 ++++++++++++++++++--
 xen/arch/x86/mm/shadow/multi.c |   14 -------
 xen/arch/x86/mm/shadow/types.h |    3 +
 xen/include/asm-x86/hvm/io.h   |    2 -
 xen/include/asm-x86/p2m.h      |    2 -
 xen/include/asm-x86/paging.h   |   15 +------
 9 files changed, 160 insertions(+), 70 deletions(-)

diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/hvm/io.c     Tue Feb 20 15:37:03 2007 +0000
@@ -371,7 +371,20 @@ static void hvm_pio_assist(struct cpu_us
             {
                 unsigned long addr = pio_opp->addr;
                 if ( hvm_paging_enabled(current) )
-                    (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
+                {
+                    int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
+                    if ( rv != 0 ) 
+                    {
+                        /* Failed on the page-spanning copy.  Inject PF into
+                         * the guest for the address where we failed. */
+                        addr += p->size - rv;
+                        gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side "
+                                 "of a page-spanning PIO: va=%#lx\n", addr);
+                        hvm_inject_exception(TRAP_page_fault, 
+                                             PFEC_write_access, addr);
+                        return;
+                    }
+                }
                 else
                     (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
             }
@@ -489,7 +502,20 @@ static void hvm_mmio_assist(struct cpu_u
             unsigned long addr = mmio_opp->addr;
 
             if (hvm_paging_enabled(current))
-                (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
+            {
+                int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
+                if ( rv != 0 ) 
+                {
+                    /* Failed on the page-spanning copy.  Inject PF into
+                     * the guest for the address where we failed. */
+                    addr += p->size - rv;
+                    gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side of "
+                             "a page-spanning MMIO: va=%#lx\n", addr);
+                    hvm_inject_exception(TRAP_page_fault, 
+                                         PFEC_write_access, addr);
+                    return;
+                }
+            }
             else
                 (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
         }
diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/hvm/platform.c       Tue Feb 20 15:37:03 2007 +0000
@@ -815,7 +815,7 @@ int inst_copy_from_guest(unsigned char *
 }
 
 void send_pio_req(unsigned long port, unsigned long count, int size,
-                  long value, int dir, int df, int value_is_ptr)
+                  paddr_t value, int dir, int df, int value_is_ptr)
 {
     struct vcpu *v = current;
     vcpu_iodata_t *vio;
@@ -823,7 +823,7 @@ void send_pio_req(unsigned long port, un
 
     if ( size == 0 || count == 0 ) {
         printk("null pio request? port %lx, count %lx, "
-               "size %d, value %lx, dir %d, value_is_ptr %d.\n",
+               "size %d, value %"PRIpaddr", dir %d, value_is_ptr %d.\n",
                port, count, size, value, dir, value_is_ptr);
     }
 
@@ -849,15 +849,7 @@ void send_pio_req(unsigned long port, un
 
     p->io_count++;
 
-    if ( value_is_ptr )   /* get physical address of data */
-    {
-        if ( hvm_paging_enabled(current) )
-            p->data = paging_gva_to_gpa(current, value);
-        else
-            p->data = value; /* guest VA == guest PA */
-    }
-    else if ( dir == IOREQ_WRITE )
-        p->data = value;
+    p->data = value;
 
     if ( hvm_portio_intercept(p) )
     {
@@ -870,7 +862,7 @@ void send_pio_req(unsigned long port, un
 }
 
 static void send_mmio_req(unsigned char type, unsigned long gpa,
-                          unsigned long count, int size, long value,
+                          unsigned long count, int size, paddr_t value,
                           int dir, int df, int value_is_ptr)
 {
     struct vcpu *v = current;
@@ -879,7 +871,8 @@ static void send_mmio_req(unsigned char 
 
     if ( size == 0 || count == 0 ) {
         printk("null mmio request? type %d, gpa %lx, "
-               "count %lx, size %d, value %lx, dir %d, value_is_ptr %d.\n",
+               "count %lx, size %d, value %"PRIpaddr"x, dir %d, "
+               "value_is_ptr %d.\n",
                type, gpa, count, size, value, dir, value_is_ptr);
     }
 
@@ -905,15 +898,7 @@ static void send_mmio_req(unsigned char 
 
     p->io_count++;
 
-    if ( value_is_ptr )
-    {
-        if ( hvm_paging_enabled(v) )
-            p->data = paging_gva_to_gpa(v, value);
-        else
-            p->data = value; /* guest VA == guest PA */
-    }
-    else
-        p->data = value;
+    p->data = value;
 
     if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
     {
@@ -960,6 +945,7 @@ static void mmio_operands(int type, unsi
 #define GET_REPEAT_COUNT() \
      (mmio_op->flags & REPZ ? (ad_size == WORD ? regs->ecx & 0xFFFF : 
regs->ecx) : 1)
 
+
 void handle_mmio(unsigned long gpa)
 {
     unsigned long inst_addr;
@@ -1014,7 +1000,8 @@ void handle_mmio(unsigned long gpa)
     {
         unsigned long count = GET_REPEAT_COUNT();
         int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
-        unsigned long addr;
+        unsigned long addr, gfn; 
+        paddr_t paddr;
         int dir, size = op_size;
 
         ASSERT(count);
@@ -1024,7 +1011,9 @@ void handle_mmio(unsigned long gpa)
         if ( ad_size == WORD )
             addr &= 0xFFFF;
         addr += hvm_get_segment_base(v, x86_seg_es);
-        if ( paging_gva_to_gpa(v, addr) == gpa )
+        gfn = paging_gva_to_gfn(v, addr);
+        paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+        if ( paddr == gpa )
         {
             enum x86_segment seg;
 
@@ -1044,9 +1033,23 @@ void handle_mmio(unsigned long gpa)
             default: domain_crash_synchronous();
             }
             addr += hvm_get_segment_base(v, seg);
+            gfn = paging_gva_to_gfn(v, addr);
+            paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
         }
         else
             dir = IOREQ_READ;
+
+        if ( gfn == INVALID_GFN ) 
+        {
+            /* The guest does not have the non-mmio address mapped. 
+             * Need to send in a page fault */
+            int errcode = 0;
+            /* IO read --> memory write */
+            if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+            regs->eip -= inst_len; /* do not advance %eip */
+            hvm_inject_exception(TRAP_page_fault, errcode, addr);
+            return;
+        }
 
         /*
          * In case of a movs spanning multiple pages, we break the accesses
@@ -1065,10 +1068,27 @@ void handle_mmio(unsigned long gpa)
 
             if ( dir == IOREQ_WRITE ) {
                 if ( hvm_paging_enabled(v) )
-                    (void)hvm_copy_from_guest_virt(&value, addr, size);
+                {
+                    int rv = hvm_copy_from_guest_virt(&value, addr, size);
+                    if ( rv != 0 ) 
+                    {
+                        /* Failed on the page-spanning copy.  Inject PF into
+                         * the guest for the address where we failed */
+                        regs->eip -= inst_len; /* do not advance %eip */
+                        /* Must set CR2 at the failing address */ 
+                        addr += size - rv;
+                        gdprintk(XENLOG_DEBUG, "Pagefault on non-io side of a "
+                                 "page-spanning MMIO: va=%#lx\n", addr);
+                        hvm_inject_exception(TRAP_page_fault, 0, addr);
+                        return;
+                    }
+                }
                 else
-                    (void)hvm_copy_from_guest_phys(&value, addr, size);
-            } else
+                    (void) hvm_copy_from_guest_phys(&value, addr, size);
+            } else /* dir != IOREQ_WRITE */
+                /* Remember where to write the result, as a *VA*.
+                 * Must be a VA so we can handle the page overlap 
+                 * correctly in hvm_mmio_assist() */
                 mmio_op->addr = addr;
 
             if ( count != 1 )
@@ -1091,7 +1111,8 @@ void handle_mmio(unsigned long gpa)
 
             ASSERT(count);
 
-            send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, df, 1);
+            send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, 
+                          paddr, dir, df, 1);
         }
         break;
     }
diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Feb 20 15:37:03 2007 +0000
@@ -1589,6 +1589,8 @@ static void svm_io_instruction(struct vc
     if (info.fields.str)
     { 
         unsigned long addr, count;
+        paddr_t paddr;
+        unsigned long gfn;
         int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
 
         if (!svm_get_io_address(v, regs, size, info, &count, &addr))
@@ -1606,6 +1608,20 @@ static void svm_io_instruction(struct vc
             pio_opp->flags |= REPZ;
         }
 
+        /* Translate the address to a physical address */
+        gfn = paging_gva_to_gfn(v, addr);
+        if ( gfn == INVALID_GFN ) 
+        {
+            /* The guest does not have the RAM address mapped. 
+             * Need to send in a page fault */
+            int errcode = 0;
+            /* IO read --> memory write */
+            if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+            svm_hvm_inject_exception(TRAP_page_fault, errcode, addr);
+            return;
+        }
+        paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+
         /*
          * Handle string pio instructions that cross pages or that
          * are unaligned. See the comments in hvm_platform.c/handle_mmio()
@@ -1619,11 +1635,27 @@ static void svm_io_instruction(struct vc
 
             if (dir == IOREQ_WRITE)   /* OUTS */
             {
-                if (hvm_paging_enabled(current))
-                    (void)hvm_copy_from_guest_virt(&value, addr, size);
+                if ( hvm_paging_enabled(current) )
+                {
+                    int rv = hvm_copy_from_guest_virt(&value, addr, size);
+                    if ( rv != 0 ) 
+                    {
+                        /* Failed on the page-spanning copy.  Inject PF into
+                         * the guest for the address where we failed. */
+                        addr += size - rv;
+                        gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
+                                 "of a page-spanning PIO: va=%#lx\n", addr);
+                        svm_hvm_inject_exception(TRAP_page_fault, 0, addr);
+                        return;
+                    }
+                }
                 else
-                    (void)hvm_copy_from_guest_phys(&value, addr, size);
-            }
+                    (void) hvm_copy_from_guest_phys(&value, addr, size);
+            } else /* dir != IOREQ_WRITE */
+                /* Remember where to write the result, as a *VA*.
+                 * Must be a VA so we can handle the page overlap 
+                 * correctly in hvm_pio_assist() */
+                pio_opp->addr = addr;
 
             if (count == 1)
                 regs->eip = vmcb->exitinfo2;
@@ -1645,7 +1677,7 @@ static void svm_io_instruction(struct vc
             else    
                 regs->eip = vmcb->exitinfo2;
 
-            send_pio_req(port, count, size, addr, dir, df, 1);
+            send_pio_req(port, count, size, paddr, dir, df, 1);
         }
     } 
     else 
@@ -2718,7 +2750,8 @@ asmlinkage void svm_vmexit_handler(struc
         if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF) 
         {
             if (svm_paging_enabled(v) && 
-                !mmio_space(paging_gva_to_gpa(current, vmcb->exitinfo2)))
+                !mmio_space(
+                    paging_gva_to_gfn(current, vmcb->exitinfo2) << PAGE_SHIFT))
             {
                 printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64","
                        "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", "
@@ -2728,7 +2761,8 @@ asmlinkage void svm_vmexit_handler(struc
                        (u64)vmcb->exitinfo1,
                        (u64)vmcb->exitinfo2,
                        (u64)vmcb->exitintinfo.bytes,
-                       (u64)paging_gva_to_gpa(current, vmcb->exitinfo2));
+                       (((u64)paging_gva_to_gfn(current, vmcb->exitinfo2)
+                        << PAGE_SHIFT) | (vmcb->exitinfo2 & ~PAGE_MASK)));
             }
             else 
             {
diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Feb 20 15:37:03 2007 +0000
@@ -1426,6 +1426,8 @@ static void vmx_io_instruction(unsigned 
 
     if ( test_bit(4, &exit_qualification) ) { /* string instruction */
         unsigned long addr, count = 1, base;
+        paddr_t paddr;
+        unsigned long gfn;
         u32 ar_bytes, limit;
         int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
         int long_mode = 0;
@@ -1545,6 +1547,20 @@ static void vmx_io_instruction(unsigned 
         }
 #endif
 
+        /* Translate the address to a physical address */
+        gfn = paging_gva_to_gfn(current, addr);
+        if ( gfn == INVALID_GFN ) 
+        {
+            /* The guest does not have the RAM address mapped. 
+             * Need to send in a page fault */
+            int errcode = 0;
+            /* IO read --> memory write */
+            if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+            vmx_inject_exception(TRAP_page_fault, errcode, addr);
+            return;
+        }
+        paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+
         /*
          * Handle string pio instructions that cross pages or that
          * are unaligned. See the comments in hvm_domain.c/handle_mmio()
@@ -1557,10 +1573,25 @@ static void vmx_io_instruction(unsigned 
             if ( dir == IOREQ_WRITE )   /* OUTS */
             {
                 if ( hvm_paging_enabled(current) )
-                    (void)hvm_copy_from_guest_virt(&value, addr, size);
+                {
+                    int rv = hvm_copy_from_guest_virt(&value, addr, size);
+                    if ( rv != 0 ) 
+                    {
+                        /* Failed on the page-spanning copy.  Inject PF into
+                         * the guest for the address where we failed. */ 
+                        addr += size - rv;
+                        gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
+                                 "of a page-spanning PIO: va=%#lx\n", addr);
+                        vmx_inject_exception(TRAP_page_fault, 0, addr);
+                        return;
+                    }
+                }
                 else
-                    (void)hvm_copy_from_guest_phys(&value, addr, size);
-            } else
+                    (void) hvm_copy_from_guest_phys(&value, addr, size);
+            } else /* dir != IOREQ_WRITE */
+                /* Remember where to write the result, as a *VA*.
+                 * Must be a VA so we can handle the page overlap 
+                 * correctly in hvm_pio_assist() */
                 pio_opp->addr = addr;
 
             if ( count == 1 )
@@ -1580,7 +1611,7 @@ static void vmx_io_instruction(unsigned 
             } else
                 regs->eip += inst_len;
 
-            send_pio_req(port, count, size, addr, dir, df, 1);
+            send_pio_req(port, count, size, paddr, dir, df, 1);
         }
     } else {
         if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Tue Feb 20 15:37:03 2007 +0000
@@ -3038,19 +3038,6 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
 }
 
 
-static paddr_t
-sh_gva_to_gpa(struct vcpu *v, unsigned long va)
-/* Called to translate a guest virtual address to what the *guest*
- * pagetables would map it to. */
-{
-    unsigned long gfn = sh_gva_to_gfn(v, va);
-    if ( gfn == INVALID_GFN )
-        return 0;
-    else
-        return (((paddr_t)gfn) << PAGE_SHIFT) + (va & ~PAGE_MASK);
-}
-
-
 static inline void
 sh_update_linear_entries(struct vcpu *v)
 /* Sync up all the linear mappings for this vcpu's pagetables */
@@ -4348,7 +4335,6 @@ struct paging_mode sh_paging_mode = {
 struct paging_mode sh_paging_mode = {
     .page_fault                    = sh_page_fault, 
     .invlpg                        = sh_invlpg,
-    .gva_to_gpa                    = sh_gva_to_gpa,
     .gva_to_gfn                    = sh_gva_to_gfn,
     .update_cr3                    = sh_update_cr3,
     .update_paging_modes           = shadow_update_paging_modes,
diff -r e4ddec3dffb0 -r 6746873997b5 xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/arch/x86/mm/shadow/types.h    Tue Feb 20 15:37:03 2007 +0000
@@ -244,6 +244,7 @@ static inline shadow_l4e_t shadow_l4e_fr
 
 /* Type of the guest's frame numbers */
 TYPE_SAFE(u32,gfn)
+#undef INVALID_GFN
 #define INVALID_GFN ((u32)(-1u))
 #define SH_PRI_gfn "05x"
 
@@ -307,6 +308,7 @@ static inline guest_l2e_t guest_l2e_from
 
 /* Type of the guest's frame numbers */
 TYPE_SAFE(unsigned long,gfn)
+#undef INVALID_GFN
 #define INVALID_GFN ((unsigned long)(-1ul))
 #define SH_PRI_gfn "05lx"
 
@@ -467,7 +469,6 @@ struct shadow_walk_t
  */
 #define sh_page_fault              INTERNAL_NAME(sh_page_fault)
 #define sh_invlpg                  INTERNAL_NAME(sh_invlpg)
-#define sh_gva_to_gpa              INTERNAL_NAME(sh_gva_to_gpa)
 #define sh_gva_to_gfn              INTERNAL_NAME(sh_gva_to_gfn)
 #define sh_update_cr3              INTERNAL_NAME(sh_update_cr3)
 #define sh_rm_write_access_from_l1 INTERNAL_NAME(sh_rm_write_access_from_l1)
diff -r e4ddec3dffb0 -r 6746873997b5 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/include/asm-x86/hvm/io.h      Tue Feb 20 15:37:03 2007 +0000
@@ -144,7 +144,7 @@ static inline int irq_masked(unsigned lo
 #endif
 
 extern void send_pio_req(unsigned long port, unsigned long count, int size,
-                         long value, int dir, int df, int value_is_ptr);
+                         paddr_t value, int dir, int df, int value_is_ptr);
 extern void handle_mmio(unsigned long gpa);
 extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
 extern void hvm_io_assist(struct vcpu *v);
diff -r e4ddec3dffb0 -r 6746873997b5 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/include/asm-x86/p2m.h Tue Feb 20 15:37:03 2007 +0000
@@ -89,7 +89,7 @@ static inline unsigned long get_mfn_from
 /* Is this guest address an mmio one? (i.e. not defined in p2m map) */
 static inline int mmio_space(paddr_t gpa)
 {
-    unsigned long gfn = gpa >> PAGE_SHIFT;    
+    unsigned long gfn = gpa >> PAGE_SHIFT;
     return !mfn_valid(mfn_x(gfn_to_mfn_current(gfn)));
 }
 
diff -r e4ddec3dffb0 -r 6746873997b5 xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h      Tue Feb 20 13:57:26 2007 +0000
+++ b/xen/include/asm-x86/paging.h      Tue Feb 20 15:37:03 2007 +0000
@@ -115,7 +115,6 @@ struct paging_mode {
     int           (*page_fault            )(struct vcpu *v, unsigned long va,
                                             struct cpu_user_regs *regs);
     int           (*invlpg                )(struct vcpu *v, unsigned long va);
-    paddr_t       (*gva_to_gpa            )(struct vcpu *v, unsigned long va);
     unsigned long (*gva_to_gfn            )(struct vcpu *v, unsigned long va);
     void          (*update_cr3            )(struct vcpu *v, int do_locking);
     void          (*update_paging_modes   )(struct vcpu *v);
@@ -190,18 +189,10 @@ static inline int paging_invlpg(struct v
     return v->arch.paging.mode->invlpg(v, va);
 }
 
-/* Translate a guest virtual address to the physical address that the
- * *guest* pagetables would map it to. */
-static inline paddr_t paging_gva_to_gpa(struct vcpu *v, unsigned long va)
-{
-    if ( unlikely(!paging_vcpu_mode_translate(v)) )
-        return (paddr_t) va;
-
-    return v->arch.paging.mode->gva_to_gpa(v, va);
-}
-
 /* Translate a guest virtual address to the frame number that the
- * *guest* pagetables would map it to. */
+ * *guest* pagetables would map it to.  Returns INVALID_GFN if the guest 
+ * tables don't map this address. */
+#define INVALID_GFN (-1UL)
 static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va)
 {
     if ( unlikely(!paging_vcpu_mode_translate(v)) )

_______________________________________________
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®.