aboutsummaryrefslogtreecommitdiffstats
path: root/netbsd-2.0-xen-sparse
diff options
context:
space:
mode:
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>2004-09-27 16:47:41 +0000
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>2004-09-27 16:47:41 +0000
commit082a3d52cc94f427a8d46940281a99be9581d0dc (patch)
tree38ff5077853d9aa7d2dbc2fbaed23990153f0881 /netbsd-2.0-xen-sparse
parentcf5252944715e7ca3eda163e9d9c71aab2f61af7 (diff)
downloadxen-082a3d52cc94f427a8d46940281a99be9581d0dc.tar.gz
xen-082a3d52cc94f427a8d46940281a99be9581d0dc.tar.bz2
xen-082a3d52cc94f427a8d46940281a99be9581d0dc.zip
bitkeeper revision 1.1159.94.1 (4158442dkfhj0Lw3hZW1w5YYKJA01g)
Add support for block devices.
Diffstat (limited to 'netbsd-2.0-xen-sparse')
-rw-r--r--netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN8
-rw-r--r--netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h1
-rw-r--r--netbsd-2.0-xen-sparse/sys/arch/xen/include/xbdvar.h56
-rw-r--r--netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c749
4 files changed, 581 insertions, 233 deletions
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];