diff options
author | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-09-14 06:47:52 -0400 |
---|---|---|
committer | Stefano Stabellini <stefano.stabellini@eu.citrix.com> | 2012-09-14 06:47:52 -0400 |
commit | 2e01f16601d8924b12b1acf1cdc49a0d1cc1cfb2 (patch) | |
tree | 25563e7fcc72619a52bb335dd845e741e39ae6d5 /arch/arm/xen | |
parent | c43cdfbc4cebdf1a7992432615bf5155b51b8cc0 (diff) |
xen/arm: Xen detection and shared_info page mapping
Check for a node in the device tree compatible with "xen,xen", if it is
present set xen_domain_type to XEN_HVM_DOMAIN and continue
initialization.
Map the real shared info page using XENMEM_add_to_physmap with
XENMAPSPACE_shared_info.
Changes in v4:
- simpler parsing of Xen version in the compatible DT node.
Changes in v3:
- use the "xen,xen" notation rather than "arm,xen";
- add an additional check on the presence of the Xen version.
Changes in v2:
- replace pr_info with pr_debug.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'arch/arm/xen')
-rw-r--r-- | arch/arm/xen/enlighten.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index c53554032a60..6a0217d4e662 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c | |||
@@ -5,6 +5,9 @@ | |||
5 | #include <asm/xen/hypervisor.h> | 5 | #include <asm/xen/hypervisor.h> |
6 | #include <asm/xen/hypercall.h> | 6 | #include <asm/xen/hypercall.h> |
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/of.h> | ||
9 | #include <linux/of_irq.h> | ||
10 | #include <linux/of_address.h> | ||
8 | 11 | ||
9 | struct start_info _xen_start_info; | 12 | struct start_info _xen_start_info; |
10 | struct start_info *xen_start_info = &_xen_start_info; | 13 | struct start_info *xen_start_info = &_xen_start_info; |
@@ -33,3 +36,61 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | |||
33 | return -ENOSYS; | 36 | return -ENOSYS; |
34 | } | 37 | } |
35 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); | 38 | EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); |
39 | |||
40 | /* | ||
41 | * see Documentation/devicetree/bindings/arm/xen.txt for the | ||
42 | * documentation of the Xen Device Tree format. | ||
43 | */ | ||
44 | static int __init xen_guest_init(void) | ||
45 | { | ||
46 | struct xen_add_to_physmap xatp; | ||
47 | static struct shared_info *shared_info_page = 0; | ||
48 | struct device_node *node; | ||
49 | int len; | ||
50 | const char *s = NULL; | ||
51 | const char *version = NULL; | ||
52 | const char *xen_prefix = "xen,xen-"; | ||
53 | |||
54 | node = of_find_compatible_node(NULL, NULL, "xen,xen"); | ||
55 | if (!node) { | ||
56 | pr_debug("No Xen support\n"); | ||
57 | return 0; | ||
58 | } | ||
59 | s = of_get_property(node, "compatible", &len); | ||
60 | if (strlen(xen_prefix) + 3 < len && | ||
61 | !strncmp(xen_prefix, s, strlen(xen_prefix))) | ||
62 | version = s + strlen(xen_prefix); | ||
63 | if (version == NULL) { | ||
64 | pr_debug("Xen version not found\n"); | ||
65 | return 0; | ||
66 | } | ||
67 | xen_domain_type = XEN_HVM_DOMAIN; | ||
68 | |||
69 | if (!shared_info_page) | ||
70 | shared_info_page = (struct shared_info *) | ||
71 | get_zeroed_page(GFP_KERNEL); | ||
72 | if (!shared_info_page) { | ||
73 | pr_err("not enough memory\n"); | ||
74 | return -ENOMEM; | ||
75 | } | ||
76 | xatp.domid = DOMID_SELF; | ||
77 | xatp.idx = 0; | ||
78 | xatp.space = XENMAPSPACE_shared_info; | ||
79 | xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT; | ||
80 | if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) | ||
81 | BUG(); | ||
82 | |||
83 | HYPERVISOR_shared_info = (struct shared_info *)shared_info_page; | ||
84 | |||
85 | /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info | ||
86 | * page, we use it in the event channel upcall and in some pvclock | ||
87 | * related functions. We don't need the vcpu_info placement | ||
88 | * optimizations because we don't use any pv_mmu or pv_irq op on | ||
89 | * HVM. | ||
90 | * The shared info contains exactly 1 CPU (the boot CPU). The guest | ||
91 | * is required to use VCPUOP_register_vcpu_info to place vcpu info | ||
92 | * for secondary CPUs as they are brought up. */ | ||
93 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | ||
94 | return 0; | ||
95 | } | ||
96 | core_initcall(xen_guest_init); | ||