|
|
1.1 root 1: /*
2: * Copyright (C) 2006-2009, 2011 Free Software Foundation
3: *
4: * This program is free software ; you can redistribute it and/or modify
5: * it under the terms of the GNU General Public License as published by
6: * the Free Software Foundation ; either version 2 of the License, or
7: * (at your option) any later version.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY ; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with the program ; if not, write to the Free Software
16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include <sys/types.h>
20: #include <mach/mig_errors.h>
21: #include <kern/kalloc.h>
22: #include <ipc/ipc_port.h>
23: #include <ipc/ipc_space.h>
24: #include <vm/vm_kern.h>
25: #include <vm/vm_user.h>
26: #include <device/device_types.h>
27: #include <device/device_port.h>
28: #include <device/disk_status.h>
29: #include <device/device_reply.user.h>
30: #include <device/device_emul.h>
31: #include <device/ds_routines.h>
32: #include <xen/public/io/blkif.h>
33: #include <xen/evt.h>
34: #include <string.h>
35: #include <util/atoi.h>
36: #include "store.h"
37: #include "block.h"
38: #include "grant.h"
39: #include "ring.h"
40: #include "xen.h"
41:
42: /* Hypervisor part */
43:
44: struct block_data {
45: struct device device;
46: char *name;
47: int open_count;
48: char *backend;
49: domid_t domid;
50: char *vbd;
51: int handle;
52: unsigned info;
53: dev_mode_t mode;
54: unsigned sector_size;
55: unsigned long nr_sectors;
56: ipc_port_t port;
57: blkif_front_ring_t ring;
58: evtchn_port_t evt;
59: simple_lock_data_t lock;
60: simple_lock_data_t pushlock;
61: };
62:
63: static int n_vbds;
64: static struct block_data *vbd_data;
65:
66: struct device_emulation_ops hyp_block_emulation_ops;
67:
68: static void hyp_block_intr(int unit) {
69: struct block_data *bd = &vbd_data[unit];
70: blkif_response_t *rsp;
71: int more;
72: io_return_t *err;
73:
74: simple_lock(&bd->lock);
75: more = RING_HAS_UNCONSUMED_RESPONSES(&bd->ring);
76: while (more) {
77: rmb(); /* make sure we see responses */
78: rsp = RING_GET_RESPONSE(&bd->ring, bd->ring.rsp_cons++);
79: err = (void *) (unsigned long) rsp->id;
80: switch (rsp->status) {
81: case BLKIF_RSP_ERROR:
82: *err = D_IO_ERROR;
83: break;
84: case BLKIF_RSP_OKAY:
85: break;
86: default:
87: printf("Unrecognized blkif status %d\n", rsp->status);
88: goto drop;
89: }
90: thread_wakeup(err);
91: drop:
92: thread_wakeup_one(bd);
93: RING_FINAL_CHECK_FOR_RESPONSES(&bd->ring, more);
94: }
95: simple_unlock(&bd->lock);
96: }
97:
98: #define VBD_PATH "device/vbd"
99: void hyp_block_init(void) {
100: char **vbds, **vbd;
101: char *c;
102: int i, disk, partition;
103: int n;
104: int grant;
105: char port_name[10];
106: char *prefix;
107: char device_name[32];
108: domid_t domid;
109: evtchn_port_t evt;
110: hyp_store_transaction_t t;
111: vm_offset_t addr;
112: struct block_data *bd;
113: blkif_sring_t *ring;
114:
115: vbds = hyp_store_ls(0, 1, VBD_PATH);
116: if (!vbds) {
117: printf("hd: No block device (%s). Hoping you don't need any\n", hyp_store_error);
118: n_vbds = 0;
119: return;
120: }
121:
122: n = 0;
123: for (vbd = vbds; *vbd; vbd++)
124: n++;
125:
126: vbd_data = (void*) kalloc(n * sizeof(*vbd_data));
127: if (!vbd_data) {
128: printf("hd: No memory room for VBD\n");
129: n_vbds = 0;
130: return;
131: }
132: n_vbds = n;
133:
134: for (n = 0; n < n_vbds; n++) {
135: bd = &vbd_data[n];
136: mach_atoi((u_char *) vbds[n], &bd->handle);
137: if (bd->handle == MACH_ATOI_DEFAULT)
138: continue;
139:
140: bd->open_count = -2;
141: bd->vbd = vbds[n];
142:
143: /* Get virtual number. */
144: i = hyp_store_read_int(0, 5, VBD_PATH, "/", vbds[n], "/", "virtual-device");
145: if (i == -1)
146: panic("hd: couldn't virtual device of VBD %s\n",vbds[n]);
147: if ((i >> 28) == 1) {
148: /* xvd, new format */
149: prefix = "xvd";
150: disk = (i >> 8) & ((1 << 20) - 1);
151: partition = i & ((1 << 8) - 1);
152: } else if ((i >> 8) == 202) {
153: /* xvd, old format */
154: prefix = "xvd";
155: disk = (i >> 4) & ((1 << 4) - 1);
156: partition = i & ((1 << 4) - 1);
157: } else if ((i >> 8) == 8) {
158: /* SCSI */
159: prefix = "sd";
160: disk = (i >> 4) & ((1 << 4) - 1);
161: partition = i & ((1 << 4) - 1);
162: } else if ((i >> 8) == 3) {
163: /* IDE primary */
164: prefix = "hd";
165: disk = (i >> 6) & ((1 << 2) - 1);
166: partition = i & ((1 << 6) - 1);
167: } else if ((i >> 8) == 22) {
168: /* IDE secondary */
169: prefix = "hd";
170: disk = ((i >> 6) & ((1 << 2) - 1)) + 2;
171: partition = i & ((1 << 6) - 1);
172: } else if ((i >> 8) == 33) {
173: /* IDE 3 */
174: prefix = "hd";
175: disk = ((i >> 6) & ((1 << 2) - 1)) + 4;
176: partition = i & ((1 << 6) - 1);
177: } else if ((i >> 8) == 34) {
178: /* IDE 4 */
179: prefix = "hd";
180: disk = ((i >> 6) & ((1 << 2) - 1)) + 6;
181: partition = i & ((1 << 6) - 1);
182: } else if ((i >> 8) == 56) {
183: /* IDE 5 */
184: prefix = "hd";
185: disk = ((i >> 6) & ((1 << 2) - 1)) + 8;
186: partition = i & ((1 << 6) - 1);
187: } else if ((i >> 8) == 57) {
188: /* IDE 6 */
189: prefix = "hd";
190: disk = ((i >> 6) & ((1 << 2) - 1)) + 10;
191: partition = i & ((1 << 6) - 1);
192: } else if ((i >> 8) == 88) {
193: /* IDE 7 */
194: prefix = "hd";
195: disk = ((i >> 6) & ((1 << 2) - 1)) + 12;
196: partition = i & ((1 << 6) - 1);
197: } else if ((i >> 8) == 89) {
198: /* IDE 8 */
199: prefix = "hd";
200: disk = ((i >> 6) & ((1 << 2) - 1)) + 14;
201: partition = i & ((1 << 6) - 1);
202: } else if ((i >> 8) == 90) {
203: /* IDE 9 */
204: prefix = "hd";
205: disk = ((i >> 6) & ((1 << 2) - 1)) + 16;
206: partition = i & ((1 << 6) - 1);
207: } else if ((i >> 8) == 91) {
208: /* IDE 10 */
209: prefix = "hd";
210: disk = ((i >> 6) & ((1 << 2) - 1)) + 18;
211: partition = i & ((1 << 6) - 1);
212: } else {
213: printf("unsupported VBD number %d\n", i);
214: continue;
215: }
216: if (partition)
217: sprintf(device_name, "%s%ds%d", prefix, disk, partition);
218: else
219: sprintf(device_name, "%s%d", prefix, disk);
1.1.1.2 root 220: bd->name = (char*) kalloc(strlen(device_name) + 1);
1.1 root 221: strcpy(bd->name, device_name);
222:
223: /* Get domain id of backend driver. */
224: i = hyp_store_read_int(0, 5, VBD_PATH, "/", vbds[n], "/", "backend-id");
225: if (i == -1)
226: panic("%s: couldn't read backend domid (%s)", device_name, hyp_store_error);
227: bd->domid = domid = i;
228:
229: do {
230: t = hyp_store_transaction_start();
231:
232: /* Get a page for ring */
233: if ((addr = vm_page_grab_phys_addr()) == -1)
234: panic("%s: couldn't allocate space for store ring\n", device_name);
235: ring = (void*) phystokv(addr);
236: SHARED_RING_INIT(ring);
237: FRONT_RING_INIT(&bd->ring, ring, PAGE_SIZE);
238: grant = hyp_grant_give(domid, atop(addr), 0);
239:
240: /* and give it to backend. */
241: i = sprintf(port_name, "%d", grant);
242: c = hyp_store_write(t, port_name, 5, VBD_PATH, "/", vbds[n], "/", "ring-ref");
243: if (!c)
244: panic("%s: couldn't store ring reference (%s)", device_name, hyp_store_error);
245: kfree((vm_offset_t) c, strlen(c)+1);
246:
247: /* Allocate an event channel and give it to backend. */
248: bd->evt = evt = hyp_event_channel_alloc(domid);
249: hyp_evt_handler(evt, hyp_block_intr, n, SPL7);
1.1.1.3 root 250: i = sprintf(port_name, "%u", evt);
1.1 root 251: c = hyp_store_write(t, port_name, 5, VBD_PATH, "/", vbds[n], "/", "event-channel");
252: if (!c)
253: panic("%s: couldn't store event channel (%s)", device_name, hyp_store_error);
254: kfree((vm_offset_t) c, strlen(c)+1);
255: c = hyp_store_write(t, hyp_store_state_initialized, 5, VBD_PATH, "/", vbds[n], "/", "state");
256: if (!c)
257: panic("%s: couldn't store state (%s)", device_name, hyp_store_error);
258: kfree((vm_offset_t) c, strlen(c)+1);
259: } while (!hyp_store_transaction_stop(t));
260: /* TODO randomly wait? */
261:
262: c = hyp_store_read(0, 5, VBD_PATH, "/", vbds[n], "/", "backend");
263: if (!c)
264: panic("%s: couldn't get path to backend (%s)", device_name, hyp_store_error);
265: bd->backend = c;
266:
267: while(1) {
268: i = hyp_store_read_int(0, 3, bd->backend, "/", "state");
269: if (i == MACH_ATOI_DEFAULT)
270: panic("can't read state from %s", bd->backend);
271: if (i == XenbusStateConnected)
272: break;
273: hyp_yield();
274: }
275:
276: i = hyp_store_read_int(0, 3, bd->backend, "/", "sectors");
277: if (i == -1)
278: panic("%s: couldn't get number of sectors (%s)", device_name, hyp_store_error);
279: bd->nr_sectors = i;
280:
281: i = hyp_store_read_int(0, 3, bd->backend, "/", "sector-size");
282: if (i == -1)
283: panic("%s: couldn't get sector size (%s)", device_name, hyp_store_error);
284: if (i & ~(2*(i-1)+1))
285: panic("sector size %d is not a power of 2\n", i);
286: if (i > PAGE_SIZE || PAGE_SIZE % i != 0)
287: panic("%s: couldn't handle sector size %d with pages of size %d\n", device_name, i, PAGE_SIZE);
288: bd->sector_size = i;
289:
290: i = hyp_store_read_int(0, 3, bd->backend, "/", "info");
291: if (i == -1)
292: panic("%s: couldn't get info (%s)", device_name, hyp_store_error);
293: bd->info = i;
294:
295: c = hyp_store_read(0, 3, bd->backend, "/", "mode");
296: if (!c)
297: panic("%s: couldn't get backend's mode (%s)", device_name, hyp_store_error);
298: if ((c[0] == 'w') && !(bd->info & VDISK_READONLY))
299: bd->mode = D_READ|D_WRITE;
300: else
301: bd->mode = D_READ;
302:
303: c = hyp_store_read(0, 3, bd->backend, "/", "params");
304: if (!c)
305: panic("%s: couldn't get backend's real device (%s)", device_name, hyp_store_error);
306:
307: /* TODO: change suffix */
308: printf("%s: dom%d's VBD %s (%s,%c%s) %ldMB\n", device_name, domid,
309: vbds[n], c, bd->mode & D_WRITE ? 'w' : 'r',
310: bd->info & VDISK_CDROM ? ", cdrom" : "",
311: bd->nr_sectors / ((1<<20) / 512));
312: kfree((vm_offset_t) c, strlen(c)+1);
313:
314: c = hyp_store_write(0, hyp_store_state_connected, 5, VBD_PATH, "/", bd->vbd, "/", "state");
315: if (!c)
316: panic("couldn't store state for %s (%s)", device_name, hyp_store_error);
317: kfree((vm_offset_t) c, strlen(c)+1);
318:
319: bd->open_count = -1;
320: bd->device.emul_ops = &hyp_block_emulation_ops;
321: bd->device.emul_data = bd;
322: simple_lock_init(&bd->lock);
323: simple_lock_init(&bd->pushlock);
324: }
325: }
326:
327: static ipc_port_t
328: dev_to_port(void *d)
329: {
330: struct block_data *b = d;
331: if (!d)
332: return IP_NULL;
333: return ipc_port_make_send(b->port);
334: }
335:
336: static int
337: device_close(void *devp)
338: {
339: struct block_data *bd = devp;
340: if (--bd->open_count < 0)
341: panic("too many closes on %s", bd->name);
342: printf("close, %s count %d\n", bd->name, bd->open_count);
343: if (bd->open_count)
344: return 0;
345: ipc_kobject_set(bd->port, IKO_NULL, IKOT_NONE);
346: ipc_port_dealloc_kernel(bd->port);
347: return 0;
348: }
349:
350: static io_return_t
351: device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
352: dev_mode_t mode, char *name, device_t *devp /* out */)
353: {
1.1.1.3 root 354: int i;
1.1 root 355: ipc_port_t port, notify;
356: struct block_data *bd;
357:
358: for (i = 0; i < n_vbds; i++)
359: if (!strcmp(name, vbd_data[i].name))
360: break;
361:
362: if (i == n_vbds)
363: return D_NO_SUCH_DEVICE;
364:
365: bd = &vbd_data[i];
366: if (bd->open_count == -2)
367: /* couldn't be initialized */
368: return D_NO_SUCH_DEVICE;
369:
370: if ((mode & D_WRITE) && !(bd->mode & D_WRITE))
371: return D_READ_ONLY;
372:
373: if (bd->open_count >= 0) {
374: *devp = &bd->device ;
375: bd->open_count++ ;
376: printf("re-open, %s count %d\n", bd->name, bd->open_count);
377: return D_SUCCESS;
378: }
379:
380: bd->open_count = 1;
381: printf("%s count %d\n", bd->name, bd->open_count);
382:
383: port = ipc_port_alloc_kernel();
384: if (port == IP_NULL) {
1.1.1.2 root 385: device_close(bd);
386: return KERN_RESOURCE_SHORTAGE;
1.1 root 387: }
388: bd->port = port;
389:
390: *devp = &bd->device;
391:
392: ipc_kobject_set (port, (ipc_kobject_t) &bd->device, IKOT_DEVICE);
393:
394: notify = ipc_port_make_sonce (bd->port);
395: ip_lock (bd->port);
396: ipc_port_nsrequest (bd->port, 1, notify, ¬ify);
397: assert (notify == IP_NULL);
398:
399: if (IP_VALID (reply_port))
400: ds_device_open_reply (reply_port, reply_port_type, D_SUCCESS, port);
401: else
402: device_close(bd);
403: return MIG_NO_REPLY;
404: }
405:
406: static io_return_t
407: device_read (void *d, ipc_port_t reply_port,
408: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
409: recnum_t bn, int count, io_buf_ptr_t *data,
410: unsigned *bytes_read)
411: {
412: int resid, amt;
413: io_return_t err = 0;
414: vm_page_t pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
415: grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
416: int nbpages;
417: vm_map_copy_t copy;
418: vm_offset_t offset, alloc_offset, o;
419: vm_object_t object;
420: vm_page_t m;
421: vm_size_t len, size;
422: struct block_data *bd = d;
423: struct blkif_request *req;
424:
425: *data = 0;
426: *bytes_read = 0;
427:
428: if (count < 0)
429: return D_INVALID_SIZE;
430: if (count == 0)
431: return 0;
432:
433: /* Allocate an object to hold the data. */
434: size = round_page (count);
435: object = vm_object_allocate (size);
436: if (! object)
437: {
438: err = D_NO_MEMORY;
439: goto out;
440: }
441: alloc_offset = offset = 0;
442: resid = count;
443:
444: while (resid && !err)
445: {
446: unsigned reqn;
447: int i;
448: int last_sect;
449:
450: nbpages = 0;
451:
452: /* Determine size of I/O this time around. */
453: len = round_page(offset + resid) - offset;
454: if (len > PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST)
455: len = PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST;
456:
457: /* Allocate pages. */
458: while (alloc_offset < offset + len)
459: {
1.1.1.4 ! root 460: while ((m = vm_page_grab ()) == 0)
1.1 root 461: VM_PAGE_WAIT (0);
462: assert (! m->active && ! m->inactive);
463: m->busy = TRUE;
464: assert(nbpages < BLKIF_MAX_SEGMENTS_PER_REQUEST);
465: pages[nbpages++] = m;
466: alloc_offset += PAGE_SIZE;
467: }
468:
469: /* Do the read. */
470: amt = len;
471: if (amt > resid)
472: amt = resid;
473:
474: /* allocate a request */
475: spl_t spl = splsched();
476: while(1) {
477: simple_lock(&bd->lock);
478: if (!RING_FULL(&bd->ring))
479: break;
480: thread_sleep(bd, &bd->lock, FALSE);
481: }
482: mb();
483: reqn = bd->ring.req_prod_pvt++;;
484: simple_lock(&bd->pushlock);
485: simple_unlock(&bd->lock);
486: (void) splx(spl);
487:
488: req = RING_GET_REQUEST(&bd->ring, reqn);
489: req->operation = BLKIF_OP_READ;
490: req->nr_segments = nbpages;
491: req->handle = bd->handle;
1.1.1.3 root 492: req->id = (uint64_t) (unsigned long) &err; /* pointer on the stack */
1.1 root 493: req->sector_number = bn + offset / 512;
494: for (i = 0; i < nbpages; i++) {
495: req->seg[i].gref = gref[i] = hyp_grant_give(bd->domid, atop(pages[i]->phys_addr), 0);
496: req->seg[i].first_sect = 0;
497: req->seg[i].last_sect = PAGE_SIZE/512 - 1;
498: }
499: last_sect = ((amt - 1) & PAGE_MASK) / 512;
500: req->seg[nbpages-1].last_sect = last_sect;
501:
502: memset((void*) phystokv(pages[nbpages-1]->phys_addr
503: + (last_sect + 1) * 512),
504: 0, PAGE_SIZE - (last_sect + 1) * 512);
505:
506: /* no need for a lock: as long as the request is not pushed, the event won't be triggered */
507: assert_wait((event_t) &err, FALSE);
508:
509: int notify;
510: wmb(); /* make sure it sees requests */
511: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bd->ring, notify);
512: if (notify)
513: hyp_event_channel_send(bd->evt);
514: simple_unlock(&bd->pushlock);
515:
516: thread_block(NULL);
517:
518: if (err)
519: printf("error reading %d bytes at sector %ld\n", amt,
520: bn + offset / 512);
521:
522: for (i = 0; i < nbpages; i++)
523: hyp_grant_takeback(gref[i]);
524:
525: /* Compute number of pages to insert in object. */
526: o = offset;
527:
528: resid -= amt;
529: if (resid == 0)
530: offset = o + len;
531: else
532: offset += amt;
533:
534: /* Add pages to the object. */
535: vm_object_lock (object);
536: for (i = 0; i < nbpages; i++)
537: {
538: m = pages[i];
539: assert (m->busy);
540: vm_page_lock_queues ();
541: PAGE_WAKEUP_DONE (m);
542: m->dirty = TRUE;
543: vm_page_insert (m, object, o);
544: vm_page_unlock_queues ();
545: o += PAGE_SIZE;
546: }
547: vm_object_unlock (object);
548: }
549:
550: out:
551: if (! err)
552: err = vm_map_copyin_object (object, 0, round_page (count), ©);
553: if (! err)
554: {
555: *data = (io_buf_ptr_t) copy;
556: *bytes_read = count - resid;
557: }
558: else
559: vm_object_deallocate (object);
560: return err;
561: }
562:
563: static io_return_t
564: device_write(void *d, ipc_port_t reply_port,
565: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
566: recnum_t bn, io_buf_ptr_t data, unsigned int count,
567: int *bytes_written)
568: {
569: io_return_t err = 0;
570: vm_map_copy_t copy = (vm_map_copy_t) data;
1.1.1.4 ! root 571: vm_offset_t buffer = 0;
! 572: char *map_data;
! 573: vm_offset_t map_addr;
! 574: vm_size_t map_size;
1.1.1.3 root 575: unsigned copy_npages = atop(round_page(count));
1.1 root 576: vm_offset_t phys_addrs[copy_npages];
577: struct block_data *bd = d;
578: blkif_request_t *req;
579: grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
580: unsigned reqn, size;
1.1.1.3 root 581: unsigned i, nbpages, j;
1.1.1.4 ! root 582: kern_return_t kr;
1.1 root 583:
584: if (!(bd->mode & D_WRITE))
585: return D_READ_ONLY;
586:
587: if (count == 0) {
588: vm_map_copy_discard(copy);
589: return 0;
590: }
591:
592: if (count % bd->sector_size)
593: return D_INVALID_SIZE;
594:
595: if (count > copy->size)
596: return D_INVALID_SIZE;
597:
1.1.1.4 ! root 598: /* XXX The underlying physical pages of the mapping could be highmem,
! 599: for which drivers require the use of a bounce buffer. */
! 600: kr = kmem_alloc(device_io_map, &buffer, count);
! 601: if (kr != KERN_SUCCESS)
! 602: return kr;
! 603:
! 604: kr = kmem_io_map_copyout(device_io_map, (vm_offset_t *)&map_data,
! 605: &map_addr, &map_size, copy, count);
! 606: if (kr != KERN_SUCCESS) {
! 607: kmem_free(device_io_map, buffer, count);
! 608: return kr;
! 609: }
1.1 root 610:
1.1.1.4 ! root 611: memcpy((void *)buffer, map_data, count);
! 612: kmem_io_map_deallocate(device_io_map, map_addr, map_size);
1.1 root 613:
1.1.1.4 ! root 614: for (i = 0; i < copy_npages; i++)
! 615: phys_addrs[i] = kvtophys(buffer + ptoa(i));
1.1 root 616:
617: for (i=0; i<copy_npages; i+=nbpages) {
618:
619: nbpages = BLKIF_MAX_SEGMENTS_PER_REQUEST;
620: if (nbpages > copy_npages-i)
621: nbpages = copy_npages-i;
622:
623: /* allocate a request */
624: spl_t spl = splsched();
625: while(1) {
626: simple_lock(&bd->lock);
627: if (!RING_FULL(&bd->ring))
628: break;
629: thread_sleep(bd, &bd->lock, FALSE);
630: }
631: mb();
632: reqn = bd->ring.req_prod_pvt++;;
633: simple_lock(&bd->pushlock);
634: simple_unlock(&bd->lock);
635: (void) splx(spl);
636:
637: req = RING_GET_REQUEST(&bd->ring, reqn);
638: req->operation = BLKIF_OP_WRITE;
639: req->nr_segments = nbpages;
640: req->handle = bd->handle;
1.1.1.3 root 641: req->id = (uint64_t) (unsigned long) &err; /* pointer on the stack */
1.1 root 642: req->sector_number = bn + i*PAGE_SIZE / 512;
643:
644: for (j = 0; j < nbpages; j++) {
645: req->seg[j].gref = gref[j] = hyp_grant_give(bd->domid, atop(phys_addrs[i + j]), 1);
646: req->seg[j].first_sect = 0;
647: size = PAGE_SIZE;
648: if ((i + j + 1) * PAGE_SIZE > count)
649: size = count - (i + j) * PAGE_SIZE;
650: req->seg[j].last_sect = size/512 - 1;
651: }
652:
653: /* no need for a lock: as long as the request is not pushed, the event won't be triggered */
654: assert_wait((event_t) &err, FALSE);
655:
656: int notify;
657: wmb(); /* make sure it sees requests */
658: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bd->ring, notify);
659: if (notify)
660: hyp_event_channel_send(bd->evt);
661: simple_unlock(&bd->pushlock);
662:
663: thread_block(NULL);
664:
665: for (j = 0; j < nbpages; j++)
666: hyp_grant_takeback(gref[j]);
667:
668: if (err) {
669: printf("error writing %u bytes at sector %d\n", count, bn);
670: break;
671: }
672: }
673:
1.1.1.4 ! root 674: if (buffer)
! 675: kmem_free(device_io_map, buffer, count);
1.1 root 676:
677: vm_map_copy_discard (copy);
678:
679: if (!err)
680: *bytes_written = count;
681:
682: if (IP_VALID(reply_port))
683: ds_device_write_reply (reply_port, reply_port_type, err, count);
684:
685: return MIG_NO_REPLY;
686: }
687:
688: static io_return_t
689: device_get_status(void *d, dev_flavor_t flavor, dev_status_t status,
690: mach_msg_type_number_t *status_count)
691: {
692: struct block_data *bd = d;
693:
694: switch (flavor)
695: {
696: case DEV_GET_SIZE:
697: status[DEV_GET_SIZE_DEVICE_SIZE] = (unsigned long long) bd->nr_sectors * 512;
698: status[DEV_GET_SIZE_RECORD_SIZE] = bd->sector_size;
699: *status_count = DEV_GET_SIZE_COUNT;
700: break;
701: case DEV_GET_RECORDS:
702: status[DEV_GET_RECORDS_DEVICE_RECORDS] = ((unsigned long long) bd->nr_sectors * 512) / bd->sector_size;
703: status[DEV_GET_RECORDS_RECORD_SIZE] = bd->sector_size;
704: *status_count = DEV_GET_RECORDS_COUNT;
705: break;
706: default:
707: printf("TODO: block_%s(%d)\n", __func__, flavor);
708: return D_INVALID_OPERATION;
709: }
710: return D_SUCCESS;
711: }
712:
713: struct device_emulation_ops hyp_block_emulation_ops = {
714: NULL, /* dereference */
715: NULL, /* deallocate */
716: dev_to_port,
717: device_open,
718: device_close,
719: device_write,
720: NULL, /* write_inband */
721: device_read,
722: NULL, /* read_inband */
723: NULL, /* set_status */
724: device_get_status,
725: NULL, /* set_filter */
726: NULL, /* map */
727: NULL, /* no_senders */
728: NULL, /* write_trap */
729: NULL, /* writev_trap */
730: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.