diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-26 16:42:14 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-26 16:43:35 -0400 |
commit | ae1659ee6b4bf5e12a141d04636a3de89543c237 (patch) | |
tree | 67ca3da7e9461832f9e2cb23fc89b5c7c92ff10d /arch/arm | |
parent | c341ca45ce56143804ef5a8f4db753e554e640b4 (diff) | |
parent | bbd6eb29214e1a278e8575f57d64b88077bebf6d (diff) |
Merge branch 'xenarm-for-linus' of git://xenbits.xen.org/people/sstabellini/linux-pvhvm into stable/for-linus-3.7
* 'xenarm-for-linus' of git://xenbits.xen.org/people/sstabellini/linux-pvhvm:
arm: introduce a DTS for Xen unprivileged virtual machines
MAINTAINERS: add myself as Xen ARM maintainer
xen/arm: compile netback
xen/arm: compile blkfront and blkback
xen/arm: implement alloc/free_xenballooned_pages with alloc_pages/kfree
xen/arm: receive Xen events on ARM
xen/arm: initialize grant_table on ARM
xen/arm: get privilege status
xen/arm: introduce CONFIG_XEN on ARM
xen: do not compile manage, balloon, pci, acpi, pcpu and cpu_hotplug on ARM
xen/arm: Introduce xen_ulong_t for unsigned long
xen/arm: Xen detection and shared_info page mapping
docs: Xen ARM DT bindings
xen/arm: empty implementation of grant_table arch specific functions
xen/arm: sync_bitops
xen/arm: page.h definitions
xen/arm: hypercalls
arm: initial Xen support
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/xenvm-4.2.dts | 68 | ||||
-rw-r--r-- | arch/arm/include/asm/hypervisor.h | 6 | ||||
-rw-r--r-- | arch/arm/include/asm/sync_bitops.h | 27 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/events.h | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/hypercall.h | 69 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/hypervisor.h | 19 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/interface.h | 73 | ||||
-rw-r--r-- | arch/arm/include/asm/xen/page.h | 82 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/Makefile.boot | 3 | ||||
-rw-r--r-- | arch/arm/mach-vexpress/v2m.c | 1 | ||||
-rw-r--r-- | arch/arm/xen/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/xen/enlighten.c | 168 | ||||
-rw-r--r-- | arch/arm/xen/grant-table.c | 53 | ||||
-rw-r--r-- | arch/arm/xen/hypercall.S | 106 |
16 files changed, 704 insertions, 1 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2f88d8d97701..33614669a9a0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1897,6 +1897,16 @@ config DEPRECATED_PARAM_STRUCT | |||
1897 | This was deprecated in 2001 and announced to live on for 5 years. | 1897 | This was deprecated in 2001 and announced to live on for 5 years. |
1898 | Some old boot loaders still use this way. | 1898 | Some old boot loaders still use this way. |
1899 | 1899 | ||
1900 | config XEN_DOM0 | ||
1901 | def_bool y | ||
1902 | depends on XEN | ||
1903 | |||
1904 | config XEN | ||
1905 | bool "Xen guest support on ARM (EXPERIMENTAL)" | ||
1906 | depends on EXPERIMENTAL && ARM && OF | ||
1907 | help | ||
1908 | Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. | ||
1909 | |||
1900 | endmenu | 1910 | endmenu |
1901 | 1911 | ||
1902 | menu "Boot options" | 1912 | menu "Boot options" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 30eae87ead6d..f42968a9fca3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -251,6 +251,7 @@ endif | |||
251 | core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ | 251 | core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ |
252 | core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) | 252 | core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) |
253 | core-$(CONFIG_VFP) += arch/arm/vfp/ | 253 | core-$(CONFIG_VFP) += arch/arm/vfp/ |
254 | core-$(CONFIG_XEN) += arch/arm/xen/ | ||
254 | 255 | ||
255 | # If we have a machine-specific directory, then include it in the build. | 256 | # If we have a machine-specific directory, then include it in the build. |
256 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ | 257 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ |
diff --git a/arch/arm/boot/dts/xenvm-4.2.dts b/arch/arm/boot/dts/xenvm-4.2.dts new file mode 100644 index 000000000000..ec3f9528e180 --- /dev/null +++ b/arch/arm/boot/dts/xenvm-4.2.dts | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * Xen Virtual Machine for unprivileged guests | ||
3 | * | ||
4 | * Based on ARM Ltd. Versatile Express CoreTile Express (single CPU) | ||
5 | * Cortex-A15 MPCore (V2P-CA15) | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /dts-v1/; | ||
10 | |||
11 | / { | ||
12 | model = "XENVM-4.2"; | ||
13 | compatible = "xen,xenvm-4.2", "xen,xenvm"; | ||
14 | interrupt-parent = <&gic>; | ||
15 | #address-cells = <2>; | ||
16 | #size-cells = <2>; | ||
17 | |||
18 | chosen { | ||
19 | /* this field is going to be adjusted by the hypervisor */ | ||
20 | bootargs = "console=hvc0 root=/dev/xvda"; | ||
21 | }; | ||
22 | |||
23 | cpus { | ||
24 | #address-cells = <1>; | ||
25 | #size-cells = <0>; | ||
26 | |||
27 | cpu@0 { | ||
28 | device_type = "cpu"; | ||
29 | compatible = "arm,cortex-a15"; | ||
30 | reg = <0>; | ||
31 | }; | ||
32 | }; | ||
33 | |||
34 | memory@80000000 { | ||
35 | device_type = "memory"; | ||
36 | /* this field is going to be adjusted by the hypervisor */ | ||
37 | reg = <0 0x80000000 0 0x08000000>; | ||
38 | }; | ||
39 | |||
40 | gic: interrupt-controller@2c001000 { | ||
41 | compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; | ||
42 | #interrupt-cells = <3>; | ||
43 | #address-cells = <0>; | ||
44 | interrupt-controller; | ||
45 | reg = <0 0x2c001000 0 0x1000>, | ||
46 | <0 0x2c002000 0 0x100>; | ||
47 | }; | ||
48 | |||
49 | timer { | ||
50 | compatible = "arm,armv7-timer"; | ||
51 | interrupts = <1 13 0xf08>, | ||
52 | <1 14 0xf08>, | ||
53 | <1 11 0xf08>, | ||
54 | <1 10 0xf08>; | ||
55 | }; | ||
56 | |||
57 | hypervisor { | ||
58 | compatible = "xen,xen-4.2", "xen,xen"; | ||
59 | /* this field is going to be adjusted by the hypervisor */ | ||
60 | reg = <0 0xb0000000 0 0x20000>; | ||
61 | /* this field is going to be adjusted by the hypervisor */ | ||
62 | interrupts = <1 15 0xf08>; | ||
63 | }; | ||
64 | |||
65 | motherboard { | ||
66 | arm,v2m-memory-map = "rs1"; | ||
67 | }; | ||
68 | }; | ||
diff --git a/arch/arm/include/asm/hypervisor.h b/arch/arm/include/asm/hypervisor.h new file mode 100644 index 000000000000..b90d9e523d6f --- /dev/null +++ b/arch/arm/include/asm/hypervisor.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_ARM_HYPERVISOR_H | ||
2 | #define _ASM_ARM_HYPERVISOR_H | ||
3 | |||
4 | #include <asm/xen/hypervisor.h> | ||
5 | |||
6 | #endif | ||
diff --git a/arch/arm/include/asm/sync_bitops.h b/arch/arm/include/asm/sync_bitops.h new file mode 100644 index 000000000000..63479eecbf76 --- /dev/null +++ b/arch/arm/include/asm/sync_bitops.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __ASM_SYNC_BITOPS_H__ | ||
2 | #define __ASM_SYNC_BITOPS_H__ | ||
3 | |||
4 | #include <asm/bitops.h> | ||
5 | #include <asm/system.h> | ||
6 | |||
7 | /* sync_bitops functions are equivalent to the SMP implementation of the | ||
8 | * original functions, independently from CONFIG_SMP being defined. | ||
9 | * | ||
10 | * We need them because _set_bit etc are not SMP safe if !CONFIG_SMP. But | ||
11 | * under Xen you might be communicating with a completely external entity | ||
12 | * who might be on another CPU (e.g. two uniprocessor guests communicating | ||
13 | * via event channels and grant tables). So we need a variant of the bit | ||
14 | * ops which are SMP safe even on a UP kernel. | ||
15 | */ | ||
16 | |||
17 | #define sync_set_bit(nr, p) _set_bit(nr, p) | ||
18 | #define sync_clear_bit(nr, p) _clear_bit(nr, p) | ||
19 | #define sync_change_bit(nr, p) _change_bit(nr, p) | ||
20 | #define sync_test_and_set_bit(nr, p) _test_and_set_bit(nr, p) | ||
21 | #define sync_test_and_clear_bit(nr, p) _test_and_clear_bit(nr, p) | ||
22 | #define sync_test_and_change_bit(nr, p) _test_and_change_bit(nr, p) | ||
23 | #define sync_test_bit(nr, addr) test_bit(nr, addr) | ||
24 | #define sync_cmpxchg cmpxchg | ||
25 | |||
26 | |||
27 | #endif | ||
diff --git a/arch/arm/include/asm/xen/events.h b/arch/arm/include/asm/xen/events.h new file mode 100644 index 000000000000..94b4e9020b02 --- /dev/null +++ b/arch/arm/include/asm/xen/events.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _ASM_ARM_XEN_EVENTS_H | ||
2 | #define _ASM_ARM_XEN_EVENTS_H | ||
3 | |||
4 | #include <asm/ptrace.h> | ||
5 | |||
6 | enum ipi_vector { | ||
7 | XEN_PLACEHOLDER_VECTOR, | ||
8 | |||
9 | /* Xen IPIs go here */ | ||
10 | XEN_NR_IPIS, | ||
11 | }; | ||
12 | |||
13 | static inline int xen_irqs_disabled(struct pt_regs *regs) | ||
14 | { | ||
15 | return raw_irqs_disabled_flags(regs->ARM_cpsr); | ||
16 | } | ||
17 | |||
18 | #endif /* _ASM_ARM_XEN_EVENTS_H */ | ||
diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h new file mode 100644 index 000000000000..8a823253d775 --- /dev/null +++ b/arch/arm/include/asm/xen/hypercall.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /****************************************************************************** | ||
2 | * hypercall.h | ||
3 | * | ||
4 | * Linux-specific hypervisor handling. | ||
5 | * | ||
6 | * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation; or, when distributed | ||
11 | * separately from the Linux kernel or incorporated into other | ||
12 | * software packages, subject to the following license: | ||
13 | * | ||
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
15 | * of this source file (the "Software"), to deal in the Software without | ||
16 | * restriction, including without limitation the rights to use, copy, modify, | ||
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
18 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
19 | * the following conditions: | ||
20 | * | ||
21 | * The above copyright notice and this permission notice shall be included in | ||
22 | * all copies or substantial portions of the Software. | ||
23 | * | ||
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
30 | * IN THE SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | #ifndef _ASM_ARM_XEN_HYPERCALL_H | ||
34 | #define _ASM_ARM_XEN_HYPERCALL_H | ||
35 | |||
36 | #include <xen/interface/xen.h> | ||
37 | |||
38 | long privcmd_call(unsigned call, unsigned long a1, | ||
39 | unsigned long a2, unsigned long a3, | ||
40 | unsigned long a4, unsigned long a5); | ||
41 | int HYPERVISOR_xen_version(int cmd, void *arg); | ||
42 | int HYPERVISOR_console_io(int cmd, int count, char *str); | ||
43 | int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); | ||
44 | int HYPERVISOR_sched_op(int cmd, void *arg); | ||
45 | int HYPERVISOR_event_channel_op(int cmd, void *arg); | ||
46 | unsigned long HYPERVISOR_hvm_op(int op, void *arg); | ||
47 | int HYPERVISOR_memory_op(unsigned int cmd, void *arg); | ||
48 | int HYPERVISOR_physdev_op(int cmd, void *arg); | ||
49 | |||
50 | static inline void | ||
51 | MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va, | ||
52 | unsigned int new_val, unsigned long flags) | ||
53 | { | ||
54 | BUG(); | ||
55 | } | ||
56 | |||
57 | static inline void | ||
58 | MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req, | ||
59 | int count, int *success_count, domid_t domid) | ||
60 | { | ||
61 | BUG(); | ||
62 | } | ||
63 | |||
64 | static inline int | ||
65 | HYPERVISOR_multicall(void *call_list, int nr_calls) | ||
66 | { | ||
67 | BUG(); | ||
68 | } | ||
69 | #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 000000000000..d7ab99a0c9eb --- /dev/null +++ b/arch/arm/include/asm/xen/hypervisor.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef _ASM_ARM_XEN_HYPERVISOR_H | ||
2 | #define _ASM_ARM_XEN_HYPERVISOR_H | ||
3 | |||
4 | extern struct shared_info *HYPERVISOR_shared_info; | ||
5 | extern struct start_info *xen_start_info; | ||
6 | |||
7 | /* Lazy mode for batching updates / context switch */ | ||
8 | enum paravirt_lazy_mode { | ||
9 | PARAVIRT_LAZY_NONE, | ||
10 | PARAVIRT_LAZY_MMU, | ||
11 | PARAVIRT_LAZY_CPU, | ||
12 | }; | ||
13 | |||
14 | static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void) | ||
15 | { | ||
16 | return PARAVIRT_LAZY_NONE; | ||
17 | } | ||
18 | |||
19 | #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 000000000000..ae05e56dd17d --- /dev/null +++ b/arch/arm/include/asm/xen/interface.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /****************************************************************************** | ||
2 | * Guest OS interface to ARM Xen. | ||
3 | * | ||
4 | * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012 | ||
5 | */ | ||
6 | |||
7 | #ifndef _ASM_ARM_XEN_INTERFACE_H | ||
8 | #define _ASM_ARM_XEN_INTERFACE_H | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | |||
12 | #define uint64_aligned_t uint64_t __attribute__((aligned(8))) | ||
13 | |||
14 | #define __DEFINE_GUEST_HANDLE(name, type) \ | ||
15 | typedef struct { union { type *p; uint64_aligned_t q; }; } \ | ||
16 | __guest_handle_ ## name | ||
17 | |||
18 | #define DEFINE_GUEST_HANDLE_STRUCT(name) \ | ||
19 | __DEFINE_GUEST_HANDLE(name, struct name) | ||
20 | #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) | ||
21 | #define GUEST_HANDLE(name) __guest_handle_ ## name | ||
22 | |||
23 | #define set_xen_guest_handle(hnd, val) \ | ||
24 | do { \ | ||
25 | if (sizeof(hnd) == 8) \ | ||
26 | *(uint64_t *)&(hnd) = 0; \ | ||
27 | (hnd).p = val; \ | ||
28 | } while (0) | ||
29 | |||
30 | #ifndef __ASSEMBLY__ | ||
31 | /* Explicitly size integers that represent pfns in the interface with | ||
32 | * Xen so that we can have one ABI that works for 32 and 64 bit guests. */ | ||
33 | typedef uint64_t xen_pfn_t; | ||
34 | typedef uint64_t xen_ulong_t; | ||
35 | /* Guest handles for primitive C types. */ | ||
36 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); | ||
37 | __DEFINE_GUEST_HANDLE(uint, unsigned int); | ||
38 | __DEFINE_GUEST_HANDLE(ulong, unsigned long); | ||
39 | DEFINE_GUEST_HANDLE(char); | ||
40 | DEFINE_GUEST_HANDLE(int); | ||
41 | DEFINE_GUEST_HANDLE(long); | ||
42 | DEFINE_GUEST_HANDLE(void); | ||
43 | DEFINE_GUEST_HANDLE(uint64_t); | ||
44 | DEFINE_GUEST_HANDLE(uint32_t); | ||
45 | DEFINE_GUEST_HANDLE(xen_pfn_t); | ||
46 | |||
47 | /* Maximum number of virtual CPUs in multi-processor guests. */ | ||
48 | #define MAX_VIRT_CPUS 1 | ||
49 | |||
50 | struct arch_vcpu_info { }; | ||
51 | struct arch_shared_info { }; | ||
52 | |||
53 | /* TODO: Move pvclock definitions some place arch independent */ | ||
54 | struct pvclock_vcpu_time_info { | ||
55 | u32 version; | ||
56 | u32 pad0; | ||
57 | u64 tsc_timestamp; | ||
58 | u64 system_time; | ||
59 | u32 tsc_to_system_mul; | ||
60 | s8 tsc_shift; | ||
61 | u8 flags; | ||
62 | u8 pad[2]; | ||
63 | } __attribute__((__packed__)); /* 32 bytes */ | ||
64 | |||
65 | /* It is OK to have a 12 bytes struct with no padding because it is packed */ | ||
66 | struct pvclock_wall_clock { | ||
67 | u32 version; | ||
68 | u32 sec; | ||
69 | u32 nsec; | ||
70 | } __attribute__((__packed__)); | ||
71 | #endif | ||
72 | |||
73 | #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 000000000000..174202318dff --- /dev/null +++ b/arch/arm/include/asm/xen/page.h | |||
@@ -0,0 +1,82 @@ | |||
1 | #ifndef _ASM_ARM_XEN_PAGE_H | ||
2 | #define _ASM_ARM_XEN_PAGE_H | ||
3 | |||
4 | #include <asm/page.h> | ||
5 | #include <asm/pgtable.h> | ||
6 | |||
7 | #include <linux/pfn.h> | ||
8 | #include <linux/types.h> | ||
9 | |||
10 | #include <xen/interface/grant_table.h> | ||
11 | |||
12 | #define pfn_to_mfn(pfn) (pfn) | ||
13 | #define phys_to_machine_mapping_valid (1) | ||
14 | #define mfn_to_pfn(mfn) (mfn) | ||
15 | #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) | ||
16 | |||
17 | #define pte_mfn pte_pfn | ||
18 | #define mfn_pte pfn_pte | ||
19 | |||
20 | /* Xen machine address */ | ||
21 | typedef struct xmaddr { | ||
22 | phys_addr_t maddr; | ||
23 | } xmaddr_t; | ||
24 | |||
25 | /* Xen pseudo-physical address */ | ||
26 | typedef struct xpaddr { | ||
27 | phys_addr_t paddr; | ||
28 | } xpaddr_t; | ||
29 | |||
30 | #define XMADDR(x) ((xmaddr_t) { .maddr = (x) }) | ||
31 | #define XPADDR(x) ((xpaddr_t) { .paddr = (x) }) | ||
32 | |||
33 | static inline xmaddr_t phys_to_machine(xpaddr_t phys) | ||
34 | { | ||
35 | unsigned offset = phys.paddr & ~PAGE_MASK; | ||
36 | return XMADDR(PFN_PHYS(pfn_to_mfn(PFN_DOWN(phys.paddr))) | offset); | ||
37 | } | ||
38 | |||
39 | static inline xpaddr_t machine_to_phys(xmaddr_t machine) | ||
40 | { | ||
41 | unsigned offset = machine.maddr & ~PAGE_MASK; | ||
42 | return XPADDR(PFN_PHYS(mfn_to_pfn(PFN_DOWN(machine.maddr))) | offset); | ||
43 | } | ||
44 | /* VIRT <-> MACHINE conversion */ | ||
45 | #define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v)))) | ||
46 | #define virt_to_pfn(v) (PFN_DOWN(__pa(v))) | ||
47 | #define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v))) | ||
48 | #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) | ||
49 | |||
50 | static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr) | ||
51 | { | ||
52 | /* TODO: assuming it is mapped in the kernel 1:1 */ | ||
53 | return virt_to_machine(vaddr); | ||
54 | } | ||
55 | |||
56 | /* TODO: this shouldn't be here but it is because the frontend drivers | ||
57 | * are using it (its rolled in headers) even though we won't hit the code path. | ||
58 | * So for right now just punt with this. | ||
59 | */ | ||
60 | static inline pte_t *lookup_address(unsigned long address, unsigned int *level) | ||
61 | { | ||
62 | BUG(); | ||
63 | return NULL; | ||
64 | } | ||
65 | |||
66 | static inline int m2p_add_override(unsigned long mfn, struct page *page, | ||
67 | struct gnttab_map_grant_ref *kmap_op) | ||
68 | { | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static inline int m2p_remove_override(struct page *page, bool clear_pte) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) | ||
78 | { | ||
79 | BUG(); | ||
80 | return false; | ||
81 | } | ||
82 | #endif /* _ASM_ARM_XEN_PAGE_H */ | ||
diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot index 318d308dfb93..38dbaac63349 100644 --- a/arch/arm/mach-vexpress/Makefile.boot +++ b/arch/arm/mach-vexpress/Makefile.boot | |||
@@ -7,4 +7,5 @@ initrd_phys-y := 0x60800000 | |||
7 | dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \ | 7 | dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \ |
8 | vexpress-v2p-ca9.dtb \ | 8 | vexpress-v2p-ca9.dtb \ |
9 | vexpress-v2p-ca15-tc1.dtb \ | 9 | vexpress-v2p-ca15-tc1.dtb \ |
10 | vexpress-v2p-ca15_a7.dtb | 10 | vexpress-v2p-ca15_a7.dtb \ |
11 | xenvm-4.2.dtb | ||
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 37608f22ee31..0a79b085ceaf 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -658,6 +658,7 @@ static void __init v2m_dt_init(void) | |||
658 | 658 | ||
659 | const static char *v2m_dt_match[] __initconst = { | 659 | const static char *v2m_dt_match[] __initconst = { |
660 | "arm,vexpress", | 660 | "arm,vexpress", |
661 | "xen,xenvm", | ||
661 | NULL, | 662 | NULL, |
662 | }; | 663 | }; |
663 | 664 | ||
diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile new file mode 100644 index 000000000000..43841033afd3 --- /dev/null +++ b/arch/arm/xen/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-y := enlighten.o hypercall.o grant-table.o | |||
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c new file mode 100644 index 000000000000..59bcb96ac369 --- /dev/null +++ b/arch/arm/xen/enlighten.c | |||
@@ -0,0 +1,168 @@ | |||
1 | #include <xen/xen.h> | ||
2 | #include <xen/events.h> | ||
3 | #include <xen/grant_table.h> | ||
4 | #include <xen/hvm.h> | ||
5 | #include <xen/interface/xen.h> | ||
6 | #include <xen/interface/memory.h> | ||
7 | #include <xen/interface/hvm/params.h> | ||
8 | #include <xen/features.h> | ||
9 | #include <xen/platform_pci.h> | ||
10 | #include <xen/xenbus.h> | ||
11 | #include <asm/xen/hypervisor.h> | ||
12 | #include <asm/xen/hypercall.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/irqreturn.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/of_address.h> | ||
19 | |||
20 | struct start_info _xen_start_info; | ||
21 | struct start_info *xen_start_info = &_xen_start_info; | ||
22 | EXPORT_SYMBOL_GPL(xen_start_info); | ||
23 | |||
24 | enum xen_domain_type xen_domain_type = XEN_NATIVE; | ||
25 | EXPORT_SYMBOL_GPL(xen_domain_type); | ||
26 | |||
27 | struct shared_info xen_dummy_shared_info; | ||
28 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | ||
29 | |||
30 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | ||
31 | |||
32 | /* TODO: to be removed */ | ||
33 | __read_mostly int xen_have_vector_callback; | ||
34 | EXPORT_SYMBOL_GPL(xen_have_vector_callback); | ||
35 | |||
36 | int xen_platform_pci_unplug = XEN_UNPLUG_ALL; | ||
37 | EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); | ||
38 | |||
39 | static __read_mostly int xen_events_irq = -1; | ||
40 | |||
41 | int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | ||
42 | unsigned long addr, | ||
43 | unsigned long mfn, int nr, | ||
44 | pgprot_t prot, unsigned domid) | ||
45 | { | ||
46 | return -ENOSYS; | ||
47 | } | ||
48 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | ||
49 | |||
50 | /* | ||
51 | * see Documentation/devicetree/bindings/arm/xen.txt for the | ||
52 | * documentation of the Xen Device Tree format. | ||
53 | */ | ||
54 | #define GRANT_TABLE_PHYSADDR 0 | ||
55 | static int __init xen_guest_init(void) | ||
56 | { | ||
57 | struct xen_add_to_physmap xatp; | ||
58 | static struct shared_info *shared_info_page = 0; | ||
59 | struct device_node *node; | ||
60 | int len; | ||
61 | const char *s = NULL; | ||
62 | const char *version = NULL; | ||
63 | const char *xen_prefix = "xen,xen-"; | ||
64 | struct resource res; | ||
65 | |||
66 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); | ||
67 | if (!node) { | ||
68 | pr_debug("No Xen support\n"); | ||
69 | return 0; | ||
70 | } | ||
71 | s = of_get_property(node, "compatible", &len); | ||
72 | if (strlen(xen_prefix) + 3 < len && | ||
73 | !strncmp(xen_prefix, s, strlen(xen_prefix))) | ||
74 | version = s + strlen(xen_prefix); | ||
75 | if (version == NULL) { | ||
76 | pr_debug("Xen version not found\n"); | ||
77 | return 0; | ||
78 | } | ||
79 | if (of_address_to_resource(node, GRANT_TABLE_PHYSADDR, &res)) | ||
80 | return 0; | ||
81 | xen_hvm_resume_frames = res.start >> PAGE_SHIFT; | ||
82 | xen_events_irq = irq_of_parse_and_map(node, 0); | ||
83 | pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n", | ||
84 | version, xen_events_irq, xen_hvm_resume_frames); | ||
85 | xen_domain_type = XEN_HVM_DOMAIN; | ||
86 | |||
87 | xen_setup_features(); | ||
88 | if (xen_feature(XENFEAT_dom0)) | ||
89 | xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED; | ||
90 | else | ||
91 | xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED); | ||
92 | |||
93 | if (!shared_info_page) | ||
94 | shared_info_page = (struct shared_info *) | ||
95 | get_zeroed_page(GFP_KERNEL); | ||
96 | if (!shared_info_page) { | ||
97 | pr_err("not enough memory\n"); | ||
98 | return -ENOMEM; | ||
99 | } | ||
100 | xatp.domid = DOMID_SELF; | ||
101 | xatp.idx = 0; | ||
102 | xatp.space = XENMAPSPACE_shared_info; | ||
103 | xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; | ||
104 | if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) | ||
105 | BUG(); | ||
106 | |||
107 | HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; | ||
108 | |||
109 | /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info | ||
110 | * page, we use it in the event channel upcall and in some pvclock | ||
111 | * related functions. We don't need the vcpu_info placement | ||
112 | * optimizations because we don't use any pv_mmu or pv_irq op on | ||
113 | * HVM. | ||
114 | * The shared info contains exactly 1 CPU (the boot CPU). The guest | ||
115 | * is required to use VCPUOP_register_vcpu_info to place vcpu info | ||
116 | * for secondary CPUs as they are brought up. */ | ||
117 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | ||
118 | |||
119 | gnttab_init(); | ||
120 | if (!xen_initial_domain()) | ||
121 | xenbus_probe(NULL); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | core_initcall(xen_guest_init); | ||
126 | |||
127 | static irqreturn_t xen_arm_callback(int irq, void *arg) | ||
128 | { | ||
129 | xen_hvm_evtchn_do_upcall(); | ||
130 | return IRQ_HANDLED; | ||
131 | } | ||
132 | |||
133 | static int __init xen_init_events(void) | ||
134 | { | ||
135 | if (!xen_domain() || xen_events_irq < 0) | ||
136 | return -ENODEV; | ||
137 | |||
138 | xen_init_IRQ(); | ||
139 | |||
140 | if (request_percpu_irq(xen_events_irq, xen_arm_callback, | ||
141 | "events", xen_vcpu)) { | ||
142 | pr_err("Error requesting IRQ %d\n", xen_events_irq); | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | enable_percpu_irq(xen_events_irq, 0); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | postcore_initcall(xen_init_events); | ||
151 | |||
152 | /* XXX: only until balloon is properly working */ | ||
153 | int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) | ||
154 | { | ||
155 | *pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL, | ||
156 | get_order(nr_pages)); | ||
157 | if (*pages == NULL) | ||
158 | return -ENOMEM; | ||
159 | return 0; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(alloc_xenballooned_pages); | ||
162 | |||
163 | void free_xenballooned_pages(int nr_pages, struct page **pages) | ||
164 | { | ||
165 | kfree(*pages); | ||
166 | *pages = NULL; | ||
167 | } | ||
168 | EXPORT_SYMBOL_GPL(free_xenballooned_pages); | ||
diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c new file mode 100644 index 000000000000..dbd1330c0196 --- /dev/null +++ b/arch/arm/xen/grant-table.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /****************************************************************************** | ||
2 | * grant_table.c | ||
3 | * ARM specific part | ||
4 | * | ||
5 | * Granting foreign access to our memory reservation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version 2 | ||
9 | * as published by the Free Software Foundation; or, when distributed | ||
10 | * separately from the Linux kernel or incorporated into other | ||
11 | * software packages, subject to the following license: | ||
12 | * | ||
13 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
14 | * of this source file (the "Software"), to deal in the Software without | ||
15 | * restriction, including without limitation the rights to use, copy, modify, | ||
16 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
17 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
18 | * the following conditions: | ||
19 | * | ||
20 | * The above copyright notice and this permission notice shall be included in | ||
21 | * all copies or substantial portions of the Software. | ||
22 | * | ||
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
24 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
25 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
26 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
27 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
28 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
29 | * IN THE SOFTWARE. | ||
30 | */ | ||
31 | |||
32 | #include <xen/interface/xen.h> | ||
33 | #include <xen/page.h> | ||
34 | #include <xen/grant_table.h> | ||
35 | |||
36 | int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, | ||
37 | unsigned long max_nr_gframes, | ||
38 | void **__shared) | ||
39 | { | ||
40 | return -ENOSYS; | ||
41 | } | ||
42 | |||
43 | void arch_gnttab_unmap(void *shared, unsigned long nr_gframes) | ||
44 | { | ||
45 | return; | ||
46 | } | ||
47 | |||
48 | int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, | ||
49 | unsigned long max_nr_gframes, | ||
50 | grant_status_t **__shared) | ||
51 | { | ||
52 | return -ENOSYS; | ||
53 | } | ||
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S new file mode 100644 index 000000000000..074f5ed101b9 --- /dev/null +++ b/arch/arm/xen/hypercall.S | |||
@@ -0,0 +1,106 @@ | |||
1 | /****************************************************************************** | ||
2 | * hypercall.S | ||
3 | * | ||
4 | * Xen hypercall wrappers | ||
5 | * | ||
6 | * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License version 2 | ||
10 | * as published by the Free Software Foundation; or, when distributed | ||
11 | * separately from the Linux kernel or incorporated into other | ||
12 | * software packages, subject to the following license: | ||
13 | * | ||
14 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
15 | * of this source file (the "Software"), to deal in the Software without | ||
16 | * restriction, including without limitation the rights to use, copy, modify, | ||
17 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
18 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
19 | * the following conditions: | ||
20 | * | ||
21 | * The above copyright notice and this permission notice shall be included in | ||
22 | * all copies or substantial portions of the Software. | ||
23 | * | ||
24 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
25 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
27 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
28 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
30 | * IN THE SOFTWARE. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * The Xen hypercall calling convention is very similar to the ARM | ||
35 | * procedure calling convention: the first paramter is passed in r0, the | ||
36 | * second in r1, the third in r2 and the fourth in r3. Considering that | ||
37 | * Xen hypercalls have 5 arguments at most, the fifth paramter is passed | ||
38 | * in r4, differently from the procedure calling convention of using the | ||
39 | * stack for that case. | ||
40 | * | ||
41 | * The hypercall number is passed in r12. | ||
42 | * | ||
43 | * The return value is in r0. | ||
44 | * | ||
45 | * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM | ||
46 | * hypercall tag. | ||
47 | */ | ||
48 | |||
49 | #include <linux/linkage.h> | ||
50 | #include <asm/assembler.h> | ||
51 | #include <xen/interface/xen.h> | ||
52 | |||
53 | |||
54 | /* HVC 0xEA1 */ | ||
55 | #ifdef CONFIG_THUMB2_KERNEL | ||
56 | #define xen_hvc .word 0xf7e08ea1 | ||
57 | #else | ||
58 | #define xen_hvc .word 0xe140ea71 | ||
59 | #endif | ||
60 | |||
61 | #define HYPERCALL_SIMPLE(hypercall) \ | ||
62 | ENTRY(HYPERVISOR_##hypercall) \ | ||
63 | mov r12, #__HYPERVISOR_##hypercall; \ | ||
64 | xen_hvc; \ | ||
65 | mov pc, lr; \ | ||
66 | ENDPROC(HYPERVISOR_##hypercall) | ||
67 | |||
68 | #define HYPERCALL0 HYPERCALL_SIMPLE | ||
69 | #define HYPERCALL1 HYPERCALL_SIMPLE | ||
70 | #define HYPERCALL2 HYPERCALL_SIMPLE | ||
71 | #define HYPERCALL3 HYPERCALL_SIMPLE | ||
72 | #define HYPERCALL4 HYPERCALL_SIMPLE | ||
73 | |||
74 | #define HYPERCALL5(hypercall) \ | ||
75 | ENTRY(HYPERVISOR_##hypercall) \ | ||
76 | stmdb sp!, {r4} \ | ||
77 | ldr r4, [sp, #4] \ | ||
78 | mov r12, #__HYPERVISOR_##hypercall; \ | ||
79 | xen_hvc \ | ||
80 | ldm sp!, {r4} \ | ||
81 | mov pc, lr \ | ||
82 | ENDPROC(HYPERVISOR_##hypercall) | ||
83 | |||
84 | .text | ||
85 | |||
86 | HYPERCALL2(xen_version); | ||
87 | HYPERCALL3(console_io); | ||
88 | HYPERCALL3(grant_table_op); | ||
89 | HYPERCALL2(sched_op); | ||
90 | HYPERCALL2(event_channel_op); | ||
91 | HYPERCALL2(hvm_op); | ||
92 | HYPERCALL2(memory_op); | ||
93 | HYPERCALL2(physdev_op); | ||
94 | |||
95 | ENTRY(privcmd_call) | ||
96 | stmdb sp!, {r4} | ||
97 | mov r12, r0 | ||
98 | mov r0, r1 | ||
99 | mov r1, r2 | ||
100 | mov r2, r3 | ||
101 | ldr r3, [sp, #8] | ||
102 | ldr r4, [sp, #4] | ||
103 | xen_hvc | ||
104 | ldm sp!, {r4} | ||
105 | mov pc, lr | ||
106 | ENDPROC(privcmd_call); | ||