From: Stefano Stabellini Date: Wed, 28 Sep 2011 16:14:58 +0000 (+0100) Subject: xen: initial ARM support X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=fecca8f9d44746a43e72974db41141bdee4d59ff;p=people%2Fsstabellini%2Flinux-pvhvm-deprecated.git xen: initial ARM support Signed-off-by: Stefano Stabellini --- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 776d76b8cb6..01ab7cb8dcb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2201,6 +2201,12 @@ config NEON Say Y to include support code for NEON, the ARMv7 Advanced SIMD Extension. +config XEN + bool "Xen guest support on ARM" + depends on ARM + help + Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. + endmenu menu "Userspace binary formats" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index dfcf3b033e1..e2e6c3b5d36 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -252,6 +252,7 @@ endif core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) core-$(CONFIG_VFP) += arch/arm/vfp/ +core-$(CONFIG_XEN) += arch/arm/xen/ # If we have a machine-specific directory, then include it in the build. core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h new file mode 100644 index 00000000000..efa7c61598d --- /dev/null +++ b/arch/arm/include/asm/xen/events.h @@ -0,0 +1,9 @@ +#ifndef _ASM_ARM_XEN_EVENTS_H +#define _ASM_ARM_XEN_EVENTS_H + +enum ipi_vector { + /* Xen IPIs go here */ + XEN_NR_IPIS, +}; + +#endif /* _ASM_ARM_XEN_EVENTS_H */ diff --git a/arch/arm/include/asm/xen/grant_table.h b/arch/arm/include/asm/xen/grant_table.h new file mode 100644 index 00000000000..4e3f7b2a168 --- /dev/null +++ b/arch/arm/include/asm/xen/grant_table.h @@ -0,0 +1,7 @@ +#ifndef _ASM_ARM_XEN_GRANT_TABLE_H +#define _ASM_ARM_XEN_GRANT_TABLE_H + +#define xen_alloc_vm_area(size) alloc_vm_area(size) +#define xen_free_vm_area(area) free_vm_area(area) + +#endif /* _ASM_ARM_XEN_GRANT_TABLE_H */ diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h new file mode 100644 index 00000000000..7cf1d614f82 --- /dev/null +++ b/arch/arm/include/asm/xen/hypercall.h @@ -0,0 +1,195 @@ +/****************************************************************************** + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * Stefano Stabellini , Citrix, 2011 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _ASM_ARM_XEN_HYPERCALL_H +#define _ASM_ARM_XEN_HYPERCALL_H + +#define __HYPERCALL_RETREG "r0" +#define __HYPERCALL_ARG1REG "r0" +#define __HYPERCALL_ARG2REG "r1" +#define __HYPERCALL_ARG3REG "r2" +#define __HYPERCALL_ARG4REG "r3" +#define __HYPERCALL_ARG5REG "r4" + +#define __HYPERCALL_DECLS \ + register unsigned long __res asm(__HYPERCALL_RETREG); \ + register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \ + register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \ + register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \ + register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \ + register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; + +#define __HYPERCALL_0PARAM "=r" (__res) +#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1) +#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2) +#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3) +#define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4) +#define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5) + +#define __HYPERCALL_0ARG() +#define __HYPERCALL_1ARG(a1) \ + __HYPERCALL_0ARG() __arg1 = (unsigned long)(a1); +#define __HYPERCALL_2ARG(a1,a2) \ + __HYPERCALL_1ARG(a1) __arg2 = (unsigned long)(a2); +#define __HYPERCALL_3ARG(a1,a2,a3) \ + __HYPERCALL_2ARG(a1,a2) __arg3 = (unsigned long)(a3); +#define __HYPERCALL_4ARG(a1,a2,a3,a4) \ + __HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4); +#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \ + __HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5); + +#define __HYPERCALL_CLOBBER5 "memory" +#define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG +#define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG +#define __HYPERCALL_CLOBBER2 __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG +#define __HYPERCALL_CLOBBER1 __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG +#define __HYPERCALL_CLOBBER0 __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG + +#define _hypercall0(type, number) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_0ARG(); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_0PARAM \ + : \ + : __HYPERCALL_CLOBBER0); \ + (type)__res; \ +}) + +#define _hypercall1(type, number, a1) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_1ARG(a1); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_1PARAM \ + : \ + : __HYPERCALL_CLOBBER1); \ + (type)__res; \ +}) + +#define _hypercall2(type, number, a1, a2) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_2ARG(a1, a2); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_2PARAM \ + : \ + : __HYPERCALL_CLOBBER2); \ + (type)__res; \ +}) + +#define _hypercall3(type, number, a1, a2, a3) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_3ARG(a1, a2, a3); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_3PARAM \ + : \ + : __HYPERCALL_CLOBBER3); \ + (type)__res; \ +}) + +#define _hypercall4(type, number, a1, a2, a3, a4) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_4ARG(a1, a2, a3, a4); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_4PARAM \ + : \ + : __HYPERCALL_CLOBBER4); \ + (type)__res; \ +}) + +#define _hypercall5(type, number, a1, a2, a3, a4, a5) \ +({ \ + __HYPERCALL_DECLS; \ + __HYPERCALL_5ARG(a1, a2, a3, a4, a5); \ + asm volatile (__HYPERCALL \ + : __HYPERCALL_5PARAM \ + : \ + : __HYPERCALL_CLOBBER5); \ + (type)__res; \ +}) + + + +/* -- Hypercall definitions go below -- */ + +#define __HYPERCALL ".word 0xe1400171" /* hypercall number 0x11 */ +static inline int +HYPERVISOR_xen_version(int cmd, void *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); +} +#undef __HYPERCALL + +#define __HYPERCALL ".word 0xe1400172" /* hypercall number 0x12 */ +static inline int +HYPERVISOR_console_io(int cmd, int count, char *str) +{ + return _hypercall3(int, __HYPERVISOR_console_io, cmd, count, str); +} +#undef __HYPERCALL + +#define __HYPERCALL ".word 0xe1400174" /* hypercall number 0x14 */ +static inline int +HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) +{ + return _hypercall3(int, grant_table_op, cmd, uop, count); +} +#undef __HYPERCALL + +#define __HYPERCALL ".word 0xe140017d" /* hypercall number 0x1d */ +static inline int +HYPERVISOR_sched_op(int cmd, void *arg) +{ + return _hypercall2(int, sched_op, cmd, arg); +} +#undef __HYPERCALL + +#define __HYPERCALL ".word 0xe1400270" /* hypercall number 0x20 */ +static inline int +HYPERVISOR_event_channel_op(int cmd, void *arg) +{ + int rc = _hypercall2(int, event_channel_op, cmd, arg); + if (unlikely(rc == -ENOSYS)) { + struct evtchn_op op; + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, event_channel_op_compat, &op); + memcpy(arg, &op.u, sizeof(op.u)); + } + return rc; +} +#undef __HYPERCALL + +#endif /* _ASM_ARM_XEN_HYPERCALL_H */ diff --git a/arch/arm/include/asm/xen/hypervisor.h b/arch/arm/include/asm/xen/hypervisor.h new file mode 100644 index 00000000000..2470f53fe28 --- /dev/null +++ b/arch/arm/include/asm/xen/hypervisor.h @@ -0,0 +1,7 @@ +#ifndef _ASM_ARM_XEN_HYPERVISOR_H +#define _ASM_ARM_XEN_HYPERVISOR_H + +extern struct shared_info *HYPERVISOR_shared_info; +extern struct start_info *xen_start_info; + +#endif /* _ASM_ARM_XEN_HYPERVISOR_H */ diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h new file mode 100644 index 00000000000..93b0139d672 --- /dev/null +++ b/arch/arm/include/asm/xen/interface.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * Guest OS interface to ARM Xen. + * + * Stefano Stabellini , Citrix, 2011 + */ + +#ifndef _ASM_ARM_XEN_INTERFACE_H +#define _ASM_ARM_XEN_INTERFACE_H + +#include + +#ifdef __XEN__ +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name +#else +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef type * __guest_handle_ ## name +#endif + +#define DEFINE_GUEST_HANDLE_STRUCT(name) \ + __DEFINE_GUEST_HANDLE(name, struct name) +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name + +#ifdef __XEN__ +#define set_xen_guest_handle(hnd, val) \ + do { \ + if (sizeof(hnd) == 8) \ + *(uint64_t *)&(hnd) = 0; \ + (hnd).p = val; \ + } while (0) +#endif + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +__DEFINE_GUEST_HANDLE(ulong, unsigned long); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(long); +DEFINE_GUEST_HANDLE(void); +#endif + +/* Maximum number of virtual CPUs in multi-processor guests. */ +#define MAX_VIRT_CPUS 32 + +struct arch_vcpu_info { + unsigned long cr2; + unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ +}; + +struct arch_shared_info { + unsigned long max_pfn; /* max pfn that appears in table */ + /* Frame containing list of mfns containing list of mfns containing p2m. */ + unsigned long pfn_to_mfn_frame_list_list; + unsigned long nmi_reason; +}; + +/* XXX: Move pvclock definitions some place arch independent */ +struct pvclock_vcpu_time_info { + u32 version; + u32 pad0; + u64 tsc_timestamp; + u64 system_time; + u32 tsc_to_system_mul; + s8 tsc_shift; + u8 flags; + u8 pad[2]; +} __attribute__((__packed__)); /* 32 bytes */ + +struct pvclock_wall_clock { + u32 version; + u32 sec; + u32 nsec; +} __attribute__((__packed__)); + +#endif /* _ASM_ARM_XEN_INTERFACE_H */ diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h new file mode 100644 index 00000000000..17bfb55d2ef --- /dev/null +++ b/arch/arm/include/asm/xen/page.h @@ -0,0 +1,8 @@ +#ifndef _ASM_ARM_XEN_PAGE_H +#define _ASM_ARM_XEN_PAGE_H + +#define mfn_to_virt(m) (~0) +#define mfn_to_pfn(m) (~0) +#define pfn_to_mfn(m) (~0) + +#endif /* _ASM_ARM_XEN_PAGE_H */ diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile new file mode 100644 index 00000000000..0bad594b149 --- /dev/null +++ b/arch/arm/xen/Makefile @@ -0,0 +1 @@ +obj-y := enlighten.o diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c new file mode 100644 index 00000000000..39ef68cbc80 --- /dev/null +++ b/arch/arm/xen/enlighten.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +struct start_info *xen_start_info; +EXPORT_SYMBOL_GPL(xen_start_info); + +enum xen_domain_type xen_domain_type = XEN_NATIVE; +EXPORT_SYMBOL_GPL(xen_domain_type); + + +/* TODO: remove these functions below and use the real implementation + * instead + */ +void rebind_evtchn_irq(int evtchn, int irq) +{ +} + +int bind_evtchn_to_irq(unsigned int evtchn) +{ + return 0; +} +EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 52fdf60bdbe..f30579d4282 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include "hvc_console.h" diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 974fffdf22b..7f8f8814bb4 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -1,11 +1,15 @@ +ifeq(CONFIG_X86,y) obj-y += grant-table.o features.o events.o manage.o balloon.o obj-y += xenbus/ +endif nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_features.o := $(nostackp) obj-$(CONFIG_BLOCK) += biomerge.o +ifeq(CONFIG_X86,y) obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o +endif obj-$(CONFIG_XEN_XENCOMM) += xencomm.o obj-$(CONFIG_XEN_BALLOON) += xen-balloon.o obj-$(CONFIG_XEN_SELFBALLOONING) += xen-selfballoon.o diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 6a6e9144934..19354db725d 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h @@ -10,7 +10,10 @@ #define __XEN_PUBLIC_XEN_H__ #include +#include +#ifdef CONFIG_X86 #include +#endif /* * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS).