source: trunk/packages/xen-common/xen-common/extras/mini-os/arch/ia64/xencomm.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 6.5 KB
Line 
1/*
2 * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
3 * Tristan Gingold <tristan.gingold@bull.net>
4 *
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.
9 *
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.
14 *
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
18 */
19
20/*
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
23 */
24
25
26#include <os.h>
27#include <hypervisor.h>
28#include <xen/xencomm.h>
29#include <xen/grant_table.h>
30
31
32#define XENCOMM_MINI_ADDRS 3
33struct xencomm_mini
34{
35        struct xencomm_desc _desc;
36        uint64_t address[XENCOMM_MINI_ADDRS];
37};
38
39#define xen_guest_handle(hnd)  ((hnd).p)
40
41
42/* Translate virtual address to physical address.  */
43uint64_t
44xencomm_vaddr_to_paddr(uint64_t vaddr)
45{
46        if (IA64_RR_EXTR(vaddr) == 5)
47                return KERN_VIRT_2_PHYS(vaddr);
48
49        if (IA64_RR_EXTR(vaddr) == 7)
50                return __pa(vaddr);
51
52        return 0;
53}
54
55#define min(a,b) (((a) < (b)) ? (a) : (b))
56static int
57xencomm_init_desc(struct xencomm_desc *desc, void *buffer, unsigned long bytes)
58{
59        unsigned long recorded = 0;
60        int i = 0;
61
62        if ((buffer == NULL) && (bytes > 0))
63                BUG();
64
65        /* record the physical pages used */
66        if (buffer == NULL)
67                desc->nr_addrs = 0;
68
69        while ((recorded < bytes) && (i < desc->nr_addrs)) {
70                unsigned long vaddr = (unsigned long)buffer + recorded;
71                unsigned long paddr;
72                int offset;
73                int chunksz;
74
75                offset = vaddr % PAGE_SIZE; /* handle partial pages */
76                chunksz = min(PAGE_SIZE - offset, bytes - recorded);
77
78                paddr = xencomm_vaddr_to_paddr(vaddr);
79                if (paddr == ~0UL) {
80                        printk("%s: couldn't translate vaddr %lx\n",
81                               __func__, vaddr);
82                        return -EINVAL;
83                }
84
85                desc->address[i++] = SWAP(paddr);
86                recorded += chunksz;
87        }
88        if (recorded < bytes) {
89                printk("%s: could only translate %ld of %ld bytes\n",
90                       __func__, recorded, bytes);
91                return -ENOSPC;
92        }
93
94        /* mark remaining addresses invalid (just for safety) */
95        while (i < desc->nr_addrs)
96                desc->address[i++] = SWAP(XENCOMM_INVALID);
97        desc->magic = SWAP(XENCOMM_MAGIC);
98        return 0;
99}
100
101static void *
102xencomm_alloc_mini(struct xencomm_mini *area, int *nbr_area)
103{
104        unsigned long base;
105        unsigned int pageoffset;
106
107        while (*nbr_area >= 0) {
108                /* Allocate an area.  */
109                (*nbr_area)--;
110
111                base = (unsigned long)(area + *nbr_area);
112                pageoffset = base % PAGE_SIZE; 
113
114                /* If the area does not cross a page, use it.  */
115                if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini))
116                        return &area[*nbr_area];
117        }
118        /* No more area.  */
119        return NULL;
120}
121
122int
123xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
124                    void *buffer, unsigned long bytes,
125                    struct xencomm_handle **ret)
126{
127        struct xencomm_desc *desc;
128        int rc;
129        unsigned long res;
130
131        desc = xencomm_alloc_mini(area, nbr_area);
132        if (!desc)
133                return -ENOMEM;
134        desc->nr_addrs = XENCOMM_MINI_ADDRS;
135
136        rc = xencomm_init_desc(desc, buffer, bytes);
137        if (rc)
138                return rc;
139
140        res = xencomm_vaddr_to_paddr((unsigned long)desc);
141        if (res == ~0UL)
142                return -EINVAL;
143
144        *ret = (struct xencomm_handle*)res;
145        return 0;
146}
147
148static int
149xencommize_mini_grant_table_op(struct xencomm_mini *xc_area, int *nbr_area,
150                               unsigned int cmd, void *op, unsigned int count,
151                               struct xencomm_handle **desc)
152{
153        struct xencomm_handle *desc1;
154        unsigned int argsize=0;
155        int rc;
156
157        switch (cmd) {
158        case GNTTABOP_map_grant_ref:
159                argsize = sizeof(struct gnttab_map_grant_ref);
160                break;
161        case GNTTABOP_unmap_grant_ref:
162                argsize = sizeof(struct gnttab_unmap_grant_ref);
163                break;
164        case GNTTABOP_setup_table:
165        {
166                struct gnttab_setup_table *setup = op;
167
168                argsize = sizeof(*setup);
169
170                if (count != 1)
171                        return -EINVAL;
172                rc = xencomm_create_mini
173                        (xc_area, nbr_area,
174                         (void*)SWAP((uint64_t)
175                                     xen_guest_handle(setup->frame_list)),
176                         SWAP(setup->nr_frames)
177                         * sizeof(*xen_guest_handle(setup->frame_list)),
178                         &desc1);
179                if (rc)
180                        return rc;
181                set_xen_guest_handle(setup->frame_list,
182                                     (void *)SWAP((uint64_t)desc1));
183                break;
184        }
185        case GNTTABOP_dump_table:
186                argsize = sizeof(struct gnttab_dump_table);
187                break;
188        case GNTTABOP_transfer:
189                argsize = sizeof(struct gnttab_transfer);
190                break;
191        case GNTTABOP_copy:
192                argsize = sizeof(struct gnttab_copy);
193                break;
194        default:
195                printk("%s: unknown mini grant table op %d\n", __func__, cmd);
196                BUG();
197        }
198
199        rc = xencomm_create_mini(xc_area, nbr_area, op, count * argsize, desc);
200
201        return rc;
202}
203
204int
205xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
206                                      unsigned int count)
207{
208        int rc;
209        struct xencomm_handle *desc;
210        int nbr_area = 2;
211        struct xencomm_mini xc_area[2];
212
213        rc = xencommize_mini_grant_table_op(xc_area, &nbr_area,
214                                            cmd, op, count, &desc);
215        if (rc)
216                return rc;
217        return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
218}
219
220static void
221gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
222{
223        uint32_t flags;
224
225        flags = uop->flags;
226
227        if (flags & GNTMAP_host_map) {
228                if (flags & GNTMAP_application_map) {
229                        printk("GNTMAP_application_map is not supported yet: "
230                               "flags 0x%x\n", flags);
231                        BUG();
232                }
233                if (flags & GNTMAP_contains_pte) {
234                        printk("GNTMAP_contains_pte is not supported yet flags "
235                               "0x%x\n", flags);
236                        BUG();
237                }
238        } else if (flags & GNTMAP_device_map) {
239                printk("GNTMAP_device_map is not supported yet 0x%x\n", flags);
240                BUG();//XXX not yet. actually this flag is not used.
241        } else {
242                BUG();
243        }
244}
245
246int
247HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
248{
249        if (cmd == GNTTABOP_map_grant_ref) {
250                unsigned int i;
251                for (i = 0; i < count; i++) {
252                        gnttab_map_grant_ref_pre(
253                                (struct gnttab_map_grant_ref*)uop + i);
254                }
255        }
256        return xencomm_mini_hypercall_grant_table_op(cmd, uop, count);
257}
258
259        /* In fw.S */
260extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
261int
262HYPERVISOR_suspend(unsigned long srec)
263{
264        struct sched_shutdown arg;
265
266        arg.reason = (uint32_t)SWAP((uint32_t)SHUTDOWN_suspend);
267
268        return xencomm_arch_hypercall_suspend(xencomm_create_inline(&arg));
269}
270
Note: See TracBrowser for help on using the repository browser.