diff options
-rw-r--r-- | .rootkeys | 1 | ||||
-rw-r--r-- | netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN | 8 | ||||
-rw-r--r-- | netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h | 1 | ||||
-rw-r--r-- | netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h | 56 | ||||
-rw-r--r-- | netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c | 749 |
5 files changed, 582 insertions, 233 deletions
@@ -283,6 +283,7 @@ 413cb3b4bRsqiHQLTKEZk4-zOksf8A netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h 413cb3b4OqY83qI8GztIZGADpvrpSw netbsd-2.0-xen-sparse/sys/arch/xen/include/if_xennetvar.h 413cb3b42GG0LffraTnpZKlSUq57wg netbsd-2.0-xen-sparse/sys/arch/xen/include/pmap.h +41580792kPzxLiPb47k_GDEMSbAbzA netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h 413cb3b4F0ArkWVBRyspkw7ivfXihg netbsd-2.0-xen-sparse/sys/arch/xen/include/xen.h 413cb3b4ullQud70n4JClwoEEUBh8Q netbsd-2.0-xen-sparse/sys/arch/xen/include/xenfunc.h 413cb3b4y1Ffq8BOhbdSpn-fGmKuEg netbsd-2.0-xen-sparse/sys/arch/xen/include/xenpmap.h diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN b/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN index e54802263f..eece41d429 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN @@ -132,10 +132,10 @@ npx0 at hypervisor? # x86 math coprocessor xencons* at hypervisor? # Xen virtual console xennet* at hypervisor? # Xen virtual network interface -#xbd* at hypervisor? # Xen virtual block device -#wd* at hypervisor? # Xen vbd (wd identity) -#sd* at hypervisor? # Xen vbd (sd identity) -#cd* at hypervisor? # Xen vbd (cd identity) +xbd* at hypervisor? # Xen virtual block device +wd* at hypervisor? # Xen vbd (wd identity) +sd* at hypervisor? # Xen vbd (sd identity) +cd* at hypervisor? # Xen vbd (cd identity) #xenkbc* at hypervisor? # Xen Keyboard/Mouse Interface #pckbd* at xenkbc? # Keyboard diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h index 83a170485e..b906595275 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h @@ -59,6 +59,7 @@ struct xen_npx_attach_args { #include <machine/hypervisor-ifs/event_channel.h> #include <machine/hypervisor-ifs/io/domain_controller.h> #include <machine/hypervisor-ifs/io/netif.h> +#include <machine/hypervisor-ifs/io/blkif.h> #undef u8 #undef u16 diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h b/netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h new file mode 100644 index 0000000000..8c1c57c692 --- /dev/null +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h @@ -0,0 +1,56 @@ +/* $NetBSD: xbdvar.h,v 1.5 2004/05/07 14:15:11 cl Exp $ */ + +/* + * + * Copyright (c) 2004 Christian Limpach. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christian Limpach. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _XEN_XBDVAR_H_ +#define _XEN_XBDVAR_H_ + +struct xbd_softc { + struct device sc_dev; /* base device glue */ + struct dk_softc sc_dksc; /* generic disk interface */ + unsigned long sc_xd_device; /* cookie identifying device */ + struct dk_intf *sc_di; /* pseudo-disk interface */ + struct simplelock sc_slock; /* our lock */ + int sc_shutdown; /* about to be removed */ +}; + +struct xbd_attach_args { + const char *xa_device; + vdisk_t *xa_xd; + struct dk_intf *xa_dkintf; + struct sysctlnode *xa_diskcookies; +}; + +int xbd_scan(struct device *, struct xbd_attach_args *, cfprint_t); + +#endif /* _XEN_XBDVAR_H_ */ diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c index b72ffc95a1..9cfab063a9 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c @@ -63,12 +63,15 @@ __KERNEL_RCSID(0, "$NetBSD: xbd.c,v 1.9.2.1 2004/05/22 15:59:11 he Exp $"); #include <dev/dkvar.h> #include <machine/xbdvar.h> + #include <machine/xen.h> #include <machine/hypervisor.h> -#include <machine/hypervisor-ifs/hypervisor-if.h> -#include <machine/hypervisor-ifs/vbd.h> #include <machine/evtchn.h> +#include <machine/ctrl_if.h> + +static void control_send(blkif_request_t *, blkif_response_t *); +static void send_interface_connect(void); static void xbd_attach(struct device *, struct device *, void *); static int xbd_detach(struct device *, int); @@ -178,11 +181,13 @@ static dev_t xbd_cd_cdev_major; static int xbdstart(struct dk_softc *, struct buf *); static int xbd_response_handler(void *); +#if 0 static void xbd_update_create_kthread(void *); static void xbd_update_kthread(void *); static int xbd_update_handler(void *); +#endif -static int xbdinit(struct xbd_softc *, xen_disk_t *, struct dk_intf *); +static int xbdinit(struct xbd_softc *, vdisk_t *, struct dk_intf *); /* Pseudo-disk Interface */ static struct dk_intf dkintf_esdi = { @@ -346,18 +351,32 @@ static int bufq_users = 0; #define MAX_VBDS 64 static int nr_vbds; -static xen_disk_t *vbd_info; +static vdisk_t *vbd_info; + +static blkif_ring_t *blk_ring = NULL; +static BLKIF_RING_IDX resp_cons; /* Response consumer for comms ring. */ +static BLKIF_RING_IDX req_prod; /* Private request producer. */ +static BLKIF_RING_IDX last_req_prod; /* Request producer at last trap. */ -static blk_ring_t *blk_ring = NULL; -static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */ -static BLK_RING_IDX req_prod; /* Private request producer. */ -static BLK_RING_IDX last_req_prod; /* Request producer at last trap. */ +#define STATE_CLOSED 0 +#define STATE_DISCONNECTED 1 +#define STATE_CONNECTED 2 +static unsigned int state = STATE_CLOSED; +static unsigned int blkif_evtchn = 0; +static unsigned int blkif_irq = 0; +static unsigned int blkif_handle = 0; -#define STATE_ACTIVE 0 -#define STATE_SUSPENDED 1 -#define STATE_CLOSED 2 -static unsigned int state = STATE_SUSPENDED; +static int blkif_control_rsp_valid = 0; +static blkif_response_t blkif_control_rsp; +/** Network interface info. */ +struct xbd_ctrl { + + cfprint_t xc_cfprint; + struct device *xc_parent; +}; + +static struct xbd_ctrl blkctrl; #define XBDUNIT(x) DISKUNIT(x) #define GETXBD_SOFTC(_xs, x) if (!((_xs) = getxbd_softc(x))) return ENXIO @@ -396,70 +415,317 @@ getxbd_softc(dev_t dev) } static int -get_vbd_info(xen_disk_t *disk_info) +get_vbd_info(vdisk_t *disk_info) { - int err; - block_io_op_t op; + vdisk_t *buf; + int nr; + blkif_request_t req; + blkif_response_t rsp; + paddr_t pa; + buf = (vdisk_t *)uvm_km_kmemalloc1(kmem_map, NULL, + PAGE_SIZE, PAGE_SIZE, UVM_UNKNOWN_OFFSET, 0); + pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa); /* Probe for disk information. */ - memset(&op, 0, sizeof(op)); - op.cmd = BLOCK_IO_OP_VBD_PROBE; - op.u.probe_params.domain = 0; - op.u.probe_params.xdi.max = MAX_VBDS; - op.u.probe_params.xdi.disks = disk_info; - op.u.probe_params.xdi.count = 0; - - err = HYPERVISOR_block_io_op(&op); - if (err) { - printf("WARNING: Could not probe disks (%d)\n", err); - DIAGPANIC(("get_vbd_info: Could not probe disks (%d)", err)); - return -1; + memset(&req, 0, sizeof(req)); + req.operation = BLKIF_OP_PROBE; + req.nr_segments = 1; + req.frame_and_sects[0] = xpmap_ptom_masked(pa) | 7; + + control_send(&req, &rsp); + nr = rsp.status > MAX_VBDS ? MAX_VBDS : rsp.status; + + if (rsp.status < 0) + printf("WARNING: Could not probe disks (%d)\n", rsp.status); + + memcpy(disk_info, buf, nr * sizeof(vdisk_t)); + + uvm_km_free(kmem_map, (vaddr_t)buf, PAGE_SIZE); + + return nr; +} + +static struct xbd_attach_args * +get_xbda(vdisk_t *xd) +{ + + switch (XEN_MAJOR(xd->device)) { +#if NSD > 0 + case XEN_SCSI_DISK0_MAJOR: + case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR: + case XEN_SCSI_DISK8_MAJOR ... XEN_SCSI_DISK15_MAJOR: + if (xd->capacity == 0) + return NULL; + return &sd_ata; + case XEN_SCSI_CDROM_MAJOR: + return &cd_ata; +#endif +#if NWD > 0 + case XEN_IDE0_MAJOR: + case XEN_IDE1_MAJOR: + case XEN_IDE2_MAJOR: + case XEN_IDE3_MAJOR: + case XEN_IDE4_MAJOR: + case XEN_IDE5_MAJOR: + case XEN_IDE6_MAJOR: + case XEN_IDE7_MAJOR: + case XEN_IDE8_MAJOR: + case XEN_IDE9_MAJOR: + switch (VDISK_TYPE(xd->info)) { + case VDISK_TYPE_CDROM: + return &cd_ata; + case VDISK_TYPE_DISK: + if (xd->capacity == 0) + return NULL; + return &wd_ata; + default: + return NULL; + } + break; +#endif + default: + if (xd->capacity == 0) + return NULL; + return &xbd_ata; + } + return NULL; +} + +static void +free_interface(void) +{ + + /* Prevent new requests being issued until we fix things up. */ + // simple_lock(&blkif_io_lock); + // recovery = 1; + state = STATE_DISCONNECTED; + // simple_unlock(&blkif_io_lock); + + /* Free resources associated with old device channel. */ + if (blk_ring) { + uvm_km_free(kmem_map, (vaddr_t)blk_ring, PAGE_SIZE); + blk_ring = NULL; } - return op.u.probe_params.xdi.count; + if (blkif_irq) { +#if 0 + free_irq(blkif_irq, NULL); +#endif + blkif_irq = 0; + } + + if (blkif_evtchn) { +#if 0 + unbind_evtchn_from_irq(blkif_evtchn); +#endif + blkif_evtchn = 0; + } +} + +static void +close_interface(void){ +} + +static void +disconnect_interface(void) +{ + + if (blk_ring == NULL) + blk_ring = (blkif_ring_t *)uvm_km_kmemalloc1(kmem_map, NULL, + PAGE_SIZE, PAGE_SIZE, UVM_UNKNOWN_OFFSET, 0); + memset(blk_ring, 0, PAGE_SIZE); + blk_ring->req_prod = blk_ring->resp_prod = resp_cons = req_prod = + last_req_prod = 0; + state = STATE_DISCONNECTED; + send_interface_connect(); } static void reset_interface(void) { - block_io_op_t op; - op.cmd = BLOCK_IO_OP_RESET; - if (HYPERVISOR_block_io_op(&op) != 0) - printf("xbd: Possible blkdev trouble: couldn't reset ring\n"); + printf("Recovering virtual block device driver\n"); + free_interface(); + disconnect_interface(); } static void -init_interface(void) +connect_interface(blkif_fe_interface_status_t *status) { - block_io_op_t op; + // unsigned long flags; + struct xbd_attach_args *xbda; + vdisk_t *xd; + int i; - reset_interface(); + blkif_evtchn = status->evtchn; + blkif_irq = bind_evtchn_to_irq(blkif_evtchn); - if (blk_ring == NULL) { - op.cmd = BLOCK_IO_OP_RING_ADDRESS; - (void)HYPERVISOR_block_io_op(&op); + event_set_handler(blkif_irq, &xbd_response_handler, NULL, IPL_BIO); + hypervisor_enable_irq(blkif_irq); - blk_ring = (blk_ring_t *)uvm_km_valloc_align(kernel_map, - PAGE_SIZE, PAGE_SIZE); - pmap_kenter_ma((vaddr_t)blk_ring, op.u.ring_mfn << PAGE_SHIFT, - VM_PROT_READ|VM_PROT_WRITE); - DPRINTF(XBDB_SETUP, ("init_interface: " - "ring va %p and wired to %p\n", - blk_ring, (void *)(op.u.ring_mfn << PAGE_SHIFT))); + /* Transition to connected in case we need to do + * a partition probe on a whole disk. */ + state = STATE_CONNECTED; - blk_ring->req_prod = blk_ring->resp_prod = - resp_cons = req_prod = last_req_prod = 0; + /* Probe for discs attached to the interface. */ + // xlvbd_init(); + MALLOC(vbd_info, vdisk_t *, MAX_VBDS * sizeof(vdisk_t), + M_DEVBUF, M_WAITOK); + memset(vbd_info, 0, MAX_VBDS * sizeof(vdisk_t)); + nr_vbds = get_vbd_info(vbd_info); + if (nr_vbds <= 0) + goto out; - event_set_handler(_EVENT_BLKDEV, &xbd_response_handler, - NULL, IPL_BIO); - hypervisor_enable_event(_EVENT_BLKDEV); + for (i = 0; i < nr_vbds; i++) { + xd = &vbd_info[i]; + xbda = get_xbda(xd); + if (xbda) { + xbda->xa_xd = xd; + config_found(blkctrl.xc_parent, xbda, + blkctrl.xc_cfprint); + } } - __insn_barrier(); - state = STATE_ACTIVE; +#if 0 + /* Kick pending requests. */ + save_and_cli(flags); + // simple_lock(&blkif_io_lock); + kick_pending_request_queues(); + // simple_unlock(&blkif_io_lock); + restore_flags(flags); +#endif + return; + + out: + FREE(vbd_info, M_DEVBUF); + vbd_info = NULL; + return; +} + +static void +unexpected(blkif_fe_interface_status_t *status) +{ + + printf("Unexpected blkif status %d in state %d\n", + status->status, state); } +#if 0 +static struct device * +find_device(vdisk_t *xd) +{ + struct device *dv; + struct xbd_softc *xs = NULL; + + for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) { + if (dv->dv_cfattach == NULL || + dv->dv_cfattach->ca_attach != xbd_attach) + continue; + xs = (struct xbd_softc *)dv; + if (xd == NULL || xs->sc_xd_device == xd->device) + break; + } + return dv; +} +#endif + +static void +blkif_status(blkif_fe_interface_status_t *status) +{ + + if (status->handle != blkif_handle) { + printf("Invalid blkif: handle=%u", status->handle); + return; + } + + switch (status->status) { + case BLKIF_INTERFACE_STATUS_CLOSED: + switch (state) { + case STATE_CLOSED: + unexpected(status); + break; + case STATE_DISCONNECTED: + case STATE_CONNECTED: + unexpected(status); + close_interface(); + break; + } + break; + + case BLKIF_INTERFACE_STATUS_DISCONNECTED: + switch (state) { + case STATE_CLOSED: + disconnect_interface(); + break; + case STATE_DISCONNECTED: + case STATE_CONNECTED: + unexpected(status); + reset_interface(); + break; + } + break; + + case BLKIF_INTERFACE_STATUS_CONNECTED: + switch (state) { + case STATE_CLOSED: + unexpected(status); + disconnect_interface(); + connect_interface(status); + break; + case STATE_DISCONNECTED: + connect_interface(status); + break; + case STATE_CONNECTED: + unexpected(status); + connect_interface(status); + break; + } + break; + + case BLKIF_INTERFACE_STATUS_CHANGED: + switch (state) { + case STATE_CLOSED: + case STATE_DISCONNECTED: + unexpected(status); + break; + case STATE_CONNECTED: +#if 0 + vbd_update(); +#endif + break; + } + break; + + default: + printf(" Invalid blkif status: %d\n", status->status); + break; + } +} + + +static void +xbd_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) +{ + switch (msg->subtype) { + case CMSG_BLKIF_FE_INTERFACE_STATUS: + if (msg->length != sizeof(blkif_fe_interface_status_t)) + goto parse_error; + blkif_status((blkif_fe_interface_status_t *) + &msg->msg[0]); + break; + default: + goto parse_error; + } + + ctrl_if_send_response(msg); + return; + + parse_error: + msg->length = 0; + ctrl_if_send_response(msg); +} + +#if 0 static void enable_update_events(struct device *self) { @@ -468,23 +734,109 @@ enable_update_events(struct device *self) event_set_handler(_EVENT_VBD_UPD, &xbd_update_handler, self, IPL_BIO); hypervisor_enable_event(_EVENT_VBD_UPD); } +#endif static void signal_requests_to_xen(void) { - block_io_op_t op; - DPRINTF(XBDB_IO, ("signal_requests_to_xen: %d -> %d\n", - blk_ring->req_prod, MASK_BLK_IDX(req_prod))); - blk_ring->req_prod = MASK_BLK_IDX(req_prod); + DPRINTF(XBDB_IO, ("signal_requests_to_xen: %x -> %x\n", + blk_ring->req_prod, req_prod)); + blk_ring->req_prod = req_prod; last_req_prod = req_prod; - op.cmd = BLOCK_IO_OP_SIGNAL; - HYPERVISOR_block_io_op(&op); + hypervisor_notify_via_evtchn(blkif_evtchn); return; } static void +control_send(blkif_request_t *req, blkif_response_t *rsp) +{ + unsigned long flags; + struct xbdreq *xr; + + retry: + while ((req_prod - resp_cons) == BLKIF_RING_SIZE) { + tsleep((caddr_t) &req_prod, PUSER | PCATCH, + "blkfront", 0); + } + + save_and_cli(flags); + // simple_lock(&blkif_io_lock); + if ((req_prod - resp_cons) == BLKIF_RING_SIZE) { + // simple_unlock(&blkif_io_lock); + restore_flags(flags); + goto retry; + } + + blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req; + + GET_XBDREQ(xr); + blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req.id = (unsigned long)xr; + // rec_ring[id].id = (unsigned long) req; + + // translate_req_to_pfn( &rec_ring[id], req ); + + req_prod++; + signal_requests_to_xen(); + + // simple_unlock(&blkif_io_lock); + restore_flags(flags); + + while (!blkif_control_rsp_valid) { + /* XXXcl: sleep/wakeup not ready yet - busy wait for now. + * interrupts are still of, so we pick up the control + * channel response on return from HYPERVISOR_yield(). + */ +#if 0 + tsleep((caddr_t)&blkif_control_rsp_valid, PUSER | PCATCH, + "blkfront", 0); +#else + HYPERVISOR_yield(); +#endif + } + + memcpy(rsp, &blkif_control_rsp, sizeof(*rsp)); + blkif_control_rsp_valid = 0; +} + +/* Send a driver status notification to the domain controller. */ +static void +send_driver_status(int ok) +{ + ctrl_msg_t cmsg = { + .type = CMSG_BLKIF_FE, + .subtype = CMSG_BLKIF_FE_DRIVER_STATUS, + .length = sizeof(blkif_fe_driver_status_t), + }; + blkif_fe_driver_status_t *msg = (void*)cmsg.msg; + + msg->status = ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN; + + ctrl_if_send_message_block(&cmsg, NULL, 0, 0); +} + +/* Tell the controller to bring up the interface. */ +static void +send_interface_connect(void) +{ + ctrl_msg_t cmsg = { + .type = CMSG_BLKIF_FE, + .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT, + .length = sizeof(blkif_fe_interface_connect_t), + }; + blkif_fe_interface_connect_t *msg = (void*)cmsg.msg; + paddr_t pa; + + pmap_extract(pmap_kernel(), (vaddr_t)blk_ring, &pa); + + msg->handle = 0; + msg->shmem_frame = xpmap_ptom_masked(pa) >> PAGE_SHIFT; + + ctrl_if_send_message_block(&cmsg, NULL, 0, 0); +} + +static void setup_sysctl(void) { struct sysctlnode *pnode; @@ -514,62 +866,16 @@ setup_sysctl(void) diskcookies = pnode; } -static struct xbd_attach_args * -get_xbda(xen_disk_t *xd) -{ - - switch (XEN_MAJOR(xd->device)) { -#if NSD > 0 - case XEN_SCSI_DISK0_MAJOR: - case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR: - case XEN_SCSI_DISK8_MAJOR ... XEN_SCSI_DISK15_MAJOR: - if (xd->capacity == 0) - return NULL; - return &sd_ata; - case XEN_SCSI_CDROM_MAJOR: - return &cd_ata; -#endif -#if NWD > 0 - case XEN_IDE0_MAJOR: - case XEN_IDE1_MAJOR: - case XEN_IDE2_MAJOR: - case XEN_IDE3_MAJOR: - case XEN_IDE4_MAJOR: - case XEN_IDE5_MAJOR: - case XEN_IDE6_MAJOR: - case XEN_IDE7_MAJOR: - case XEN_IDE8_MAJOR: - case XEN_IDE9_MAJOR: - switch (XD_TYPE(xd->info)) { - case XD_TYPE_CDROM: - return &cd_ata; - case XD_TYPE_DISK: - if (xd->capacity == 0) - return NULL; - return &wd_ata; - default: - return NULL; - } - break; -#endif - default: - if (xd->capacity == 0) - return NULL; - return &xbd_ata; - } - return NULL; -} - int xbd_scan(struct device *self, struct xbd_attach_args *mainbus_xbda, cfprint_t print) { struct xbdreq *xr; - struct xbd_attach_args *xbda; - xen_disk_t *xd; int i; - init_interface(); + blkctrl.xc_parent = self; + blkctrl.xc_cfprint = print; + if (xen_start_info.flags & SIF_PRIVILEGED) setup_sysctl(); @@ -593,47 +899,23 @@ xbd_scan(struct device *self, struct xbd_attach_args *mainbus_xbda, xbd_cd_cdev_major = major(devsw_blk2chr(makedev(xbd_cd_major, 0))); #endif - MALLOC(xr, struct xbdreq *, BLK_RING_SIZE * sizeof(struct xbdreq), + MALLOC(xr, struct xbdreq *, BLKIF_RING_SIZE * sizeof(struct xbdreq), M_DEVBUF, M_WAITOK | M_ZERO); #ifdef DEBUG xbd_allxr = xr; #endif - - /* XXX Xen1.2: We cannot use BLK_RING_SIZE many slots, since - * Xen 1.2 keeps indexes masked in the ring and the case where - * we queue all slots at once is handled wrong. - */ - for (i = 0; i < BLK_RING_SIZE - 1; i++) + for (i = 0; i < BLKIF_RING_SIZE - 1; i++) PUT_XBDREQ(&xr[i]); - MALLOC(vbd_info, xen_disk_t *, MAX_VBDS * sizeof(xen_disk_t), - M_DEVBUF, M_WAITOK); - memset(vbd_info, 0, MAX_VBDS * sizeof(xen_disk_t)); - nr_vbds = get_vbd_info(vbd_info); - if (nr_vbds <= 0) - goto out; + (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, xbd_ctrlif_rx, + CALLBACK_IN_BLOCKING_CONTEXT); - for (i = 0; i < nr_vbds; i++) { - xd = &vbd_info[i]; - xbda = get_xbda(xd); - if (xbda) { - xbda->xa_xd = xd; - config_found(self, xbda, print); - } - } + send_driver_status(1); +#if 0 enable_update_events(self); - - return 0; - - out: - FREE(vbd_info, M_DEVBUF); - vbd_info = NULL; - FREE(xr, M_DEVBUF); -#ifdef DEBUG - xbd_allxr = NULL; #endif - SLIST_INIT(&xbdreqs); + return 0; } @@ -844,20 +1126,21 @@ fill_ring(struct xbdreq *xr) paddr_t pa; unsigned long ma; vaddr_t addr, off; - blk_ring_req_entry_t *ring_req; - int breq, nr_sectors; + blkif_request_t *ring_req; + int breq, nr_sectors, fsect, lsect; /* Fill out a communications ring structure. */ - ring_req = &blk_ring->ring[MASK_BLK_IDX(req_prod)].req; + ring_req = &blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req; ring_req->id = (unsigned long)xr; - ring_req->operation = pxr->xr_bp->b_flags & B_READ ? XEN_BLOCK_READ : - XEN_BLOCK_WRITE; - ring_req->sector_number = (xen_sector_t)pxr->xr_bn; + ring_req->operation = pxr->xr_bp->b_flags & B_READ ? BLKIF_OP_READ : + BLKIF_OP_WRITE; + ring_req->sector_number = pxr->xr_bn; ring_req->device = pxr->xr_sc->sc_xd_device; DPRINTF(XBDB_IO, ("fill_ring(%d): bp %p sector %llu pxr %p xr %p\n", - MASK_BLK_IDX(req_prod), pxr->xr_bp, (unsigned long long)pxr->xr_bn, - pxr, xr)); + MASK_BLKIF_IDX(req_prod), pxr->xr_bp, + (unsigned long long)pxr->xr_bn, + pxr, xr)); xr->xr_breq = 0; ring_req->nr_segments = 0; @@ -870,7 +1153,7 @@ fill_ring(struct xbdreq *xr) #else pmap_extract(pmap_kernel(), addr, &pa); #endif - ma = xpmap_ptom_masked(pa) + off; + ma = xpmap_ptom_masked(pa); DIAGCONDPANIC((ma & (XEN_BSIZE - 1)) != 0, ("xbd request ma not sector aligned")); @@ -878,23 +1161,29 @@ fill_ring(struct xbdreq *xr) breq = PAGE_SIZE - off; else breq = pxr->xr_bqueue; + nr_sectors = breq >> XEN_BSHIFT; DIAGCONDPANIC(nr_sectors >= XEN_BSIZE, ("xbd request nr_sectors >= XEN_BSIZE")); + fsect = off >> XEN_BSHIFT; + lsect = fsect + nr_sectors - 1; + DIAGCONDPANIC(fsect > 7, ("xbd request fsect > 7")); + DIAGCONDPANIC(lsect > 7, ("xbd request lsect > 7")); + DPRINTF(XBDB_IO, ("fill_ring(%d): va 0x%08lx pa 0x%08lx " "ma 0x%08lx, sectors %d, left %ld/%ld\n", - MASK_BLK_IDX(req_prod), addr, pa, ma, nr_sectors, + MASK_BLKIF_IDX(req_prod), addr, pa, ma, nr_sectors, pxr->xr_bqueue >> XEN_BSHIFT, pxr->xr_bqueue)); - ring_req->buffer_and_sects[ring_req->nr_segments++] = - ma | nr_sectors; + ring_req->frame_and_sects[ring_req->nr_segments++] = + ma | (fsect<<3) | lsect; addr += PAGE_SIZE; pxr->xr_bqueue -= breq; pxr->xr_bn += nr_sectors; xr->xr_breq += breq; off = 0; - if (ring_req->nr_segments == MAX_BLK_SEGS) + if (ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST) break; } pxr->xr_data = addr; @@ -1048,64 +1337,81 @@ xbd_response_handler(void *arg) { struct buf *bp; struct xbd_softc *xs; - blk_ring_resp_entry_t *ring_resp; + blkif_response_t *ring_resp; struct xbdreq *pxr, *xr; - int i; + BLKIF_RING_IDX i, rp; - for (i = resp_cons; i != blk_ring->resp_prod; i = BLK_RING_INC(i)) { - ring_resp = &blk_ring->ring[MASK_BLK_IDX(i)].resp; + rp = blk_ring->resp_prod; + __insn_barrier(); /* Ensure we see queued responses up to 'rp'. */ + + for (i = resp_cons; i != rp; i++) { + ring_resp = &blk_ring->ring[MASK_BLKIF_IDX(i)].resp; xr = (struct xbdreq *)ring_resp->id; - pxr = xr->xr_parent; - - DPRINTF(XBDB_IO, ("xbd_response_handler(%d): pxr %p xr %p " - "bdone %04lx breq %04lx\n", i, pxr, xr, pxr->xr_bdone, - xr->xr_breq)); - pxr->xr_bdone -= xr->xr_breq; - DIAGCONDPANIC(pxr->xr_bdone < 0, - ("xbd_response_handler: pxr->xr_bdone < 0")); - - if (__predict_false(ring_resp->status)) { - pxr->xr_bp->b_flags |= B_ERROR; - pxr->xr_bp->b_error = EIO; - } - if (xr != pxr) { - PUT_XBDREQ(xr); - if (!SIMPLEQ_EMPTY(&xbdr_suspended)) - xbdresume(); - } + switch (ring_resp->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + pxr = xr->xr_parent; + + DPRINTF(XBDB_IO, ("xbd_response_handler(%d): pxr %p " + "xr %p bdone %04lx breq %04lx\n", i, pxr, + xr, pxr->xr_bdone, xr->xr_breq)); + pxr->xr_bdone -= xr->xr_breq; + DIAGCONDPANIC(pxr->xr_bdone < 0, + ("xbd_response_handler: pxr->xr_bdone < 0")); + + if (__predict_false(ring_resp->status)) { + pxr->xr_bp->b_flags |= B_ERROR; + pxr->xr_bp->b_error = EIO; + } - if (pxr->xr_bdone == 0) { - bp = pxr->xr_bp; - xs = getxbd_softc(bp->b_dev); - if (xs == NULL) { /* don't fail bp if we're shutdown */ - bp->b_flags |= B_ERROR; - bp->b_error = EIO; + if (xr != pxr) { + PUT_XBDREQ(xr); + if (!SIMPLEQ_EMPTY(&xbdr_suspended)) + xbdresume(); } - DPRINTF(XBDB_IO, ("xbd_response_handler(%d): " - "completed bp %p\n", i, bp)); - if (bp->b_flags & B_ERROR) - bp->b_resid = bp->b_bcount; - else - bp->b_resid = 0; - - if (pxr->xr_aligned) - unmap_align(pxr); - - PUT_XBDREQ(pxr); - if (xs) - disk_unbusy(&xs->sc_dksc.sc_dkdev, - (bp->b_bcount - bp->b_resid), - (bp->b_flags & B_READ)); - biodone(bp); - if (!SIMPLEQ_EMPTY(&xbdr_suspended)) - xbdresume(); - /* XXX possible lockup if this was the only - * active device and requests were held back in - * the queue. - */ - if (xs) - dk_iodone(xs->sc_di, &xs->sc_dksc); + + if (pxr->xr_bdone == 0) { + bp = pxr->xr_bp; + xs = getxbd_softc(bp->b_dev); + if (xs == NULL) { /* don't fail bp if we're shutdown */ + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + } + DPRINTF(XBDB_IO, ("xbd_response_handler(%d): " + "completed bp %p\n", i, bp)); + if (bp->b_flags & B_ERROR) + bp->b_resid = bp->b_bcount; + else + bp->b_resid = 0; + + if (pxr->xr_aligned) + unmap_align(pxr); + + PUT_XBDREQ(pxr); + if (xs) + disk_unbusy(&xs->sc_dksc.sc_dkdev, + (bp->b_bcount - bp->b_resid), + (bp->b_flags & B_READ)); + biodone(bp); + if (!SIMPLEQ_EMPTY(&xbdr_suspended)) + xbdresume(); + /* XXX possible lockup if this was the only + * active device and requests were held back in + * the queue. + */ + if (xs) + dk_iodone(xs->sc_di, &xs->sc_dksc); + } + break; + case BLKIF_OP_PROBE: + memcpy(&blkif_control_rsp, ring_resp, + sizeof(*ring_resp)); + blkif_control_rsp_valid = 1; + wakeup((caddr_t)&blkif_control_rsp_valid); + break; + default: + panic("unknown response"); } } resp_cons = i; @@ -1115,23 +1421,7 @@ xbd_response_handler(void *arg) return 0; } -static struct device * -find_device(xen_disk_t *xd) -{ - struct device *dv; - struct xbd_softc *xs; - - for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) { - if (dv->dv_cfattach == NULL || - dv->dv_cfattach->ca_attach != xbd_attach) - continue; - xs = (struct xbd_softc *)dv; - if (xs->sc_xd_device == xd->device) - break; - } - return dv; -} - +#if 0 static void xbd_update_create_kthread(void *arg) { @@ -1145,24 +1435,24 @@ xbd_update_kthread(void *arg) struct device *parent = arg; struct xbd_attach_args *xbda; struct device *dev; - xen_disk_t *xd; - xen_disk_t *vbd_info_update, *vbd_info_old; + vdisk_t *xd; + vdisk_t *vbd_info_update, *vbd_info_old; int i, j, new_nr_vbds; extern int hypervisor_print(void *, const char *); - MALLOC(vbd_info_update, xen_disk_t *, MAX_VBDS * - sizeof(xen_disk_t), M_DEVBUF, M_WAITOK); + MALLOC(vbd_info_update, vdisk_t *, MAX_VBDS * + sizeof(vdisk_t), M_DEVBUF, M_WAITOK); for (;;) { - memset(vbd_info_update, 0, MAX_VBDS * sizeof(xen_disk_t)); + memset(vbd_info_update, 0, MAX_VBDS * sizeof(vdisk_t)); new_nr_vbds = get_vbd_info(vbd_info_update); if (memcmp(vbd_info, vbd_info_update, MAX_VBDS * - sizeof(xen_disk_t)) == 0) { + sizeof(vdisk_t)) == 0) { FREE(vbd_info_update, M_DEVBUF); tsleep(parent, PWAIT, "xbdupd", 0); - MALLOC(vbd_info_update, xen_disk_t *, MAX_VBDS * - sizeof(xen_disk_t), M_DEVBUF, M_WAITOK); + MALLOC(vbd_info_update, vdisk_t *, MAX_VBDS * + sizeof(vdisk_t), M_DEVBUF, M_WAITOK); continue; } @@ -1228,6 +1518,7 @@ xbd_update_handler(void *arg) return 0; } +#endif /* XXX: we should probably put these into dksubr.c, mostly */ int @@ -1309,7 +1600,7 @@ xbddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) } static int -xbdinit(struct xbd_softc *xs, xen_disk_t *xd, struct dk_intf *dkintf) +xbdinit(struct xbd_softc *xs, vdisk_t *xd, struct dk_intf *dkintf) { struct dk_geom *pdg; char buf[9]; |