ia64/linux-2.6.18-xen.hg

view arch/ia64/xen/xcom_hcall.c @ 767:79bf5894b3f9

[IA64] xencomm: add PHYSDEVOP_pirq_eoi_gmfn support.

This patch fixes some weird issues in upstream.
Dom0 uses one page shared with hypervisor to notify which pirqs need EOI
writes, but the page is set incorrectly for ia64 due to following reasons:
1. the related two hypercalls are not enabled in the correct way, so this page
is not really used by dom0 and hypervisor do nothing when dom0 writes eoi.

Signed-off-by : Xiantao Zhang <xiantao.zhang@intel.com>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jan 05 14:13:49 2009 +0900 (2009-01-05)
parents ad300e728982
children 92a119f247f7
line source
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.
6 *
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.
11 *
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.
15 *
16 * Tristan Gingold <tristan.gingold@bull.net>
17 *
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.
22 */
23 #include <linux/types.h>
24 #include <linux/errno.h>
25 #include <linux/kernel.h>
26 #include <linux/gfp.h>
27 #include <linux/module.h>
28 #include <xen/interface/xen.h>
29 #include <xen/interface/platform.h>
30 #include <xen/interface/memory.h>
31 #include <xen/interface/xencomm.h>
32 #include <xen/interface/version.h>
33 #include <xen/interface/sched.h>
34 #include <xen/interface/event_channel.h>
35 #include <xen/interface/physdev.h>
36 #include <xen/interface/grant_table.h>
37 #include <xen/interface/callback.h>
38 #include <xen/interface/xsm/acm_ops.h>
39 #include <xen/interface/hvm/params.h>
40 #include <xen/interface/xenoprof.h>
41 #include <xen/interface/vcpu.h>
42 #include <xen/interface/kexec.h>
43 #include <asm/hypervisor.h>
44 #include <asm/page.h>
45 #include <asm/uaccess.h>
46 #include <asm/xen/xencomm.h>
47 #include <asm/perfmon.h>
49 /* Xencomm notes:
50 * This file defines hypercalls to be used by xencomm. The hypercalls simply
51 * create inlines or mini descriptors for pointers and then call the raw arch
52 * hypercall xencomm_arch_hypercall_XXX
53 *
54 * If the arch wants to directly use these hypercalls, simply define macros
55 * in asm/hypercall.h, eg:
56 * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op
57 *
58 * The arch may also define HYPERVISOR_xxx as a function and do more operations
59 * before/after doing the hypercall.
60 *
61 * Note: because only inline or mini descriptors are created these functions
62 * must only be called with in kernel memory parameters.
63 */
65 int
66 xencomm_hypercall_console_io(int cmd, int count, char *str)
67 {
68 return xencomm_arch_hypercall_console_io
69 (cmd, count, xencomm_map_no_alloc(str, count));
70 }
71 EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io);
73 static int
74 xencommize_event_channel_op(struct xencomm_mini **xc_area, void *op,
75 struct xencomm_handle **desc)
76 {
77 *desc = __xencomm_map_no_alloc(op, sizeof(evtchn_op_t), *xc_area);
78 if (*desc == NULL)
79 return -EINVAL;
80 (*xc_area)++;
81 return 0;
82 }
84 int
85 xencomm_hypercall_event_channel_op(int cmd, void *op)
86 {
87 int rc;
88 struct xencomm_handle *desc;
89 XENCOMM_MINI_ALIGNED(xc_area, 1);
91 rc = xencommize_event_channel_op(&xc_area, op, &desc);
92 if (rc)
93 return rc;
95 return xencomm_arch_hypercall_event_channel_op(cmd, desc);
96 }
97 EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op);
99 int
100 xencomm_hypercall_xen_version(int cmd, void *arg)
101 {
102 struct xencomm_handle *desc;
103 unsigned int argsize;
105 switch (cmd) {
106 case XENVER_version:
107 /* do not actually pass an argument */
108 return xencomm_arch_hypercall_xen_version(cmd, 0);
109 case XENVER_extraversion:
110 argsize = sizeof(xen_extraversion_t);
111 break;
112 case XENVER_compile_info:
113 argsize = sizeof(xen_compile_info_t);
114 break;
115 case XENVER_capabilities:
116 argsize = sizeof(xen_capabilities_info_t);
117 break;
118 case XENVER_changeset:
119 argsize = sizeof(xen_changeset_info_t);
120 break;
121 case XENVER_platform_parameters:
122 argsize = sizeof(xen_platform_parameters_t);
123 break;
124 case XENVER_pagesize:
125 argsize = (arg == NULL) ? 0 : sizeof(void *);
126 break;
127 case XENVER_get_features:
128 argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
129 break;
131 default:
132 printk("%s: unknown version op %d\n", __func__, cmd);
133 return -ENOSYS;
134 }
136 desc = xencomm_map_no_alloc(arg, argsize);
137 if (desc == NULL)
138 return -EINVAL;
140 return xencomm_arch_hypercall_xen_version(cmd, desc);
141 }
142 EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version);
144 static int
145 xencommize_physdev_op(struct xencomm_mini **xc_area, int cmd, void *op,
146 struct xencomm_handle **desc)
147 {
148 unsigned int argsize;
150 switch (cmd) {
151 case PHYSDEVOP_apic_read:
152 case PHYSDEVOP_apic_write:
153 argsize = sizeof(physdev_apic_t);
154 break;
155 case PHYSDEVOP_alloc_irq_vector:
156 case PHYSDEVOP_free_irq_vector:
157 argsize = sizeof(physdev_irq_t);
158 break;
159 case PHYSDEVOP_irq_status_query:
160 argsize = sizeof(physdev_irq_status_query_t);
161 break;
162 case PHYSDEVOP_manage_pci_add:
163 case PHYSDEVOP_manage_pci_remove:
164 argsize = sizeof(physdev_manage_pci_t);
165 break;
166 case PHYSDEVOP_map_pirq:
167 argsize = sizeof(physdev_map_pirq_t);
168 break;
169 case PHYSDEVOP_unmap_pirq:
170 argsize = sizeof(physdev_unmap_pirq_t);
171 break;
172 case PHYSDEVOP_pirq_eoi_gmfn:
173 argsize = sizeof(physdev_pirq_eoi_gmfn_t);
174 break;
176 default:
177 printk("%s: unknown physdev op %d\n", __func__, cmd);
178 return -ENOSYS;
179 }
181 *desc = __xencomm_map_no_alloc(op, argsize, *xc_area);
182 if (*desc == NULL)
183 return -EINVAL;
184 (*xc_area)++;
185 return 0;
186 }
188 int
189 xencomm_hypercall_physdev_op(int cmd, void *op)
190 {
191 int rc;
192 struct xencomm_handle *desc;
193 XENCOMM_MINI_ALIGNED(xc_area, 1);
195 rc = xencommize_physdev_op(&xc_area, cmd, op, &desc);
196 if (rc)
197 return rc;
199 return xencomm_arch_hypercall_physdev_op(cmd, desc);
200 }
202 static int
203 xencommize_grant_table_op(struct xencomm_mini **xc_area,
204 unsigned int cmd, void *op, unsigned int count,
205 struct xencomm_handle **desc)
206 {
207 struct xencomm_handle *desc1;
208 unsigned int argsize;
210 switch (cmd) {
211 case GNTTABOP_map_grant_ref:
212 argsize = sizeof(struct gnttab_map_grant_ref);
213 break;
214 case GNTTABOP_unmap_grant_ref:
215 argsize = sizeof(struct gnttab_unmap_grant_ref);
216 break;
217 case GNTTABOP_unmap_and_replace:
218 argsize = sizeof(struct gnttab_unmap_and_replace);
219 break;
220 case GNTTABOP_setup_table:
221 {
222 struct gnttab_setup_table *setup = op;
224 argsize = sizeof(*setup);
226 if (count != 1)
227 return -EINVAL;
228 desc1 = __xencomm_map_no_alloc
229 (xen_guest_handle(setup->frame_list),
230 setup->nr_frames *
231 sizeof(*xen_guest_handle(setup->frame_list)),
232 *xc_area);
233 if (desc1 == NULL)
234 return -EINVAL;
235 (*xc_area)++;
236 set_xen_guest_handle(setup->frame_list, (void *)desc1);
237 break;
238 }
239 case GNTTABOP_dump_table:
240 argsize = sizeof(struct gnttab_dump_table);
241 break;
242 case GNTTABOP_transfer:
243 argsize = sizeof(struct gnttab_transfer);
244 break;
245 case GNTTABOP_copy:
246 argsize = sizeof(struct gnttab_copy);
247 break;
248 case GNTTABOP_query_size:
249 argsize = sizeof(struct gnttab_query_size);
250 break;
251 default:
252 printk("%s: unknown hypercall grant table op %d\n",
253 __func__, cmd);
254 BUG();
255 }
257 *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area);
258 if (*desc == NULL)
259 return -EINVAL;
260 (*xc_area)++;
262 return 0;
263 }
265 int
266 xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
267 unsigned int count)
268 {
269 int rc;
270 struct xencomm_handle *desc;
271 XENCOMM_MINI_ALIGNED(xc_area, 2);
273 rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc);
274 if (rc)
275 return rc;
277 return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
278 }
279 EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op);
281 int
282 xencomm_hypercall_sched_op(int cmd, void *arg)
283 {
284 struct xencomm_handle *desc;
285 unsigned int argsize;
287 switch (cmd) {
288 case SCHEDOP_yield:
289 case SCHEDOP_block:
290 argsize = 0;
291 break;
292 case SCHEDOP_shutdown:
293 argsize = sizeof(sched_shutdown_t);
294 break;
295 case SCHEDOP_remote_shutdown:
296 argsize = sizeof(sched_remote_shutdown_t);
297 break;
298 case SCHEDOP_poll:
299 {
300 sched_poll_t *poll = arg;
301 struct xencomm_handle *ports;
303 argsize = sizeof(sched_poll_t);
304 ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports),
305 sizeof(*xen_guest_handle(poll->ports)));
307 set_xen_guest_handle(poll->ports, (void *)ports);
308 break;
309 }
310 default:
311 printk("%s: unknown sched op %d\n", __func__, cmd);
312 return -ENOSYS;
313 }
315 desc = xencomm_map_no_alloc(arg, argsize);
316 if (desc == NULL)
317 return -EINVAL;
319 return xencomm_arch_hypercall_sched_op(cmd, desc);
320 }
321 EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op);
323 int xencomm_hypercall_platform_op(struct xen_platform_op *arg)
324 {
325 return xencomm_arch_hypercall_platform_op(
326 xencomm_map_no_alloc(arg,
327 sizeof(struct xen_platform_op))
328 );
329 }
330 EXPORT_SYMBOL_GPL(xencomm_hypercall_platform_op);
332 int
333 xencomm_hypercall_multicall(void *call_list, int nr_calls)
334 {
335 int rc;
336 int i;
337 multicall_entry_t *mce;
338 struct xencomm_handle *desc;
339 XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2);
341 for (i = 0; i < nr_calls; i++) {
342 mce = (multicall_entry_t *)call_list + i;
344 switch (mce->op) {
345 case __HYPERVISOR_update_va_mapping:
346 case __HYPERVISOR_mmu_update:
347 /* No-op on ia64. */
348 break;
349 case __HYPERVISOR_grant_table_op:
350 rc = xencommize_grant_table_op
351 (&xc_area,
352 mce->args[0], (void *)mce->args[1],
353 mce->args[2], &desc);
354 if (rc)
355 return rc;
356 mce->args[1] = (unsigned long)desc;
357 break;
358 case __HYPERVISOR_event_channel_op:
359 rc = xencommize_event_channel_op(&xc_area,
360 (void *)mce->args[1],
361 &desc);
362 if (rc)
363 return rc;
364 mce->args[1] = (unsigned long)desc;
365 break;
366 case __HYPERVISOR_physdev_op:
367 switch (mce->args[0]) {
368 case PHYSDEVOP_eoi: {
369 struct physdev_eoi *eoi =
370 (struct physdev_eoi *)mce->args[1];
371 mce->op = __HYPERVISOR_ia64_fast_eoi;
372 mce->args[0] = eoi->irq;
373 break;
374 }
375 default:
376 rc = xencommize_physdev_op(&xc_area,
377 mce->args[0],
378 (void *)mce->args[1],
379 &desc);
380 if (rc)
381 return rc;
382 mce->args[1] = (unsigned long)desc;
383 break;
384 }
385 break;
386 case __HYPERVISOR_memory_op:
387 default:
388 printk("%s: unhandled multicall op entry op %lu\n",
389 __func__, mce->op);
390 return -ENOSYS;
391 }
392 }
394 desc = xencomm_map_no_alloc(call_list,
395 nr_calls * sizeof(multicall_entry_t));
396 if (desc == NULL)
397 return -EINVAL;
399 return xencomm_arch_hypercall_multicall(desc, nr_calls);
400 }
401 EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall);
403 int
404 xencomm_hypercall_callback_op(int cmd, void *arg)
405 {
406 unsigned int argsize;
407 switch (cmd)
408 {
409 case CALLBACKOP_register:
410 argsize = sizeof(struct callback_register);
411 break;
412 case CALLBACKOP_unregister:
413 argsize = sizeof(struct callback_unregister);
414 break;
415 default:
416 printk("%s: unknown callback op %d\n", __func__, cmd);
417 return -ENOSYS;
418 }
420 return xencomm_arch_hypercall_callback_op
421 (cmd, xencomm_map_no_alloc(arg, argsize));
422 }
424 static int
425 xencommize_memory_reservation(struct xencomm_mini **xc_area,
426 xen_memory_reservation_t *mop)
427 {
428 struct xencomm_handle *desc;
430 desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start),
431 mop->nr_extents *
432 sizeof(*xen_guest_handle(mop->extent_start)),
433 *xc_area);
434 if (desc == NULL)
435 return -EINVAL;
437 set_xen_guest_handle(mop->extent_start, (void *)desc);
438 (*xc_area)++;
439 return 0;
440 }
442 int
443 xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
444 {
445 XEN_GUEST_HANDLE(xen_pfn_t) extent_start_va[2];
446 xen_memory_reservation_t *xmr = NULL, *xme_in = NULL, *xme_out = NULL;
447 xen_memory_map_t *memmap = NULL;
448 XEN_GUEST_HANDLE(void) buffer;
449 int rc;
450 struct xencomm_handle *desc;
451 unsigned int argsize;
452 XENCOMM_MINI_ALIGNED(xc_area, 2);
454 switch (cmd) {
455 case XENMEM_increase_reservation:
456 case XENMEM_decrease_reservation:
457 case XENMEM_populate_physmap:
458 xmr = (xen_memory_reservation_t *)arg;
459 set_xen_guest_handle(extent_start_va[0],
460 xen_guest_handle(xmr->extent_start));
462 argsize = sizeof(*xmr);
463 rc = xencommize_memory_reservation(&xc_area, xmr);
464 if (rc)
465 return rc;
466 break;
468 case XENMEM_maximum_gpfn:
469 argsize = 0;
470 break;
472 case XENMEM_maximum_ram_page:
473 argsize = 0;
474 break;
476 case XENMEM_exchange:
477 xme_in = &((xen_memory_exchange_t *)arg)->in;
478 xme_out = &((xen_memory_exchange_t *)arg)->out;
479 set_xen_guest_handle(extent_start_va[0],
480 xen_guest_handle(xme_in->extent_start));
481 set_xen_guest_handle(extent_start_va[1],
482 xen_guest_handle(xme_out->extent_start));
484 argsize = sizeof(xen_memory_exchange_t);
485 rc = xencommize_memory_reservation(&xc_area, xme_in);
486 if (rc)
487 return rc;
488 rc = xencommize_memory_reservation(&xc_area, xme_out);
489 if (rc)
490 return rc;
491 break;
493 case XENMEM_add_to_physmap:
494 argsize = sizeof(xen_add_to_physmap_t);
495 break;
497 case XENMEM_machine_memory_map:
498 argsize = sizeof(*memmap);
499 memmap = (xen_memory_map_t *)arg;
500 set_xen_guest_handle(buffer, xen_guest_handle(memmap->buffer));
501 desc = xencomm_map_no_alloc(xen_guest_handle(memmap->buffer),
502 memmap->nr_entries);
503 if (desc == NULL)
504 return -EINVAL;
505 set_xen_guest_handle(memmap->buffer, (void *)desc);
506 break;
508 default:
509 printk("%s: unknown memory op %d\n", __func__, cmd);
510 return -ENOSYS;
511 }
513 desc = xencomm_map_no_alloc(arg, argsize);
514 if (desc == NULL)
515 return -EINVAL;
517 rc = xencomm_arch_hypercall_memory_op(cmd, desc);
519 switch (cmd) {
520 case XENMEM_increase_reservation:
521 case XENMEM_decrease_reservation:
522 case XENMEM_populate_physmap:
523 set_xen_guest_handle(xmr->extent_start,
524 xen_guest_handle(extent_start_va[0]));
525 break;
527 case XENMEM_exchange:
528 set_xen_guest_handle(xme_in->extent_start,
529 xen_guest_handle(extent_start_va[0]));
530 set_xen_guest_handle(xme_out->extent_start,
531 xen_guest_handle(extent_start_va[1]));
532 break;
534 case XENMEM_machine_memory_map:
535 set_xen_guest_handle(memmap->buffer, xen_guest_handle(buffer));
536 break;
537 }
539 return rc;
540 }
541 EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op);
543 unsigned long
544 xencomm_hypercall_hvm_op(int cmd, void *arg)
545 {
546 struct xencomm_handle *desc;
547 unsigned int argsize;
549 switch (cmd) {
550 case HVMOP_get_param:
551 case HVMOP_set_param:
552 argsize = sizeof(xen_hvm_param_t);
553 break;
554 default:
555 printk("%s: unknown HVMOP %d\n", __func__, cmd);
556 return -EINVAL;
557 }
559 desc = xencomm_map_no_alloc(arg, argsize);
560 if (desc == NULL)
561 return -EINVAL;
563 return xencomm_arch_hypercall_hvm_op(cmd, desc);
564 }
565 EXPORT_SYMBOL_GPL(xencomm_hypercall_hvm_op);
567 int
568 xencomm_hypercall_suspend(unsigned long srec)
569 {
570 struct sched_shutdown arg;
572 arg.reason = SHUTDOWN_suspend;
574 return xencomm_arch_hypercall_suspend(
575 xencomm_map_no_alloc(&arg, sizeof(arg)));
576 }
578 int
579 xencomm_hypercall_xenoprof_op(int op, void *arg)
580 {
581 unsigned int argsize;
582 struct xencomm_handle *desc;
584 switch (op) {
585 case XENOPROF_init:
586 argsize = sizeof(xenoprof_init_t);
587 break;
588 case XENOPROF_set_active:
589 argsize = sizeof(domid_t);
590 break;
591 case XENOPROF_set_passive:
592 argsize = sizeof(xenoprof_passive_t);
593 break;
594 case XENOPROF_counter:
595 argsize = sizeof(xenoprof_counter_t);
596 break;
597 case XENOPROF_get_buffer:
598 argsize = sizeof(xenoprof_get_buffer_t);
599 break;
601 case XENOPROF_reset_active_list:
602 case XENOPROF_reset_passive_list:
603 case XENOPROF_reserve_counters:
604 case XENOPROF_setup_events:
605 case XENOPROF_enable_virq:
606 case XENOPROF_start:
607 case XENOPROF_stop:
608 case XENOPROF_disable_virq:
609 case XENOPROF_release_counters:
610 case XENOPROF_shutdown:
611 return xencomm_arch_hypercall_xenoprof_op(op, arg);
613 default:
614 printk("%s: op %d isn't supported\n", __func__, op);
615 return -ENOSYS;
616 }
618 desc = xencomm_map_no_alloc(arg, argsize);
619 if (desc == NULL)
620 return -EINVAL;
622 return xencomm_arch_hypercall_xenoprof_op(op, desc);
623 }
624 EXPORT_SYMBOL_GPL(xencomm_hypercall_xenoprof_op);
626 int
627 xencomm_hypercall_perfmon_op(unsigned long cmd, void* arg,
628 unsigned long count)
629 {
630 unsigned int argsize;
631 struct xencomm_handle *desc;
633 switch (cmd) {
634 case PFM_GET_FEATURES:
635 argsize = sizeof(pfarg_features_t);
636 break;
637 case PFM_CREATE_CONTEXT:
638 argsize = sizeof(pfarg_context_t);
639 break;
640 case PFM_LOAD_CONTEXT:
641 argsize = sizeof(pfarg_load_t);
642 break;
643 case PFM_WRITE_PMCS:
644 case PFM_WRITE_PMDS:
645 argsize = sizeof(pfarg_reg_t) * count;
646 break;
648 case PFM_DESTROY_CONTEXT:
649 case PFM_UNLOAD_CONTEXT:
650 case PFM_START:
651 case PFM_STOP:
652 return xencomm_arch_hypercall_perfmon_op(cmd, arg, count);
654 default:
655 printk("%s:%d cmd %ld isn't supported\n",
656 __func__, __LINE__, cmd);
657 BUG();
658 }
660 desc = xencomm_map_no_alloc(arg, argsize);
661 if (desc == NULL)
662 return -EINVAL;
664 return xencomm_arch_hypercall_perfmon_op(cmd, desc, count);
665 }
666 EXPORT_SYMBOL_GPL(xencomm_hypercall_perfmon_op);
668 long
669 xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg)
670 {
671 unsigned int argsize;
672 switch (cmd) {
673 case VCPUOP_register_runstate_memory_area: {
674 vcpu_register_runstate_memory_area_t *area =
675 (vcpu_register_runstate_memory_area_t *)arg;
676 argsize = sizeof(*arg);
677 set_xen_guest_handle(area->addr.h,
678 (void *)xencomm_map_no_alloc(area->addr.v,
679 sizeof(area->addr.v)));
680 break;
681 }
683 default:
684 printk("%s: unknown vcpu op %d\n", __func__, cmd);
685 return -ENOSYS;
686 }
688 return xencomm_arch_hypercall_vcpu_op(cmd, cpu,
689 xencomm_map_no_alloc(arg, argsize));
690 }
692 long
693 xencomm_hypercall_opt_feature(void *arg)
694 {
695 return xencomm_arch_hypercall_opt_feature(
696 xencomm_map_no_alloc(arg,
697 sizeof(struct xen_ia64_opt_feature)));
698 }
700 int
701 xencomm_hypercall_fpswa_revision(unsigned int *revision)
702 {
703 struct xencomm_handle *desc;
705 desc = xencomm_map_no_alloc(revision, sizeof(*revision));
706 if (desc == NULL)
707 return -EINVAL;
709 return xencomm_arch_hypercall_fpswa_revision(desc);
710 }
711 EXPORT_SYMBOL_GPL(xencomm_hypercall_fpswa_revision);
713 int
714 xencomm_hypercall_kexec_op(int cmd, void *arg)
715 {
716 unsigned int argsize;
717 struct xencomm_handle *desc;
719 switch (cmd) {
720 case KEXEC_CMD_kexec_get_range:
721 argsize = sizeof(xen_kexec_range_t);
722 break;
723 case KEXEC_CMD_kexec_load:
724 case KEXEC_CMD_kexec_unload:
725 argsize = sizeof(xen_kexec_load_t);
726 break;
727 case KEXEC_CMD_kexec:
728 argsize = sizeof(xen_kexec_exec_t);
729 break;
730 default:
731 printk("%s:%d cmd %d isn't supported\n",
732 __func__, __LINE__, cmd);
733 BUG();
734 }
736 desc = xencomm_map_no_alloc(arg, argsize);
737 if (desc == NULL)
738 return -EINVAL;
740 return xencomm_arch_hypercall_kexec_op(cmd, desc);
741 }