V4L/DVB: cx231xx: improve error handling
[wandboard.git] / arch / ia64 / xen / xcom_hcall.c
blobccaf7431f7c89b510841b65443f674d5f09c7781
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 /* xen early printk uses console io hypercall before
53 * xencomm initialization. In that case, we just ignore it.
55 if (!xencomm_is_initialized())
56 return 0;
58 return xencomm_arch_hypercall_console_io
59 (cmd, count, xencomm_map_no_alloc(str, count));
61 EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io);
63 int
64 xencomm_hypercall_event_channel_op(int cmd, void *op)
66 struct xencomm_handle *desc;
67 desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op));
68 if (desc == NULL)
69 return -EINVAL;
71 return xencomm_arch_hypercall_event_channel_op(cmd, desc);
73 EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op);
75 int
76 xencomm_hypercall_xen_version(int cmd, void *arg)
78 struct xencomm_handle *desc;
79 unsigned int argsize;
81 switch (cmd) {
82 case XENVER_version:
83 /* do not actually pass an argument */
84 return xencomm_arch_hypercall_xen_version(cmd, 0);
85 case XENVER_extraversion:
86 argsize = sizeof(struct xen_extraversion);
87 break;
88 case XENVER_compile_info:
89 argsize = sizeof(struct xen_compile_info);
90 break;
91 case XENVER_capabilities:
92 argsize = sizeof(struct xen_capabilities_info);
93 break;
94 case XENVER_changeset:
95 argsize = sizeof(struct xen_changeset_info);
96 break;
97 case XENVER_platform_parameters:
98 argsize = sizeof(struct xen_platform_parameters);
99 break;
100 case XENVER_get_features:
101 argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info);
102 break;
104 default:
105 printk(KERN_DEBUG
106 "%s: unknown version op %d\n", __func__, cmd);
107 return -ENOSYS;
110 desc = xencomm_map_no_alloc(arg, argsize);
111 if (desc == NULL)
112 return -EINVAL;
114 return xencomm_arch_hypercall_xen_version(cmd, desc);
116 EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version);
119 xencomm_hypercall_physdev_op(int cmd, void *op)
121 unsigned int argsize;
123 switch (cmd) {
124 case PHYSDEVOP_apic_read:
125 case PHYSDEVOP_apic_write:
126 argsize = sizeof(struct physdev_apic);
127 break;
128 case PHYSDEVOP_alloc_irq_vector:
129 case PHYSDEVOP_free_irq_vector:
130 argsize = sizeof(struct physdev_irq);
131 break;
132 case PHYSDEVOP_irq_status_query:
133 argsize = sizeof(struct physdev_irq_status_query);
134 break;
136 default:
137 printk(KERN_DEBUG
138 "%s: unknown physdev op %d\n", __func__, cmd);
139 return -ENOSYS;
142 return xencomm_arch_hypercall_physdev_op
143 (cmd, xencomm_map_no_alloc(op, argsize));
146 static int
147 xencommize_grant_table_op(struct xencomm_mini **xc_area,
148 unsigned int cmd, void *op, unsigned int count,
149 struct xencomm_handle **desc)
151 struct xencomm_handle *desc1;
152 unsigned int argsize;
154 switch (cmd) {
155 case GNTTABOP_map_grant_ref:
156 argsize = sizeof(struct gnttab_map_grant_ref);
157 break;
158 case GNTTABOP_unmap_grant_ref:
159 argsize = sizeof(struct gnttab_unmap_grant_ref);
160 break;
161 case GNTTABOP_setup_table:
163 struct gnttab_setup_table *setup = op;
165 argsize = sizeof(*setup);
167 if (count != 1)
168 return -EINVAL;
169 desc1 = __xencomm_map_no_alloc
170 (xen_guest_handle(setup->frame_list),
171 setup->nr_frames *
172 sizeof(*xen_guest_handle(setup->frame_list)),
173 *xc_area);
174 if (desc1 == NULL)
175 return -EINVAL;
176 (*xc_area)++;
177 set_xen_guest_handle(setup->frame_list, (void *)desc1);
178 break;
180 case GNTTABOP_dump_table:
181 argsize = sizeof(struct gnttab_dump_table);
182 break;
183 case GNTTABOP_transfer:
184 argsize = sizeof(struct gnttab_transfer);
185 break;
186 case GNTTABOP_copy:
187 argsize = sizeof(struct gnttab_copy);
188 break;
189 case GNTTABOP_query_size:
190 argsize = sizeof(struct gnttab_query_size);
191 break;
192 default:
193 printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n",
194 __func__, cmd);
195 BUG();
198 *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area);
199 if (*desc == NULL)
200 return -EINVAL;
201 (*xc_area)++;
203 return 0;
207 xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
208 unsigned int count)
210 int rc;
211 struct xencomm_handle *desc;
212 XENCOMM_MINI_ALIGNED(xc_area, 2);
214 rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc);
215 if (rc)
216 return rc;
218 return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
220 EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op);
223 xencomm_hypercall_sched_op(int cmd, void *arg)
225 struct xencomm_handle *desc;
226 unsigned int argsize;
228 switch (cmd) {
229 case SCHEDOP_yield:
230 case SCHEDOP_block:
231 argsize = 0;
232 break;
233 case SCHEDOP_shutdown:
234 argsize = sizeof(struct sched_shutdown);
235 break;
236 case SCHEDOP_poll:
238 struct sched_poll *poll = arg;
239 struct xencomm_handle *ports;
241 argsize = sizeof(struct sched_poll);
242 ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports),
243 sizeof(*xen_guest_handle(poll->ports)));
245 set_xen_guest_handle(poll->ports, (void *)ports);
246 break;
248 default:
249 printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd);
250 return -ENOSYS;
253 desc = xencomm_map_no_alloc(arg, argsize);
254 if (desc == NULL)
255 return -EINVAL;
257 return xencomm_arch_hypercall_sched_op(cmd, desc);
259 EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op);
262 xencomm_hypercall_multicall(void *call_list, int nr_calls)
264 int rc;
265 int i;
266 struct multicall_entry *mce;
267 struct xencomm_handle *desc;
268 XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2);
270 for (i = 0; i < nr_calls; i++) {
271 mce = (struct multicall_entry *)call_list + i;
273 switch (mce->op) {
274 case __HYPERVISOR_update_va_mapping:
275 case __HYPERVISOR_mmu_update:
276 /* No-op on ia64. */
277 break;
278 case __HYPERVISOR_grant_table_op:
279 rc = xencommize_grant_table_op
280 (&xc_area,
281 mce->args[0], (void *)mce->args[1],
282 mce->args[2], &desc);
283 if (rc)
284 return rc;
285 mce->args[1] = (unsigned long)desc;
286 break;
287 case __HYPERVISOR_memory_op:
288 default:
289 printk(KERN_DEBUG
290 "%s: unhandled multicall op entry op %lu\n",
291 __func__, mce->op);
292 return -ENOSYS;
296 desc = xencomm_map_no_alloc(call_list,
297 nr_calls * sizeof(struct multicall_entry));
298 if (desc == NULL)
299 return -EINVAL;
301 return xencomm_arch_hypercall_multicall(desc, nr_calls);
303 EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall);
306 xencomm_hypercall_callback_op(int cmd, void *arg)
308 unsigned int argsize;
309 switch (cmd) {
310 case CALLBACKOP_register:
311 argsize = sizeof(struct callback_register);
312 break;
313 case CALLBACKOP_unregister:
314 argsize = sizeof(struct callback_unregister);
315 break;
316 default:
317 printk(KERN_DEBUG
318 "%s: unknown callback op %d\n", __func__, cmd);
319 return -ENOSYS;
322 return xencomm_arch_hypercall_callback_op
323 (cmd, xencomm_map_no_alloc(arg, argsize));
326 static int
327 xencommize_memory_reservation(struct xencomm_mini *xc_area,
328 struct xen_memory_reservation *mop)
330 struct xencomm_handle *desc;
332 desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start),
333 mop->nr_extents *
334 sizeof(*xen_guest_handle(mop->extent_start)),
335 xc_area);
336 if (desc == NULL)
337 return -EINVAL;
339 set_xen_guest_handle(mop->extent_start, (void *)desc);
340 return 0;
344 xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
346 GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} };
347 struct xen_memory_reservation *xmr = NULL;
348 int rc;
349 struct xencomm_handle *desc;
350 unsigned int argsize;
351 XENCOMM_MINI_ALIGNED(xc_area, 2);
353 switch (cmd) {
354 case XENMEM_increase_reservation:
355 case XENMEM_decrease_reservation:
356 case XENMEM_populate_physmap:
357 xmr = (struct xen_memory_reservation *)arg;
358 set_xen_guest_handle(extent_start_va[0],
359 xen_guest_handle(xmr->extent_start));
361 argsize = sizeof(*xmr);
362 rc = xencommize_memory_reservation(xc_area, xmr);
363 if (rc)
364 return rc;
365 xc_area++;
366 break;
368 case XENMEM_maximum_ram_page:
369 argsize = 0;
370 break;
372 case XENMEM_add_to_physmap:
373 argsize = sizeof(struct xen_add_to_physmap);
374 break;
376 default:
377 printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd);
378 return -ENOSYS;
381 desc = xencomm_map_no_alloc(arg, argsize);
382 if (desc == NULL)
383 return -EINVAL;
385 rc = xencomm_arch_hypercall_memory_op(cmd, desc);
387 switch (cmd) {
388 case XENMEM_increase_reservation:
389 case XENMEM_decrease_reservation:
390 case XENMEM_populate_physmap:
391 set_xen_guest_handle(xmr->extent_start,
392 xen_guest_handle(extent_start_va[0]));
393 break;
396 return rc;
398 EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op);
401 xencomm_hypercall_suspend(unsigned long srec)
403 struct sched_shutdown arg;
405 arg.reason = SHUTDOWN_suspend;
407 return xencomm_arch_hypercall_sched_op(
408 SCHEDOP_shutdown, xencomm_map_no_alloc(&arg, sizeof(arg)));
411 long
412 xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg)
414 unsigned int argsize;
415 switch (cmd) {
416 case VCPUOP_register_runstate_memory_area: {
417 struct vcpu_register_runstate_memory_area *area =
418 (struct vcpu_register_runstate_memory_area *)arg;
419 argsize = sizeof(*arg);
420 set_xen_guest_handle(area->addr.h,
421 (void *)xencomm_map_no_alloc(area->addr.v,
422 sizeof(area->addr.v)));
423 break;
426 default:
427 printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd);
428 return -ENOSYS;
431 return xencomm_arch_hypercall_vcpu_op(cmd, cpu,
432 xencomm_map_no_alloc(arg, argsize));
435 long
436 xencomm_hypercall_opt_feature(void *arg)
438 return xencomm_arch_hypercall_opt_feature(
439 xencomm_map_no_alloc(arg,
440 sizeof(struct xen_ia64_opt_feature)));