ia64/pv_ops/xen: implement xen pv_time_ops.
[pv_ops_mirror.git] / arch / ia64 / xen / xcom_hcall.c
blobb23b68476f3484204b5bfbe9f50b612743474635
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * Tristan Gingold <tristan.gingold@bull.net>
18 * Copyright (c) 2007
19 * Isaku Yamahata <yamahata at valinux co jp>
20 * VA Linux Systems Japan K.K.
21 * consolidate mini and inline version.
24 #include <linux/module.h>
25 #include <xen/interface/xen.h>
26 #include <xen/interface/memory.h>
27 #include <xen/interface/grant_table.h>
28 #include <xen/interface/callback.h>
29 #include <xen/interface/vcpu.h>
30 #include <asm/xen/hypervisor.h>
31 #include <asm/xen/xencomm.h>
33 /* Xencomm notes:
34 * This file defines hypercalls to be used by xencomm. The hypercalls simply
35 * create inlines or mini descriptors for pointers and then call the raw arch
36 * hypercall xencomm_arch_hypercall_XXX
38 * If the arch wants to directly use these hypercalls, simply define macros
39 * in asm/xen/hypercall.h, eg:
40 * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op
42 * The arch may also define HYPERVISOR_xxx as a function and do more operations
43 * before/after doing the hypercall.
45 * Note: because only inline or mini descriptors are created these functions
46 * must only be called with in kernel memory parameters.
49 int
50 xencomm_hypercall_console_io(int cmd, int count, char *str)
52 return xencomm_arch_hypercall_console_io
53 (cmd, count, xencomm_map_no_alloc(str, count));
55 EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io);
57 int
58 xencomm_hypercall_event_channel_op(int cmd, void *op)
60 struct xencomm_handle *desc;
61 desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op));
62 if (desc == NULL)
63 return -EINVAL;
65 return xencomm_arch_hypercall_event_channel_op(cmd, desc);
67 EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op);
69 int
70 xencomm_hypercall_xen_version(int cmd, void *arg)
72 struct xencomm_handle *desc;
73 unsigned int argsize;
75 switch (cmd) {
76 case XENVER_version:
77 /* do not actually pass an argument */
78 return xencomm_arch_hypercall_xen_version(cmd, 0);
79 case XENVER_extraversion:
80 argsize = sizeof(struct xen_extraversion);
81 break;
82 case XENVER_compile_info:
83 argsize = sizeof(struct xen_compile_info);
84 break;
85 case XENVER_capabilities:
86 argsize = sizeof(struct xen_capabilities_info);
87 break;
88 case XENVER_changeset:
89 argsize = sizeof(struct xen_changeset_info);
90 break;
91 case XENVER_platform_parameters:
92 argsize = sizeof(struct xen_platform_parameters);
93 break;
94 case XENVER_get_features:
95 argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info);
96 break;
98 default:
99 printk(KERN_DEBUG
100 "%s: unknown version op %d\n", __func__, cmd);
101 return -ENOSYS;
104 desc = xencomm_map_no_alloc(arg, argsize);
105 if (desc == NULL)
106 return -EINVAL;
108 return xencomm_arch_hypercall_xen_version(cmd, desc);
110 EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version);
113 xencomm_hypercall_physdev_op(int cmd, void *op)
115 unsigned int argsize;
117 switch (cmd) {
118 case PHYSDEVOP_apic_read:
119 case PHYSDEVOP_apic_write:
120 argsize = sizeof(struct physdev_apic);
121 break;
122 case PHYSDEVOP_alloc_irq_vector:
123 case PHYSDEVOP_free_irq_vector:
124 argsize = sizeof(struct physdev_irq);
125 break;
126 case PHYSDEVOP_irq_status_query:
127 argsize = sizeof(struct physdev_irq_status_query);
128 break;
130 default:
131 printk(KERN_DEBUG
132 "%s: unknown physdev op %d\n", __func__, cmd);
133 return -ENOSYS;
136 return xencomm_arch_hypercall_physdev_op
137 (cmd, xencomm_map_no_alloc(op, argsize));
140 static int
141 xencommize_grant_table_op(struct xencomm_mini **xc_area,
142 unsigned int cmd, void *op, unsigned int count,
143 struct xencomm_handle **desc)
145 struct xencomm_handle *desc1;
146 unsigned int argsize;
148 switch (cmd) {
149 case GNTTABOP_map_grant_ref:
150 argsize = sizeof(struct gnttab_map_grant_ref);
151 break;
152 case GNTTABOP_unmap_grant_ref:
153 argsize = sizeof(struct gnttab_unmap_grant_ref);
154 break;
155 case GNTTABOP_setup_table:
157 struct gnttab_setup_table *setup = op;
159 argsize = sizeof(*setup);
161 if (count != 1)
162 return -EINVAL;
163 desc1 = __xencomm_map_no_alloc
164 (xen_guest_handle(setup->frame_list),
165 setup->nr_frames *
166 sizeof(*xen_guest_handle(setup->frame_list)),
167 *xc_area);
168 if (desc1 == NULL)
169 return -EINVAL;
170 (*xc_area)++;
171 set_xen_guest_handle(setup->frame_list, (void *)desc1);
172 break;
174 case GNTTABOP_dump_table:
175 argsize = sizeof(struct gnttab_dump_table);
176 break;
177 case GNTTABOP_transfer:
178 argsize = sizeof(struct gnttab_transfer);
179 break;
180 case GNTTABOP_copy:
181 argsize = sizeof(struct gnttab_copy);
182 break;
183 case GNTTABOP_query_size:
184 argsize = sizeof(struct gnttab_query_size);
185 break;
186 default:
187 printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n",
188 __func__, cmd);
189 BUG();
192 *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area);
193 if (*desc == NULL)
194 return -EINVAL;
195 (*xc_area)++;
197 return 0;
201 xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
202 unsigned int count)
204 int rc;
205 struct xencomm_handle *desc;
206 XENCOMM_MINI_ALIGNED(xc_area, 2);
208 rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc);
209 if (rc)
210 return rc;
212 return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
214 EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op);
217 xencomm_hypercall_sched_op(int cmd, void *arg)
219 struct xencomm_handle *desc;
220 unsigned int argsize;
222 switch (cmd) {
223 case SCHEDOP_yield:
224 case SCHEDOP_block:
225 argsize = 0;
226 break;
227 case SCHEDOP_shutdown:
228 argsize = sizeof(struct sched_shutdown);
229 break;
230 case SCHEDOP_poll:
232 struct sched_poll *poll = arg;
233 struct xencomm_handle *ports;
235 argsize = sizeof(struct sched_poll);
236 ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports),
237 sizeof(*xen_guest_handle(poll->ports)));
239 set_xen_guest_handle(poll->ports, (void *)ports);
240 break;
242 default:
243 printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd);
244 return -ENOSYS;
247 desc = xencomm_map_no_alloc(arg, argsize);
248 if (desc == NULL)
249 return -EINVAL;
251 return xencomm_arch_hypercall_sched_op(cmd, desc);
253 EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op);
256 xencomm_hypercall_multicall(void *call_list, int nr_calls)
258 int rc;
259 int i;
260 struct multicall_entry *mce;
261 struct xencomm_handle *desc;
262 XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2);
264 for (i = 0; i < nr_calls; i++) {
265 mce = (struct multicall_entry *)call_list + i;
267 switch (mce->op) {
268 case __HYPERVISOR_update_va_mapping:
269 case __HYPERVISOR_mmu_update:
270 /* No-op on ia64. */
271 break;
272 case __HYPERVISOR_grant_table_op:
273 rc = xencommize_grant_table_op
274 (&xc_area,
275 mce->args[0], (void *)mce->args[1],
276 mce->args[2], &desc);
277 if (rc)
278 return rc;
279 mce->args[1] = (unsigned long)desc;
280 break;
281 case __HYPERVISOR_memory_op:
282 default:
283 printk(KERN_DEBUG
284 "%s: unhandled multicall op entry op %lu\n",
285 __func__, mce->op);
286 return -ENOSYS;
290 desc = xencomm_map_no_alloc(call_list,
291 nr_calls * sizeof(struct multicall_entry));
292 if (desc == NULL)
293 return -EINVAL;
295 return xencomm_arch_hypercall_multicall(desc, nr_calls);
297 EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall);
300 xencomm_hypercall_callback_op(int cmd, void *arg)
302 unsigned int argsize;
303 switch (cmd) {
304 case CALLBACKOP_register:
305 argsize = sizeof(struct callback_register);
306 break;
307 case CALLBACKOP_unregister:
308 argsize = sizeof(struct callback_unregister);
309 break;
310 default:
311 printk(KERN_DEBUG
312 "%s: unknown callback op %d\n", __func__, cmd);
313 return -ENOSYS;
316 return xencomm_arch_hypercall_callback_op
317 (cmd, xencomm_map_no_alloc(arg, argsize));
320 static int
321 xencommize_memory_reservation(struct xencomm_mini *xc_area,
322 struct xen_memory_reservation *mop)
324 struct xencomm_handle *desc;
326 desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start),
327 mop->nr_extents *
328 sizeof(*xen_guest_handle(mop->extent_start)),
329 xc_area);
330 if (desc == NULL)
331 return -EINVAL;
333 set_xen_guest_handle(mop->extent_start, (void *)desc);
334 return 0;
338 xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
340 GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
341 struct xen_memory_reservation *xmr = NULL;
342 int rc;
343 struct xencomm_handle *desc;
344 unsigned int argsize;
345 XENCOMM_MINI_ALIGNED(xc_area, 2);
347 switch (cmd) {
348 case XENMEM_increase_reservation:
349 case XENMEM_decrease_reservation:
350 case XENMEM_populate_physmap:
351 xmr = (struct xen_memory_reservation *)arg;
352 set_xen_guest_handle(extent_start_va[0],
353 xen_guest_handle(xmr->extent_start));
355 argsize = sizeof(*xmr);
356 rc = xencommize_memory_reservation(xc_area, xmr);
357 if (rc)
358 return rc;
359 xc_area++;
360 break;
362 case XENMEM_maximum_ram_page:
363 argsize = 0;
364 break;
366 case XENMEM_add_to_physmap:
367 argsize = sizeof(struct xen_add_to_physmap);
368 break;
370 default:
371 printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd);
372 return -ENOSYS;
375 desc = xencomm_map_no_alloc(arg, argsize);
376 if (desc == NULL)
377 return -EINVAL;
379 rc = xencomm_arch_hypercall_memory_op(cmd, desc);
381 switch (cmd) {
382 case XENMEM_increase_reservation:
383 case XENMEM_decrease_reservation:
384 case XENMEM_populate_physmap:
385 set_xen_guest_handle(xmr->extent_start,
386 xen_guest_handle(extent_start_va[0]));
387 break;
390 return rc;
392 EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op);
394 long
395 xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg)
397 unsigned int argsize;
398 switch (cmd) {
399 case VCPUOP_register_runstate_memory_area: {
400 struct vcpu_register_runstate_memory_area *area =
401 (struct vcpu_register_runstate_memory_area *)arg;
402 argsize = sizeof(*arg);
403 set_xen_guest_handle(area->addr.h,
404 (void *)xencomm_map_no_alloc(area->addr.v,
405 sizeof(area->addr.v)));
406 break;
409 default:
410 printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd);
411 return -ENOSYS;
414 return xencomm_arch_hypercall_vcpu_op(cmd, cpu,
415 xencomm_map_no_alloc(arg, argsize));
418 long
419 xencomm_hypercall_opt_feature(void *arg)
421 return xencomm_arch_hypercall_opt_feature(
422 xencomm_map_no_alloc(arg,
423 sizeof(struct xen_ia64_opt_feature)));