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

[Minios-devel] [UNIKRAFT PATCH v2 5/8] plat/kvm: Add KVM (x86_64) interrupts support



From: Costin Lupu <costin.lupu@xxxxxxxxx>

Changes:
* PIC support
* KVM specific traps
* traps and interrupt assembly stubs
* shared IRQ handlers

Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
---
 plat/kvm/Config.uk                         |   1 +
 plat/kvm/Makefile.uk                       |   9 +-
 plat/kvm/include/kvm-x86/cpu_x86_64.h      |  42 -------
 plat/kvm/include/kvm-x86/cpu_x86_64_defs.h |  42 -------
 plat/kvm/include/kvm-x86/traps.h           |  45 +++++++
 plat/kvm/include/kvm/intctrl.h             |  38 ++++++
 plat/kvm/include/kvm/irq.h                 |  43 +++++++
 plat/kvm/irq.c                             | 100 ++++++++++++++++
 plat/kvm/shutdown.c                        |   9 ++
 plat/kvm/x86/cpu_vectors_x86_64.S          | 142 ++++++++++++++++++++++
 plat/kvm/x86/cpu_x86_64.c                  |  71 -----------
 plat/kvm/x86/entry64.S                     |   1 +
 plat/kvm/x86/intctrl.c                     | 111 +++++++++++++++++
 plat/kvm/x86/lcpu.c                        |  37 ++++++
 plat/kvm/x86/setup.c                       |   6 +-
 plat/kvm/x86/traps.c                       | 186 +++++++++++++++++++++++++++++
 16 files changed, 724 insertions(+), 159 deletions(-)
 delete mode 100644 plat/kvm/include/kvm-x86/cpu_x86_64.h
 delete mode 100644 plat/kvm/include/kvm-x86/cpu_x86_64_defs.h
 create mode 100644 plat/kvm/include/kvm-x86/traps.h
 create mode 100644 plat/kvm/include/kvm/intctrl.h
 create mode 100644 plat/kvm/include/kvm/irq.h
 create mode 100644 plat/kvm/irq.c
 create mode 100644 plat/kvm/x86/cpu_vectors_x86_64.S
 delete mode 100644 plat/kvm/x86/cpu_x86_64.c
 create mode 100644 plat/kvm/x86/intctrl.c
 create mode 100644 plat/kvm/x86/traps.c

diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk
index e2299ef..449c381 100644
--- a/plat/kvm/Config.uk
+++ b/plat/kvm/Config.uk
@@ -3,6 +3,7 @@ menuconfig PLAT_KVM
        default n
        depends on (ARCH_X86_64)
        select LIBUKDEBUG
+       select LIBUKALLOC
        select LIBNOLIBC if !HAVE_LIBC
        help
                 Create a Unikraft image that runs as a KVM guest
diff --git a/plat/kvm/Makefile.uk b/plat/kvm/Makefile.uk
index 823e785..46258ff 100644
--- a/plat/kvm/Makefile.uk
+++ b/plat/kvm/Makefile.uk
@@ -16,17 +16,22 @@ LIBKVMPLAT_ASINCLUDES-y        += 
-I$(UK_PLAT_COMMON_BASE)/include
 LIBKVMPLAT_CINCLUDES-y         += -I$(LIBKVMPLAT_BASE)/include
 LIBKVMPLAT_CINCLUDES-y         += -I$(UK_PLAT_COMMON_BASE)/include
 
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/trace.c|common
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/x86/traps.c|common
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += 
$(UK_PLAT_COMMON_BASE)/x86/cpu_native.c|common
 ifeq ($(HAVE_SCHED),y)
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += 
$(UK_PLAT_COMMON_BASE)/x86/thread_start.S|common
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/thread.c|common
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(UK_PLAT_COMMON_BASE)/sw_ctx.c|common
 endif
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/entry64.S
-LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/cpu_x86_64.c
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/traps.c
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/cpu_vectors_x86_64.S
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/setup.c
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/console.c
 LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/lcpu.c
-LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/time.c
+LIBKVMPLAT_SRCS-$(ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/intctrl.c
 LIBKVMPLAT_SRCS-y              += $(LIBKVMPLAT_BASE)/shutdown.c
 LIBKVMPLAT_SRCS-y              += $(LIBKVMPLAT_BASE)/memory.c
+LIBKVMPLAT_SRCS-y              += $(LIBKVMPLAT_BASE)/irq.c
 LIBKVMPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
diff --git a/plat/kvm/include/kvm-x86/cpu_x86_64.h 
b/plat/kvm/include/kvm-x86/cpu_x86_64.h
deleted file mode 100644
index 427c705..0000000
--- a/plat/kvm/include/kvm-x86/cpu_x86_64.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/*
- * Authors: Martin Lucina
- *
- * Copyright (c) 2016-2017 Docker, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted, provided
- * that the above copyright notice and this permission notice appear
- * in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <inttypes.h>
-
-/* accessing devices via port space */
-static inline void outb(uint16_t port, uint8_t v)
-{
-       __asm__ __volatile__("outb %0,%1" : : "a"(v), "dN"(port));
-}
-
-static inline void outw(uint16_t port, uint16_t v)
-{
-       __asm__ __volatile__("outw %0,%1" : : "a"(v), "dN"(port));
-}
-static inline uint8_t inb(uint16_t port)
-{
-       uint8_t v;
-
-       __asm__ __volatile__("inb %1,%0" : "=a"(v) : "dN"(port));
-       return v;
-}
-
-void cpu_halt(void) __attribute__((noreturn));
-void cpu_init(void);
diff --git a/plat/kvm/include/kvm-x86/cpu_x86_64_defs.h 
b/plat/kvm/include/kvm-x86/cpu_x86_64_defs.h
deleted file mode 100644
index 985f8d3..0000000
--- a/plat/kvm/include/kvm-x86/cpu_x86_64_defs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/*
- * Authors: Martin Lucina
- *
- * Copyright (c) 2016-2017 Docker, Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted, provided
- * that the above copyright notice and this permission notice appear
- * in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <x86/cpu_defs.h>
-
-/*
- * GDT layout
- *
- * This should be kept consistent with the layout used by the ukvm target (as
- * defined in ukvm/ukvm_cpu_x86_64.h.
- */
-#define GDT_DESC_NULL           0
-#define GDT_DESC_CODE           1
-#define GDT_DESC_CODE32         2 /* Used by boot.S on virtio targets */
-#define GDT_DESC_DATA           3
-#define GDT_DESC_TSS_LO         4
-#define GDT_DESC_TSS_HI         5
-#define GDT_DESC_TSS            GDT_DESC_TSS_LO
-
-#define GDT_DESC_OFFSET(n)      ((n) * 0x8)
-#define GDT_NUM_ENTRIES         6
-
-#define GDT_DESC_CODE_VAL       0x00af99000000ffff
-#define GDT_DESC_DATA_VAL       0x00cf93000000ffff
diff --git a/plat/kvm/include/kvm-x86/traps.h b/plat/kvm/include/kvm-x86/traps.h
new file mode 100644
index 0000000..8210613
--- /dev/null
+++ b/plat/kvm/include/kvm-x86/traps.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Authors: Martin Lucina
+ *
+ * Copyright (c) 2016-2017 Docker, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <x86/traps.h>
+
+/*
+ * GDT layout
+ *
+ * This should be kept consistent with the layout used by the ukvm target (as
+ * defined in ukvm/ukvm_cpu_x86_64.h.
+ */
+#define GDT_DESC_NULL           0
+#define GDT_DESC_CODE           1
+#define GDT_DESC_CODE32         2 /* Used by boot.S on virtio targets */
+#define GDT_DESC_DATA           3
+#define GDT_DESC_TSS_LO         4
+#define GDT_DESC_TSS_HI         5
+#define GDT_DESC_TSS            GDT_DESC_TSS_LO
+
+#define GDT_DESC_OFFSET(n)      ((n) * 0x8)
+#define GDT_NUM_ENTRIES         6
+
+#define GDT_DESC_CODE_VAL       0x00af99000000ffff
+#define GDT_DESC_DATA_VAL       0x00cf93000000ffff
+
+
+#define IDT_NUM_ENTRIES         48
diff --git a/plat/kvm/include/kvm/intctrl.h b/plat/kvm/include/kvm/intctrl.h
new file mode 100644
index 0000000..a6ce307
--- /dev/null
+++ b/plat/kvm/include/kvm/intctrl.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+void intctrl_init(void);
+void intctrl_clear_irq(unsigned int irq);
+void intctrl_mask_irq(unsigned int irq);
+void intctrl_ack_irq(unsigned int irq);
diff --git a/plat/kvm/include/kvm/irq.h b/plat/kvm/include/kvm/irq.h
new file mode 100644
index 0000000..750ccd2
--- /dev/null
+++ b/plat/kvm/include/kvm/irq.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#ifndef __KVM_IRQ_H_
+#define __KVM_IRQ_H_
+
+#include <sys/types.h>
+#include <uk/plat/irq.h>
+
+void _ukplat_irq_handle(unsigned long irq);
+
+#endif /* __KVM_IRQ_H_ */
diff --git a/plat/kvm/irq.c b/plat/kvm/irq.c
new file mode 100644
index 0000000..b3d8aaa
--- /dev/null
+++ b/plat/kvm/irq.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Authors: Dan Williams
+ *          Martin Lucina
+ *          Ricardo Koller
+ *          Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2015-2017 IBM
+ * Copyright (c) 2016-2017 Docker, Inc.
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Taken from solo5 intr.c */
+
+#include <stdlib.h>
+#include <uk/alloc.h>
+#include <uk/list.h>
+#include <uk/plat/lcpu.h>
+#include <x86/cpu.h>
+#include <kvm/irq.h>
+#include <kvm/intctrl.h>
+#include <uk/assert.h>
+#include <errno.h>
+
+
+static struct uk_alloc *allocator;
+
+struct irq_handler {
+       irq_handler_func_t func;
+       void *arg;
+
+       UK_SLIST_ENTRY(struct irq_handler) entries;
+};
+
+UK_SLIST_HEAD(irq_handler_head, struct irq_handler);
+static struct irq_handler_head irq_handlers[16];
+
+int ukplat_irq_register(unsigned long irq, irq_handler_func_t func, void *arg)
+{
+       struct irq_handler *h;
+       unsigned long flags;
+
+       UK_ASSERT(irq < 16);
+       UK_ASSERT(allocator != NULL);
+
+       h = uk_malloc(allocator, sizeof(struct irq_handler));
+       if (!h)
+               return -ENOMEM;
+
+       h->func = func;
+       h->arg = arg;
+
+       flags = ukplat_lcpu_save_irqf();
+       UK_SLIST_INSERT_HEAD(&irq_handlers[irq], h, entries);
+       ukplat_lcpu_restore_irqf(flags);
+
+       intctrl_clear_irq(irq);
+       return 0;
+}
+
+void _ukplat_irq_handle(unsigned long irq)
+{
+       struct irq_handler *h;
+       int handled = 0;
+
+       UK_SLIST_FOREACH(h, &irq_handlers[irq], entries) {
+               if (h->func(h->arg) == 1) {
+                       handled = 1;
+                       break;
+               }
+       }
+
+       if (!handled)
+               UK_CRASH("Unhandled irq=%lu\n", irq);
+       else
+               /* Only ACK the IRQ if handled; we only need to know
+                * about an unhandled IRQ the first time round.
+                */
+               intctrl_ack_irq(irq);
+}
+
+int ukplat_irq_init(struct uk_alloc *a)
+{
+       UK_ASSERT(allocator == NULL);
+       allocator = a;
+       return 0;
+}
diff --git a/plat/kvm/shutdown.c b/plat/kvm/shutdown.c
index 673d065..a513df9 100644
--- a/plat/kvm/shutdown.c
+++ b/plat/kvm/shutdown.c
@@ -26,6 +26,8 @@
 #include <uk/print.h>
 #include <uk/plat/bootstrap.h>
 
+static void cpu_halt(void) __noreturn;
+
 /* TODO: implement CPU reset */
 void ukplat_terminate(enum ukplat_gstate request __unused)
 {
@@ -45,6 +47,13 @@ void ukplat_terminate(enum ukplat_gstate request __unused)
        cpu_halt();
 }
 
+static void cpu_halt(void)
+{
+       __asm__ __volatile__("cli; hlt");
+       for (;;)
+               ;
+}
+
 int ukplat_suspend(void)
 {
        return -EBUSY;
diff --git a/plat/kvm/x86/cpu_vectors_x86_64.S 
b/plat/kvm/x86/cpu_vectors_x86_64.S
new file mode 100644
index 0000000..1af2fd0
--- /dev/null
+++ b/plat/kvm/x86/cpu_vectors_x86_64.S
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Authors: Dan Williams
+ *          Martin Lucina
+ *          Costin Lupu <costin.lupu@xxxxxxxxx>
+ *
+ * Copyright (c) 2015-2017 IBM
+ * Copyright (c) 2016-2017 Docker, Inc.
+ * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Taken from solo5 */
+
+#include <x86/traps.h>
+#include <x86/regs.h>
+
+#define ENTRY(X)     .global X ; .type X, @function ; X:
+
+.macro PUSH_CALLER_SAVE
+       pushq %rdi
+       pushq %rsi
+       pushq %rdx
+       pushq %rcx
+       pushq %rax
+       pushq %r8
+       pushq %r9
+       pushq %r10
+       pushq %r11
+       pushq %rbx
+       pushq %rbp
+       pushq %r12
+       pushq %r13
+       pushq %r14
+       pushq %r15
+.endm
+
+.macro POP_CALLER_SAVE
+       popq %r15
+       popq %r14
+       popq %r13
+       popq %r12
+       popq %rbp
+       popq %rbx
+       popq %r11
+       popq %r10
+       popq %r9
+       popq %r8
+       popq %rax
+       popq %rcx
+       popq %rdx
+       popq %rsi
+       popq %rdi
+.endm
+
+.macro TRAP_ENTRY trapname, has_ec
+ENTRY(ASM_TRAP_SYM(\trapname))
+       cld
+
+.if !\has_ec
+       pushq $0                            /* no error code, pass 0 */
+.endif
+       PUSH_CALLER_SAVE
+       subq $REGS_PAD_SIZE, %rsp           /* we have some padding */
+
+       movq %rsp, %rdi
+       movq OFFSETOF_REGS_ORIG_RAX(%rsp), %rsi
+       call do_\trapname
+
+       addq $REGS_PAD_SIZE, %rsp           /* we have some padding */
+       POP_CALLER_SAVE
+       addq $8, %rsp                       /* discard error code */
+
+       iretq
+.endm
+
+.macro IRQ_ENTRY irqno
+ENTRY(cpu_irq_\irqno)
+       cld
+
+       pushq $0                            /* no error code */
+       PUSH_CALLER_SAVE
+       subq $REGS_PAD_SIZE, %rsp           /* we have some padding */
+
+       movq $\irqno, %rdi
+       call _ukplat_irq_handle
+
+       addq $REGS_PAD_SIZE, %rsp           /* we have some padding */
+       POP_CALLER_SAVE
+       addq $8, %rsp
+
+       iretq
+.endm
+
+TRAP_ENTRY divide_error,     0
+TRAP_ENTRY debug,            0
+TRAP_ENTRY nmi,              0
+TRAP_ENTRY int3,             0
+TRAP_ENTRY overflow,         0
+TRAP_ENTRY bounds,           0
+TRAP_ENTRY invalid_op,       0
+TRAP_ENTRY no_device,        0
+TRAP_ENTRY double_fault,     1
+TRAP_ENTRY invalid_tss,      1
+TRAP_ENTRY no_segment,       1
+TRAP_ENTRY stack_error,      1
+TRAP_ENTRY gp_fault,         1
+TRAP_ENTRY page_fault,       1
+TRAP_ENTRY coproc_error,     0
+TRAP_ENTRY alignment_check,  1
+TRAP_ENTRY machine_check,    0
+TRAP_ENTRY simd_error,       0
+TRAP_ENTRY virt_error,       0
+
+IRQ_ENTRY 0
+IRQ_ENTRY 1
+IRQ_ENTRY 2
+IRQ_ENTRY 3
+IRQ_ENTRY 4
+IRQ_ENTRY 5
+IRQ_ENTRY 6
+IRQ_ENTRY 7
+IRQ_ENTRY 8
+IRQ_ENTRY 9
+IRQ_ENTRY 10
+IRQ_ENTRY 11
+IRQ_ENTRY 12
+IRQ_ENTRY 13
+IRQ_ENTRY 14
+IRQ_ENTRY 15
diff --git a/plat/kvm/x86/cpu_x86_64.c b/plat/kvm/x86/cpu_x86_64.c
deleted file mode 100644
index 2f98b95..0000000
--- a/plat/kvm/x86/cpu_x86_64.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: ISC */
-/*
- * Authors: Dan Williams
- *          Martin Lucina
- *          Felipe Huici <felipe.huici@xxxxxxxxx>
- *          Florian Schmidt <florian.schmidt@xxxxxxxxx>
- *
- * Copyright (c) 2015-2017 IBM
- * Copyright (c) 2016-2017 Docker, Inc.
- * Copyright (c) 2017 NEC Europe Ltd., NEC Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software
- * for any purpose with or without fee is hereby granted, provided
- * that the above copyright notice and this permission notice appear
- * in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <string.h>
-#include <x86/desc.h>
-#include <kvm/setup.h>
-#include <kvm-x86/cpu_x86_64_defs.h>
-#include <kvm-x86/cpu_x86_64.h>
-
-static struct seg_desc32 cpu_gdt64[GDT_NUM_ENTRIES] ALIGN_64_BIT;
-
-/*
- * The monitor (ukvm) or bootloader + bootstrap (virtio) starts us up with a
- * bootstrap GDT which is "invisible" to the guest, init and switch to our own
- * GDT.
- *
- * This is done primarily since we need to do LTR later in a predictable
- * fashion.
- */
-static void gdt_init(void)
-{
-       volatile struct desc_table_ptr64 gdtptr;
-
-       memset(cpu_gdt64, 0, sizeof(cpu_gdt64));
-       cpu_gdt64[GDT_DESC_CODE].raw = GDT_DESC_CODE_VAL;
-       cpu_gdt64[GDT_DESC_DATA].raw = GDT_DESC_DATA_VAL;
-
-       gdtptr.limit = sizeof(cpu_gdt64) - 1;
-       gdtptr.base = (__u64) &cpu_gdt64;
-       __asm__ __volatile__("lgdt (%0)" ::"r"(&gdtptr));
-       /*
-        * TODO: Technically we should reload all segment registers here, in
-        * practice this doesn't matter since the bootstrap GDT matches ours,
-        * for now.
-        */
-}
-
-void cpu_init(void)
-{
-       gdt_init();
-}
-
-void cpu_halt(void)
-{
-       __asm__ __volatile__("cli; hlt");
-       for (;;)
-               ;
-}
diff --git a/plat/kvm/x86/entry64.S b/plat/kvm/x86/entry64.S
index 1a10359..35738b6 100644
--- a/plat/kvm/x86/entry64.S
+++ b/plat/kvm/x86/entry64.S
@@ -28,6 +28,7 @@
  */
 
 #include <x86/cpu_defs.h>
+#include <kvm-x86/traps.h>
 #include <kvm-x86/multiboot_defs.h>
 
 #define ENTRY(x) .globl x; .type x,%function; x:
diff --git a/plat/kvm/x86/intctrl.c b/plat/kvm/x86/intctrl.c
new file mode 100644
index 0000000..dc40555
--- /dev/null
+++ b/plat/kvm/x86/intctrl.c
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Authors: Dan Williams
+ *          Martin Lucina
+ *
+ * Copyright (c) 2015-2017 IBM
+ * Copyright (c) 2016-2017 Docker, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Taken from solo5 platform_intr.c */
+
+#include <stdint.h>
+#include <x86/cpu.h>
+#include <kvm/intctrl.h>
+
+#define PIC1             0x20    /* IO base address for master PIC */
+#define PIC2             0xA0    /* IO base address for slave PIC */
+#define PIC1_COMMAND     PIC1
+#define PIC1_DATA        (PIC1 + 1)
+#define PIC2_COMMAND     PIC2
+#define PIC2_DATA        (PIC2 + 1)
+#define IRQ_ON_MASTER(n) ((n) < 8)
+#define IRQ_PORT(n)      (IRQ_ON_MASTER(n) ? PIC1_DATA : PIC2_DATA)
+#define IRQ_OFFSET(n)    (IRQ_ON_MASTER(n) ? (n) : ((n) - 8))
+
+#define PIC_EOI          0x20 /* End-of-interrupt command code */
+#define ICW1_ICW4        0x01 /* ICW4 (not) needed */
+#define ICW1_SINGLE      0x02 /* Single (cascade) mode */
+#define ICW1_INTERVAL    0x04 /* Call address interval 4 (8) */
+#define ICW1_LEVEL       0x08 /* Level triggered (edge) mode */
+#define ICW1_INIT        0x10 /* Initialization - required! */
+#define ICW4_8086        0x01 /* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO        0x02 /* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE   0x08 /* Buffered mode/slave */
+#define ICW4_BUF_MASTER  0x0C /* Buffered mode/master */
+#define ICW4_SFN         0x10 /* Special fully nested (not) */
+
+/*
+ * arguments:
+ * offset1 - vector offset for master PIC vectors on the master become
+ *           offset1..offset1+7
+ * offset2 - same for slave PIC: offset2..offset2+7
+ */
+static void PIC_remap(int offset1, int offset2)
+{
+       unsigned char a1, a2;
+
+       /* save masks */
+       a1 = inb(PIC1_DATA);
+       a2 = inb(PIC2_DATA);
+
+       /* start init seq (cascade) */
+       outb(PIC1_COMMAND, ICW1_INIT + ICW1_ICW4);
+       outb(PIC2_COMMAND, ICW1_INIT + ICW1_ICW4);
+       /* ICW2: Master PIC vector off */
+       outb(PIC1_DATA, offset1);
+       /* ICW2: Slave PIC vector off */
+       outb(PIC2_DATA, offset2);
+       /* ICW3: tell Master PIC there is a slave PIC at IRQ2 (0000 0100) */
+       outb(PIC1_DATA, 4);
+       /* ICW3: tell Slave PIC its cascade identity (0000 0010) */
+       outb(PIC2_DATA, 2);
+
+       outb(PIC1_DATA, ICW4_8086);
+       outb(PIC2_DATA, ICW4_8086);
+
+       outb(PIC1_DATA, a1); /* restore saved masks. */
+       outb(PIC2_DATA, a2);
+}
+
+void intctrl_init(void)
+{
+       PIC_remap(32, 40);
+}
+
+void intctrl_ack_irq(unsigned int irq)
+{
+       if (!IRQ_ON_MASTER(irq))
+               outb(PIC2_COMMAND, PIC_EOI);
+
+       outb(PIC1_COMMAND, PIC_EOI);
+}
+
+void intctrl_mask_irq(unsigned int irq)
+{
+       __u16 port;
+
+       port = IRQ_PORT(irq);
+       outb(port, inb(port) | (1 << IRQ_OFFSET(irq)));
+}
+
+void intctrl_clear_irq(unsigned int irq)
+{
+       __u16 port;
+
+       port = IRQ_PORT(irq);
+       outb(port, inb(port) & ~(1 << IRQ_OFFSET(irq)));
+}
diff --git a/plat/kvm/x86/lcpu.c b/plat/kvm/x86/lcpu.c
index 985c670..42e2faa 100644
--- a/plat/kvm/x86/lcpu.c
+++ b/plat/kvm/x86/lcpu.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
  * Authors: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *          Costin Lupu <costin.lupu@xxxxxxxxx>
  *
  * Copyright (c) 2017, NEC Europe Ltd., NEC Corporation. All rights reserved.
  *
@@ -34,3 +35,39 @@
 
 #include <stdint.h>
 #include <uk/plat/lcpu.h>
+#include <x86/irq.h>
+
+
+void ukplat_lcpu_enable_irq(void)
+{
+       local_irq_enable();
+}
+
+void ukplat_lcpu_disable_irq(void)
+{
+       local_irq_disable();
+}
+
+unsigned long ukplat_lcpu_save_irqf(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       return flags;
+}
+
+void ukplat_lcpu_restore_irqf(unsigned long flags)
+{
+       local_irq_restore(flags);
+}
+
+int ukplat_lcpu_irqs_disabled(void)
+{
+       return irqs_disabled();
+}
+
+void ukplat_lcpu_irqs_handle_pending(void)
+{
+
+}
diff --git a/plat/kvm/x86/setup.c b/plat/kvm/x86/setup.c
index 3b13313..f1196ef 100644
--- a/plat/kvm/x86/setup.c
+++ b/plat/kvm/x86/setup.c
@@ -27,10 +27,11 @@
  */
 
 #include <string.h>
+#include <x86/traps.h>
 #include <kvm/console.h>
+#include <kvm/intctrl.h>
 #include <kvm-x86/multiboot.h>
 #include <kvm-x86/multiboot_defs.h>
-#include <kvm-x86/cpu_x86_64.h>
 #include <uk/arch/limits.h>
 #include <uk/arch/types.h>
 #include <uk/plat/console.h>
@@ -134,7 +135,8 @@ void _libkvmplat_entry(void *arg)
 
        _libkvmplat_init_console();
        _init_cpufeatures();
-       cpu_init();
+       traps_init();
+       intctrl_init();
 
        uk_printd(DLVL_INFO, "Entering from KVM (x86)...\n");
        uk_printd(DLVL_INFO, "     multiboot: %p\n", mi);
diff --git a/plat/kvm/x86/traps.c b/plat/kvm/x86/traps.c
new file mode 100644
index 0000000..27ef6d9
--- /dev/null
+++ b/plat/kvm/x86/traps.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Authors: Dan Williams
+ *          Martin Lucina
+ *          Felipe Huici <felipe.huici@xxxxxxxxx>
+ *          Florian Schmidt <florian.schmidt@xxxxxxxxx>
+ *
+ * Copyright (c) 2015-2017 IBM
+ * Copyright (c) 2016-2017 Docker, Inc.
+ * Copyright (c) 2017 NEC Europe Ltd., NEC Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software
+ * for any purpose with or without fee is hereby granted, provided
+ * that the above copyright notice and this permission notice appear
+ * in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+#include <uk/arch/lcpu.h>
+#include <x86/desc.h>
+#include <kvm-x86/traps.h>
+
+static struct seg_desc32 cpu_gdt64[GDT_NUM_ENTRIES] __align64b;
+
+/*
+ * The monitor (ukvm) or bootloader + bootstrap (virtio) starts us up with a
+ * bootstrap GDT which is "invisible" to the guest, init and switch to our own
+ * GDT.
+ *
+ * This is done primarily since we need to do LTR later in a predictable
+ * fashion.
+ */
+static void gdt_init(void)
+{
+       volatile struct desc_table_ptr64 gdtptr;
+
+       memset(cpu_gdt64, 0, sizeof(cpu_gdt64));
+       cpu_gdt64[GDT_DESC_CODE].raw = GDT_DESC_CODE_VAL;
+       cpu_gdt64[GDT_DESC_DATA].raw = GDT_DESC_DATA_VAL;
+
+       gdtptr.limit = sizeof(cpu_gdt64) - 1;
+       gdtptr.base = (__u64) &cpu_gdt64;
+       __asm__ __volatile__("lgdt (%0)" ::"r"(&gdtptr));
+       /*
+        * TODO: Technically we should reload all segment registers here, in
+        * practice this doesn't matter since the bootstrap GDT matches ours,
+        * for now.
+        */
+}
+
+static struct tss64 cpu_tss;
+
+static char cpu_intr_stack[4096]; /* IST1 */
+static char cpu_trap_stack[4096]; /* IST2 */
+static char cpu_nmi_stack[4096];  /* IST3 */
+
+static void tss_init(void)
+{
+       struct seg_desc64 *td = (void *) &cpu_gdt64[GDT_DESC_TSS_LO];
+
+       cpu_tss.ist[0] = (__u64) &cpu_intr_stack[sizeof(cpu_intr_stack)];
+       cpu_tss.ist[1] = (__u64) &cpu_trap_stack[sizeof(cpu_trap_stack)];
+       cpu_tss.ist[2] = (__u64) &cpu_nmi_stack[sizeof(cpu_nmi_stack)];
+
+       td->limit_lo = sizeof(cpu_tss);
+       td->base_lo = (__u64) &cpu_tss;
+       td->type = 0x9;
+       td->zero = 0;
+       td->dpl = 0;
+       td->p = 1;
+       td->limit_hi = 0;
+       td->gran = 0;
+       td->base_hi = (__u64) &cpu_tss >> 24;
+       td->zero1 = 0;
+
+       barrier();
+       __asm__ __volatile__(
+               "ltr %0"
+               :
+               : "r" ((unsigned short) (GDT_DESC_TSS_LO * 8))
+       );
+}
+
+
+/* Declare the traps used only by this platform: */
+DECLARE_TRAP_EC(nmi,           "NMI")
+DECLARE_TRAP_EC(double_fault,  "double fault")
+DECLARE_TRAP_EC(virt_error,    "virtualization error")
+
+
+static struct seg_gate_desc64 cpu_idt[IDT_NUM_ENTRIES] __align64b;
+
+static void idt_fillgate(unsigned int num, void *fun, unsigned int ist)
+{
+       struct seg_gate_desc64 *desc = &cpu_idt[num];
+
+       /*
+        * All gates are interrupt gates, all handlers run with interrupts off.
+        */
+       desc->offset_hi = (__u64) fun >> 16;
+       desc->offset_lo = (__u64) fun & 0xffff;
+       desc->selector = GDT_DESC_OFFSET(GDT_DESC_CODE);
+       desc->ist = ist;
+       desc->type = 14; /* == 0b1110 */
+       desc->dpl = 0;
+       desc->p = 1;
+}
+
+volatile struct desc_table_ptr64 idtptr;
+
+static void idt_init(void)
+{
+       /*
+        * Load trap vectors. All traps run on IST2 (cpu_trap_stack), except for
+        * the exceptions.
+        */
+#define FILL_TRAP_GATE(name, ist) extern void cpu_trap_##name(void); \
+       idt_fillgate(TRAP_##name, ASM_TRAP_SYM(name), ist)
+       FILL_TRAP_GATE(divide_error,    2);
+       FILL_TRAP_GATE(debug,           2);
+       FILL_TRAP_GATE(nmi,             3); /* #NMI runs on IST3 
(cpu_nmi_stack) */
+       FILL_TRAP_GATE(int3,            2);
+       FILL_TRAP_GATE(overflow,        2);
+       FILL_TRAP_GATE(bounds,          2);
+       FILL_TRAP_GATE(invalid_op,      2);
+       FILL_TRAP_GATE(no_device,       2);
+       FILL_TRAP_GATE(double_fault,    3); /* #DF runs on IST3 (cpu_nmi_stack) 
*/
+
+       FILL_TRAP_GATE(invalid_tss,     2);
+       FILL_TRAP_GATE(no_segment,      2);
+       FILL_TRAP_GATE(stack_error,     2);
+       FILL_TRAP_GATE(gp_fault,        2);
+       FILL_TRAP_GATE(page_fault,      2);
+
+       FILL_TRAP_GATE(coproc_error,    2);
+       FILL_TRAP_GATE(alignment_check, 2);
+       FILL_TRAP_GATE(machine_check,   2);
+       FILL_TRAP_GATE(simd_error,      2);
+       FILL_TRAP_GATE(virt_error,      2);
+
+       /*
+        * Load irq vectors. All irqs run on IST1 (cpu_intr_stack).
+        */
+#define FILL_IRQ_GATE(num, ist) extern void cpu_irq_##num(void); \
+       idt_fillgate(32 + num, cpu_irq_##num, ist)
+       FILL_IRQ_GATE(0, 1);
+       FILL_IRQ_GATE(1, 1);
+       FILL_IRQ_GATE(2, 1);
+       FILL_IRQ_GATE(3, 1);
+       FILL_IRQ_GATE(4, 1);
+       FILL_IRQ_GATE(5, 1);
+       FILL_IRQ_GATE(6, 1);
+       FILL_IRQ_GATE(7, 1);
+       FILL_IRQ_GATE(8, 1);
+       FILL_IRQ_GATE(9, 1);
+       FILL_IRQ_GATE(10, 1);
+       FILL_IRQ_GATE(11, 1);
+       FILL_IRQ_GATE(12, 1);
+       FILL_IRQ_GATE(13, 1);
+       FILL_IRQ_GATE(14, 1);
+       FILL_IRQ_GATE(15, 1);
+
+       idtptr.limit = sizeof(cpu_idt) - 1;
+       idtptr.base = (__u64) &cpu_idt;
+       __asm__ __volatile__("lidt (%0)" :: "r" (&idtptr));
+}
+
+void traps_init(void)
+{
+       gdt_init();
+       tss_init();
+       idt_init();
+}
+
+void traps_fini(void)
+{
+}
-- 
2.7.4


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

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