2 #include <xen/events.h>
3 #include <xen/grant_table.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>
12 #include <xen/xen-ops.h>
13 #include <asm/xen/hypervisor.h>
14 #include <asm/xen/hypercall.h>
15 #include <linux/interrupt.h>
16 #include <linux/irqreturn.h>
17 #include <linux/module.h>
19 #include <linux/of_irq.h>
20 #include <linux/of_address.h>
24 struct start_info _xen_start_info
;
25 struct start_info
*xen_start_info
= &_xen_start_info
;
26 EXPORT_SYMBOL_GPL(xen_start_info
);
28 enum xen_domain_type xen_domain_type
= XEN_NATIVE
;
29 EXPORT_SYMBOL_GPL(xen_domain_type
);
31 struct shared_info xen_dummy_shared_info
;
32 struct shared_info
*HYPERVISOR_shared_info
= (void *)&xen_dummy_shared_info
;
34 DEFINE_PER_CPU(struct vcpu_info
*, xen_vcpu
);
36 /* These are unused until we support booting "pre-ballooned" */
37 unsigned long xen_released_pages
;
38 struct xen_memory_region xen_extra_mem
[XEN_EXTRA_MEM_MAX_REGIONS
] __initdata
;
40 /* TODO: to be removed */
41 __read_mostly
int xen_have_vector_callback
;
42 EXPORT_SYMBOL_GPL(xen_have_vector_callback
);
44 int xen_platform_pci_unplug
= XEN_UNPLUG_ALL
;
45 EXPORT_SYMBOL_GPL(xen_platform_pci_unplug
);
47 static __read_mostly
int xen_events_irq
= -1;
49 /* map fgmfn of domid to lpfn in the current domain */
50 static int map_foreign_page(unsigned long lpfn
, unsigned long fgmfn
,
54 struct xen_add_to_physmap_range xatp
= {
56 .foreign_domid
= domid
,
58 .space
= XENMAPSPACE_gmfn_foreign
,
60 xen_ulong_t idx
= fgmfn
;
61 xen_pfn_t gpfn
= lpfn
;
63 set_xen_guest_handle(xatp
.idxs
, &idx
);
64 set_xen_guest_handle(xatp
.gpfns
, &gpfn
);
66 rc
= HYPERVISOR_memory_op(XENMEM_add_to_physmap_range
, &xatp
);
68 pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n",
76 xen_pfn_t fgmfn
; /* foreign domain's gmfn */
79 struct vm_area_struct
*vma
;
82 struct xen_remap_mfn_info
*info
;
85 static int remap_pte_fn(pte_t
*ptep
, pgtable_t token
, unsigned long addr
,
88 struct remap_data
*info
= data
;
89 struct page
*page
= info
->pages
[info
->index
++];
90 unsigned long pfn
= page_to_pfn(page
);
91 pte_t pte
= pfn_pte(pfn
, info
->prot
);
93 if (map_foreign_page(pfn
, info
->fgmfn
, info
->domid
))
95 set_pte_at(info
->vma
->vm_mm
, addr
, ptep
, pte
);
100 int xen_remap_domain_mfn_range(struct vm_area_struct
*vma
,
102 xen_pfn_t mfn
, int nr
,
103 pgprot_t prot
, unsigned domid
,
107 struct remap_data data
;
109 /* TBD: Batching, current sole caller only does page at a time */
119 err
= apply_to_page_range(vma
->vm_mm
, addr
, nr
<< PAGE_SHIFT
,
120 remap_pte_fn
, &data
);
123 EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range
);
125 int xen_unmap_domain_mfn_range(struct vm_area_struct
*vma
,
126 int nr
, struct page
**pages
)
130 for (i
= 0; i
< nr
; i
++) {
131 struct xen_remove_from_physmap xrp
;
132 unsigned long rc
, pfn
;
134 pfn
= page_to_pfn(pages
[i
]);
136 xrp
.domid
= DOMID_SELF
;
138 rc
= HYPERVISOR_memory_op(XENMEM_remove_from_physmap
, &xrp
);
140 pr_warn("Failed to unmap pfn:%lx rc:%ld\n",
147 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range
);
150 * see Documentation/devicetree/bindings/arm/xen.txt for the
151 * documentation of the Xen Device Tree format.
153 #define GRANT_TABLE_PHYSADDR 0
154 static int __init
xen_guest_init(void)
156 struct xen_add_to_physmap xatp
;
157 static struct shared_info
*shared_info_page
= 0;
158 struct device_node
*node
;
160 const char *s
= NULL
;
161 const char *version
= NULL
;
162 const char *xen_prefix
= "xen,xen-";
165 node
= of_find_compatible_node(NULL
, NULL
, "xen,xen");
167 pr_debug("No Xen support\n");
170 s
= of_get_property(node
, "compatible", &len
);
171 if (strlen(xen_prefix
) + 3 < len
&&
172 !strncmp(xen_prefix
, s
, strlen(xen_prefix
)))
173 version
= s
+ strlen(xen_prefix
);
174 if (version
== NULL
) {
175 pr_debug("Xen version not found\n");
178 if (of_address_to_resource(node
, GRANT_TABLE_PHYSADDR
, &res
))
180 xen_hvm_resume_frames
= res
.start
>> PAGE_SHIFT
;
181 xen_events_irq
= irq_of_parse_and_map(node
, 0);
182 pr_info("Xen %s support found, events_irq=%d gnttab_frame_pfn=%lx\n",
183 version
, xen_events_irq
, xen_hvm_resume_frames
);
184 xen_domain_type
= XEN_HVM_DOMAIN
;
186 xen_setup_features();
187 if (xen_feature(XENFEAT_dom0
))
188 xen_start_info
->flags
|= SIF_INITDOMAIN
|SIF_PRIVILEGED
;
190 xen_start_info
->flags
&= ~(SIF_INITDOMAIN
|SIF_PRIVILEGED
);
192 if (!shared_info_page
)
193 shared_info_page
= (struct shared_info
*)
194 get_zeroed_page(GFP_KERNEL
);
195 if (!shared_info_page
) {
196 pr_err("not enough memory\n");
199 xatp
.domid
= DOMID_SELF
;
201 xatp
.space
= XENMAPSPACE_shared_info
;
202 xatp
.gpfn
= __pa(shared_info_page
) >> PAGE_SHIFT
;
203 if (HYPERVISOR_memory_op(XENMEM_add_to_physmap
, &xatp
))
206 HYPERVISOR_shared_info
= (struct shared_info
*)shared_info_page
;
208 /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
209 * page, we use it in the event channel upcall and in some pvclock
210 * related functions. We don't need the vcpu_info placement
211 * optimizations because we don't use any pv_mmu or pv_irq op on
213 * The shared info contains exactly 1 CPU (the boot CPU). The guest
214 * is required to use VCPUOP_register_vcpu_info to place vcpu info
215 * for secondary CPUs as they are brought up. */
216 per_cpu(xen_vcpu
, 0) = &HYPERVISOR_shared_info
->vcpu_info
[0];
219 if (!xen_initial_domain())
224 core_initcall(xen_guest_init
);
226 static irqreturn_t
xen_arm_callback(int irq
, void *arg
)
228 xen_hvm_evtchn_do_upcall();
232 static int __init
xen_init_events(void)
234 if (!xen_domain() || xen_events_irq
< 0)
239 if (request_percpu_irq(xen_events_irq
, xen_arm_callback
,
240 "events", xen_vcpu
)) {
241 pr_err("Error requesting IRQ %d\n", xen_events_irq
);
245 enable_percpu_irq(xen_events_irq
, 0);
249 postcore_initcall(xen_init_events
);
251 /* In the hypervisor.S file. */
252 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op
);
253 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op
);
254 EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version
);
255 EXPORT_SYMBOL_GPL(HYPERVISOR_console_io
);
256 EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op
);
257 EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op
);
258 EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op
);
259 EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op
);
260 EXPORT_SYMBOL_GPL(privcmd_call
);