ia64/xen-unstable

view tools/ioemu/block-vbd.c @ 17042:a905c582a406

Add stubdomain support. See stubdom/README for usage details.

- Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in
arch_limits.h so as to permit getting them from there without
pulling all the internal Mini-OS defines.
- Setup a xen-elf cross-compilation environment in stubdom/cross-root
- Add a POSIX layer on top of Mini-OS by linking against the newlib C
library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c
- Cross-compile zlib and libpci too.
- Add an xs.h-compatible layer on top of Mini-OS' xenbus.
- Cross-compile libxc with an additional xc_minios.c and a few things
disabled.
- Cross-compile ioemu with an additional block-vbd, but without sound,
tpm and other details. A few hacks are needed:
- Align ide and scsi buffers at least on sector size to permit
direct transmission to the block backend. While we are at it, just
page-align it to possibly save a segment. Also, limit the scsi
buffer size because of limitations of the block paravirtualization
protocol.
- Allocate big tables dynamically rather that letting them go to
bss: when Mini-OS gets installed in memory, bss is not lazily
allocated, and doing so during Mini-OS is unnecessarily trick while
we can simply use malloc.
- Had to change the Mini-OS compilation somehow, so as to export
Mini-OS compilation flags to the Makefiles of libxc and ioemu.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Feb 12 14:35:39 2008 +0000 (2008-02-12)
parents
children c1003b9e0bb8
line source
1 /*
2 * Block driver for Mini-os PV devices
3 * Based on block-raw.c
4 *
5 * Copyright (c) 2006 Fabrice Bellard, 2007 Samuel Thibault
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25 #include "vl.h"
26 #include "block_int.h"
27 #include <assert.h>
28 #include <xenbus.h>
29 #include <blkfront.h>
30 #include <malloc.h>
32 #define SECTOR_SIZE 512
34 #ifndef QEMU_TOOL
35 #include "exec-all.h"
36 #endif
38 #define DEBUG_BLOCK
39 #ifdef DEBUG_BLOCK
40 #define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile )
41 #else
42 #define DEBUG_BLOCK_PRINT( formatCstr, args... )
43 #endif
45 #define FTYPE_FILE 0
46 #define FTYPE_CD 1
47 #define FTYPE_FD 2
49 typedef struct BDRVVbdState {
50 struct blkfront_dev *dev;
51 int fd;
52 int type;
53 int mode;
54 uint64_t sectors;
55 unsigned sector_size;
56 QEMU_LIST_ENTRY(BDRVVbdState) list;
57 } BDRVVbdState;
59 QEMU_LIST_HEAD(, BDRVVbdState) vbds;
61 static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename)
62 {
63 char *value;
64 if (xenbus_read(XBT_NIL, filename, &value))
65 return 0;
66 free(value);
67 return 100;
68 }
70 static int vbd_open(BlockDriverState *bs, const char *filename, int flags)
71 {
72 BDRVVbdState *s = bs->opaque;
74 //handy to test posix access
75 //return -EIO;
77 s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, &s->mode);
79 if (!s->dev)
80 return -EIO;
82 if (SECTOR_SIZE % s->sector_size) {
83 printf("sector size is %d, we only support sector sizes that divide %d\n", s->sector_size, SECTOR_SIZE);
84 return -EIO;
85 }
87 s->fd = blkfront_open(s->dev);
89 QEMU_LIST_INSERT_HEAD(&vbds, s, list);
91 return 0;
92 }
94 typedef struct VbdAIOCB {
95 BlockDriverAIOCB common;
96 struct blkfront_aiocb aiocb;
97 } VbdAIOCB;
99 void qemu_aio_init(void)
100 {
101 }
103 void qemu_aio_poll(void)
104 {
105 BDRVVbdState *s;
106 for (s = vbds.lh_first; s; s = s->list.le_next)
107 blkfront_aio_poll(s->dev);
108 }
110 /* Wait for all IO requests to complete. */
111 void qemu_aio_flush(void)
112 {
113 BDRVVbdState *s;
114 for (s = vbds.lh_first; s; s = s->list.le_next)
115 blkfront_sync(s->dev);
116 }
118 void qemu_aio_wait_start(void)
119 {
120 }
122 void qemu_aio_wait(void)
123 {
124 int some = 0;
125 DEFINE_WAIT(w);
126 while (1) {
127 BDRVVbdState *s;
128 add_waiter(w, blkfront_queue);
129 for (s = vbds.lh_first; s; s = s->list.le_next)
130 if (blkfront_aio_poll(s->dev))
131 some = 1;
132 if (some)
133 break;
134 schedule();
135 }
136 remove_waiter(w);
137 }
139 void qemu_aio_wait_end(void)
140 {
141 }
143 static void vbd_aio_callback(struct blkfront_aiocb *aiocbp, int ret) {
144 VbdAIOCB *acb = aiocbp->data;
146 acb->common.cb(acb->common.opaque, ret);
147 qemu_aio_release(acb);
148 }
150 static VbdAIOCB *vbd_aio_setup(BlockDriverState *bs,
151 int64_t sector_num, uint8_t *buf, int nb_sectors,
152 BlockDriverCompletionFunc *cb, void *opaque)
153 {
154 BDRVVbdState *s = bs->opaque;
155 VbdAIOCB *acb;
157 acb = qemu_aio_get(bs, cb, opaque);
158 if (!acb)
159 return NULL;
160 acb->aiocb.aio_dev = s->dev;
161 acb->aiocb.aio_buf = buf;
162 acb->aiocb.aio_nbytes = nb_sectors * SECTOR_SIZE;
163 acb->aiocb.aio_offset = sector_num * SECTOR_SIZE;
164 acb->aiocb.aio_cb = vbd_aio_callback;
165 acb->aiocb.data = acb;
167 return acb;
168 }
170 static BlockDriverAIOCB *vbd_aio_read(BlockDriverState *bs,
171 int64_t sector_num, uint8_t *buf, int nb_sectors,
172 BlockDriverCompletionFunc *cb, void *opaque)
173 {
174 VbdAIOCB *acb;
176 acb = vbd_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
177 if (!acb)
178 return NULL;
179 blkfront_aio(&acb->aiocb, 0);
180 return &acb->common;
181 }
183 static BlockDriverAIOCB *vbd_aio_write(BlockDriverState *bs,
184 int64_t sector_num, const uint8_t *buf, int nb_sectors,
185 BlockDriverCompletionFunc *cb, void *opaque)
186 {
187 VbdAIOCB *acb;
189 acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, cb, opaque);
190 if (!acb)
191 return NULL;
192 blkfront_aio(&acb->aiocb, 1);
193 return &acb->common;
194 }
196 static void vbd_cb(void *data, int ret) {
197 int *result = data;
198 result[0] = 1;
199 result[1] = ret;
200 }
202 static int vbd_aligned_io(BlockDriverState *bs,
203 int64_t sector_num, uint8_t *buf, int nb_sectors, int write)
204 {
205 VbdAIOCB *acb;
206 int result[2];
207 result[0] = 0;
208 qemu_aio_wait_start();
209 acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, vbd_cb, &result);
210 blkfront_aio(&acb->aiocb, write);
211 while (!result[0])
212 qemu_aio_wait();
213 qemu_aio_wait_end();
214 return result[1];
215 }
217 static int vbd_read(BlockDriverState *bs,
218 int64_t sector_num, uint8_t *buf, int nb_sectors)
219 {
220 uint8_t *iobuf;
221 int ret;
222 /* page alignment would be a bit better, but that's still fine compared to
223 * copying */
224 if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
225 return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0);
226 iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
227 ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0);
228 memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE);
229 free(iobuf);
230 if (ret < 0)
231 return ret;
232 else if (ret != nb_sectors * SECTOR_SIZE)
233 return -EINVAL;
234 else
235 return 0;
236 }
238 static int vbd_write(BlockDriverState *bs,
239 int64_t sector_num, const uint8_t *buf, int nb_sectors)
240 {
241 uint8_t *iobuf;
242 int ret;
243 if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
244 return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1);
245 iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
246 memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE);
247 ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1);
248 free(iobuf);
249 if (ret < 0)
250 return ret;
251 else if (ret != nb_sectors * SECTOR_SIZE)
252 return -EINVAL;
253 else
254 return 0;
255 }
257 static void vbd_aio_cancel(BlockDriverAIOCB *blockacb)
258 {
259 /* TODO */
260 //VbdAIOCB *acb = (VbdAIOCB *)blockacb;
262 // Try to cancel. If can't, wait for it, drop the callback and call qemu_aio_release(acb)
263 }
265 static void vbd_close(BlockDriverState *bs)
266 {
267 BDRVVbdState *s = bs->opaque;
268 bs->total_sectors = 0;
269 if (s->fd >= 0) {
270 close(s->fd);
271 s->fd = -1;
272 }
273 QEMU_LIST_REMOVE(s, list);
274 }
276 static int64_t vbd_getlength(BlockDriverState *bs)
277 {
278 BDRVVbdState *s = bs->opaque;
279 return s->sectors * s->sector_size;
280 }
282 static void vbd_flush(BlockDriverState *bs)
283 {
284 BDRVVbdState *s = bs->opaque;
285 blkfront_sync(s->dev);
286 }
288 /***********************************************/
289 /* host device */
291 static int vbd_is_inserted(BlockDriverState *bs)
292 {
293 /* TODO: monitor the backend */
294 return 1;
295 }
297 /* currently only used by fdc.c, but a CD version would be good too */
298 static int vbd_media_changed(BlockDriverState *bs)
299 {
300 /* TODO: monitor the backend */
301 return -ENOTSUP;
302 }
304 static int vbd_eject(BlockDriverState *bs, int eject_flag)
305 {
306 /* TODO: Xen support needed */
307 return -ENOTSUP;
308 }
310 static int vbd_set_locked(BlockDriverState *bs, int locked)
311 {
312 /* TODO: Xen support needed */
313 return -ENOTSUP;
314 }
316 BlockDriver bdrv_vbd = {
317 "vbd",
318 sizeof(BDRVVbdState),
319 vbd_probe,
320 vbd_open,
321 NULL,
322 NULL,
323 vbd_close,
324 NULL,
325 vbd_flush,
327 .bdrv_aio_read = vbd_aio_read,
328 .bdrv_aio_write = vbd_aio_write,
329 .bdrv_aio_cancel = vbd_aio_cancel,
330 .aiocb_size = sizeof(VbdAIOCB),
331 .bdrv_read = vbd_read,
332 .bdrv_write = vbd_write,
333 .bdrv_getlength = vbd_getlength,
335 /* removable device support */
336 .bdrv_is_inserted = vbd_is_inserted,
337 .bdrv_media_changed = vbd_media_changed,
338 .bdrv_eject = vbd_eject,
339 .bdrv_set_locked = vbd_set_locked,
340 };