2
* Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
3
* Tristan Gingold <tristan.gingold@bull.net>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
* This code is mostly taken from ia64-xen files xcom_mini.c and xencomm.c.
22
* Changes: Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com
26
#include <mini-os/os.h>
27
#include <mini-os/errno.h>
28
#include <mini-os/lib.h>
29
#include <mini-os/hypervisor.h>
30
#include <xen/xencomm.h>
31
#include <xen/grant_table.h>
34
#define XENCOMM_MINI_ADDRS 3
37
struct xencomm_desc _desc;
38
uint64_t address[XENCOMM_MINI_ADDRS];
41
#define xen_guest_handle(hnd) ((hnd).p)
43
struct xencomm_handle;
45
/* Translate virtual address to physical address. */
47
xencomm_vaddr_to_paddr(uint64_t vaddr)
49
if (IA64_RR_EXTR(vaddr) == 5)
50
return KERN_VIRT_2_PHYS(vaddr);
52
if (IA64_RR_EXTR(vaddr) == 7)
58
/* Inline version. To be used only on linear space (kernel space). */
59
static struct xencomm_handle *
60
xencomm_create_inline(void *buffer)
64
paddr = xencomm_vaddr_to_paddr((unsigned long)buffer);
65
return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
68
#define min(a,b) (((a) < (b)) ? (a) : (b))
70
xencomm_init_desc(struct xencomm_desc *desc, void *buffer, unsigned long bytes)
72
unsigned long recorded = 0;
75
if ((buffer == NULL) && (bytes > 0))
78
/* record the physical pages used */
82
while ((recorded < bytes) && (i < desc->nr_addrs)) {
83
unsigned long vaddr = (unsigned long)buffer + recorded;
88
offset = vaddr % PAGE_SIZE; /* handle partial pages */
89
chunksz = min(PAGE_SIZE - offset, bytes - recorded);
91
paddr = xencomm_vaddr_to_paddr(vaddr);
93
printk("%s: couldn't translate vaddr %lx\n",
98
desc->address[i++] = paddr;
101
if (recorded < bytes) {
102
printk("%s: could only translate %ld of %ld bytes\n",
103
__func__, recorded, bytes);
107
/* mark remaining addresses invalid (just for safety) */
108
while (i < desc->nr_addrs)
109
desc->address[i++] = XENCOMM_INVALID;
110
desc->magic = XENCOMM_MAGIC;
115
xencomm_alloc_mini(struct xencomm_mini *area, int *nbr_area)
118
unsigned int pageoffset;
120
while (*nbr_area >= 0) {
121
/* Allocate an area. */
124
base = (unsigned long)(area + *nbr_area);
125
pageoffset = base % PAGE_SIZE;
127
/* If the area does not cross a page, use it. */
128
if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini))
129
return &area[*nbr_area];
136
xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
137
void *buffer, unsigned long bytes,
138
struct xencomm_handle **ret)
140
struct xencomm_desc *desc;
144
desc = xencomm_alloc_mini(area, nbr_area);
147
desc->nr_addrs = XENCOMM_MINI_ADDRS;
149
rc = xencomm_init_desc(desc, buffer, bytes);
153
res = xencomm_vaddr_to_paddr((unsigned long)desc);
157
*ret = (struct xencomm_handle*)res;
162
xencommize_mini_grant_table_op(struct xencomm_mini *xc_area, int *nbr_area,
163
unsigned int cmd, void *op, unsigned int count,
164
struct xencomm_handle **desc)
166
struct xencomm_handle *desc1;
167
unsigned int argsize=0;
171
case GNTTABOP_map_grant_ref:
172
argsize = sizeof(struct gnttab_map_grant_ref);
174
case GNTTABOP_unmap_grant_ref:
175
argsize = sizeof(struct gnttab_unmap_grant_ref);
177
case GNTTABOP_setup_table:
179
struct gnttab_setup_table *setup = op;
181
argsize = sizeof(*setup);
185
rc = xencomm_create_mini
187
(void*)(uint64_t) xen_guest_handle(setup->frame_list),
189
* sizeof(*xen_guest_handle(setup->frame_list)),
193
set_xen_guest_handle(setup->frame_list,
194
(void *)(uint64_t)desc1);
197
case GNTTABOP_dump_table:
198
argsize = sizeof(struct gnttab_dump_table);
200
case GNTTABOP_transfer:
201
argsize = sizeof(struct gnttab_transfer);
204
argsize = sizeof(struct gnttab_copy);
207
printk("%s: unknown mini grant table op %d\n", __func__, cmd);
211
rc = xencomm_create_mini(xc_area, nbr_area, op, count * argsize, desc);
217
xencomm_arch_hypercall_grant_table_op(unsigned int cmd,
218
struct xencomm_handle *uop,
221
return _hypercall3(int, grant_table_op, cmd, uop, count);
225
xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
229
struct xencomm_handle *desc;
231
struct xencomm_mini xc_area[2];
233
rc = xencommize_mini_grant_table_op(xc_area, &nbr_area,
234
cmd, op, count, &desc);
237
return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
241
gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
247
if (flags & GNTMAP_host_map) {
248
if (flags & GNTMAP_application_map) {
249
printk("GNTMAP_application_map is not supported yet: "
250
"flags 0x%x\n", flags);
253
if (flags & GNTMAP_contains_pte) {
254
printk("GNTMAP_contains_pte is not supported yet flags "
258
} else if (flags & GNTMAP_device_map) {
259
printk("GNTMAP_device_map is not supported yet 0x%x\n", flags);
260
BUG();//XXX not yet. actually this flag is not used.
267
HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
269
if (cmd == GNTTABOP_map_grant_ref) {
271
for (i = 0; i < count; i++) {
272
gnttab_map_grant_ref_pre(
273
(struct gnttab_map_grant_ref*)uop + i);
276
return xencomm_mini_hypercall_grant_table_op(cmd, uop, count);
280
extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
282
HYPERVISOR_suspend(unsigned long srec)
284
struct sched_shutdown arg;
286
arg.reason = (uint32_t)SHUTDOWN_suspend;
288
return xencomm_arch_hypercall_suspend(xencomm_create_inline(&arg));
292
HYPERVISOR_event_channel_op(int cmd, void *arg)
295
struct xencomm_handle *newArg;
297
newArg = xencomm_create_inline(arg);
298
rc = _hypercall2(int, event_channel_op, cmd, newArg);
299
if (unlikely(rc == -ENOSYS)) {
303
memcpy(&op.u, arg, sizeof(op.u));
304
rc = _hypercall1(int, event_channel_op_compat, &op);
310
xencomm_arch_xen_version(int cmd, struct xencomm_handle *arg)
312
return _hypercall2(int, xen_version, cmd, arg);
316
xencomm_arch_xen_feature(int cmd, struct xencomm_handle *arg)
318
struct xencomm_handle *newArg;
320
newArg = xencomm_create_inline(arg);
321
return _hypercall2(int, xen_version, cmd, newArg);
325
HYPERVISOR_xen_version(int cmd, void *arg)
329
return xencomm_arch_xen_version(cmd, 0);
330
case XENVER_get_features:
331
return xencomm_arch_xen_feature(cmd, arg);
338
HYPERVISOR_console_io(int cmd, int count, char *str)
340
struct xencomm_handle *newStr;
342
newStr = xencomm_create_inline(str);
343
return _hypercall3(int, console_io, cmd, count, newStr);
347
HYPERVISOR_sched_op_compat(int cmd, unsigned long arg)
349
return _hypercall2(int, sched_op_compat, cmd, arg);
353
HYPERVISOR_sched_op(int cmd, void *arg)
355
struct xencomm_handle *newArg;
357
newArg = xencomm_create_inline(arg);
358
return _hypercall2(int, sched_op, cmd, newArg);
362
HYPERVISOR_callback_op(int cmd, void *arg)
364
struct xencomm_handle *newArg;
366
newArg = xencomm_create_inline(arg);
367
return _hypercall2(int, callback_op, cmd, newArg);
371
HYPERVISOR_opt_feature(void *arg)
373
struct xencomm_handle *new_arg;
375
new_arg = xencomm_create_inline(arg);
377
return _hypercall1(int, opt_feature, new_arg);
381
HYPERVISOR_shutdown(unsigned int reason)
383
struct sched_shutdown sched_shutdown = {
387
int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
390
rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);