aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/xen
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/xen')
-rw-r--r--sys/dev/xen/blkback/blkback.c22
-rw-r--r--sys/dev/xen/blkfront/blkfront.c51
-rw-r--r--sys/dev/xen/bus/xen_intr.c2
-rw-r--r--sys/dev/xen/bus/xenpv.c84
-rw-r--r--sys/dev/xen/console/xen_console.c3
-rw-r--r--sys/dev/xen/control/control.c60
-rw-r--r--sys/dev/xen/debug/debug.c10
-rw-r--r--sys/dev/xen/efi/pvefi.c6
-rw-r--r--sys/dev/xen/gntdev/gntdev.c13
-rw-r--r--sys/dev/xen/netfront/netfront.c38
-rw-r--r--sys/dev/xen/pcifront/pcifront.c690
-rw-r--r--sys/dev/xen/privcmd/privcmd.c14
-rw-r--r--sys/dev/xen/xenpci/xenpci.c6
-rw-r--r--sys/dev/xen/xenstore/xenstore.c11
14 files changed, 874 insertions, 136 deletions
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index 3717264256f3..c6cba729b991 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -145,6 +145,8 @@ static MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data");
*/
#define XBB_MAX_SEGMENTS_PER_REQLIST XBB_MAX_SEGMENTS_PER_REQUEST
+#define XBD_SECTOR_SHFT 9
+
/*--------------------------- Forward Declarations ---------------------------*/
struct xbb_softc;
struct xbb_xen_req;
@@ -1150,7 +1152,9 @@ xbb_get_resources(struct xbb_softc *xbb, struct xbb_xen_reqlist **reqlist,
if (*reqlist == NULL) {
*reqlist = nreqlist;
nreqlist->operation = ring_req->operation;
- nreqlist->starting_sector_number = ring_req->sector_number;
+ nreqlist->starting_sector_number =
+ (ring_req->sector_number << XBD_SECTOR_SHFT) >>
+ xbb->sector_size_shift;
STAILQ_INSERT_TAIL(&xbb->reqlist_pending_stailq, nreqlist,
links);
}
@@ -2476,13 +2480,13 @@ xbb_open_file(struct xbb_softc *xbb)
xbb->sector_size = 512;
/*
- * Sanity check. The media size has to be at least one
- * sector long.
+ * Sanity check. The media size must be a multiple of the sector
+ * size.
*/
- if (xbb->media_size < xbb->sector_size) {
+ if ((xbb->media_size % xbb->sector_size) != 0) {
error = EINVAL;
xenbus_dev_fatal(xbb->dev, error,
- "file %s size %ju < block size %u",
+ "file %s size %ju not multiple of block size %u",
xbb->dev_name,
(uintmax_t)xbb->media_size,
xbb->sector_size);
@@ -3086,9 +3090,13 @@ xbb_publish_backend_info(struct xbb_softc *xbb)
return (error);
}
+ /*
+ * The 'sectors' node is special and always contains the size
+ * in units of 512b, regardless of the value in 'sector-size'.
+ */
leaf = "sectors";
- error = xs_printf(xst, our_path, leaf,
- "%"PRIu64, xbb->media_num_sectors);
+ error = xs_printf(xst, our_path, leaf, "%ju",
+ (uintmax_t)(xbb->media_size >> XBD_SECTOR_SHFT));
if (error != 0)
break;
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index 2c5862232b41..6bb4e32f1328 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -158,7 +158,8 @@ xbd_free_command(struct xbd_command *cm)
static void
xbd_mksegarray(bus_dma_segment_t *segs, int nsegs,
grant_ref_t * gref_head, int otherend_id, int readonly,
- grant_ref_t * sg_ref, struct blkif_request_segment *sg)
+ grant_ref_t * sg_ref, struct blkif_request_segment *sg,
+ unsigned int sector_size)
{
struct blkif_request_segment *last_block_sg = sg + nsegs;
vm_paddr_t buffer_ma;
@@ -166,9 +167,9 @@ xbd_mksegarray(bus_dma_segment_t *segs, int nsegs,
int ref;
while (sg < last_block_sg) {
- KASSERT(segs->ds_addr % (1 << XBD_SECTOR_SHFT) == 0,
+ KASSERT((segs->ds_addr & (sector_size - 1)) == 0,
("XEN disk driver I/O must be sector aligned"));
- KASSERT(segs->ds_len % (1 << XBD_SECTOR_SHFT) == 0,
+ KASSERT((segs->ds_len & (sector_size - 1)) == 0,
("XEN disk driver I/Os must be a multiple of "
"the sector length"));
buffer_ma = segs->ds_addr;
@@ -241,7 +242,8 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
xenbus_get_otherend_id(sc->xbd_dev),
cm->cm_operation == BLKIF_OP_WRITE,
- cm->cm_sg_refs, ring_req->seg);
+ cm->cm_sg_refs, ring_req->seg,
+ sc->xbd_disk->d_sectorsize);
} else {
blkif_request_indirect_t *ring_req;
@@ -259,7 +261,8 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
xenbus_get_otherend_id(sc->xbd_dev),
cm->cm_operation == BLKIF_OP_WRITE,
- cm->cm_sg_refs, cm->cm_indirectionpages);
+ cm->cm_sg_refs, cm->cm_indirectionpages,
+ sc->xbd_disk->d_sectorsize);
memcpy(ring_req->indirect_grefs, &cm->cm_indirectionrefs,
sizeof(grant_ref_t) * sc->xbd_max_request_indirectpages);
}
@@ -359,7 +362,9 @@ xbd_bio_command(struct xbd_softc *sc)
}
cm->cm_bp = bp;
- cm->cm_sector_number = (blkif_sector_t)bp->bio_pblkno;
+ cm->cm_sector_number =
+ ((blkif_sector_t)bp->bio_pblkno * sc->xbd_disk->d_sectorsize) >>
+ XBD_SECTOR_SHFT;
switch (bp->bio_cmd) {
case BIO_READ:
@@ -631,7 +636,7 @@ xbd_dump(void *arg, void *virtual, off_t offset, size_t length)
cm->cm_data = virtual;
cm->cm_datalen = chunk;
cm->cm_operation = BLKIF_OP_WRITE;
- cm->cm_sector_number = offset / dp->d_sectorsize;
+ cm->cm_sector_number = offset >> XBD_SECTOR_SHFT;
cm->cm_complete = xbd_dump_complete;
xbd_enqueue_cm(cm, XBD_Q_READY);
@@ -1025,7 +1030,19 @@ xbd_instance_create(struct xbd_softc *sc, blkif_sector_t sectors,
sc->xbd_disk->d_stripesize = phys_sector_size;
sc->xbd_disk->d_stripeoffset = 0;
- sc->xbd_disk->d_mediasize = sectors * sector_size;
+ /*
+ * The 'sectors' xenbus node is always in units of 512b, regardless of
+ * the 'sector-size' xenbus node value.
+ */
+ sc->xbd_disk->d_mediasize = sectors << XBD_SECTOR_SHFT;
+ if ((sc->xbd_disk->d_mediasize % sc->xbd_disk->d_sectorsize) != 0) {
+ error = EINVAL;
+ xenbus_dev_fatal(sc->xbd_dev, error,
+ "Disk size (%ju) not a multiple of sector size (%ju)",
+ (uintmax_t)sc->xbd_disk->d_mediasize,
+ (uintmax_t)sc->xbd_disk->d_sectorsize);
+ return (error);
+ }
sc->xbd_disk->d_maxsize = sc->xbd_max_request_size;
sc->xbd_disk->d_flags = DISKFLAG_UNMAPPED_BIO;
if ((sc->xbd_flags & (XBDF_FLUSH|XBDF_BARRIER)) != 0) {
@@ -1064,9 +1081,7 @@ xbd_free(struct xbd_softc *sc)
gnttab_end_foreign_access_references(
sc->xbd_max_request_indirectpages,
&cm->cm_indirectionrefs[0]);
- contigfree(cm->cm_indirectionpages, PAGE_SIZE *
- sc->xbd_max_request_indirectpages,
- M_XENBLOCKFRONT);
+ free(cm->cm_indirectionpages, M_XENBLOCKFRONT);
cm->cm_indirectionpages = NULL;
}
@@ -1312,7 +1327,7 @@ xbd_connect(struct xbd_softc *sc)
/* Allocate datastructures based on negotiated values. */
err = bus_dma_tag_create(
bus_get_dma_tag(sc->xbd_dev), /* parent */
- 512, PAGE_SIZE, /* algnmnt, boundary */
+ sector_size, PAGE_SIZE, /* algnmnt, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -1373,9 +1388,7 @@ xbd_connect(struct xbd_softc *sc)
break;
}
if (j < sc->xbd_max_request_indirectpages) {
- contigfree(indirectpages,
- PAGE_SIZE * sc->xbd_max_request_indirectpages,
- M_XENBLOCKFRONT);
+ free(indirectpages, M_XENBLOCKFRONT);
break;
}
cm->cm_indirectionpages = indirectpages;
@@ -1384,13 +1397,17 @@ xbd_connect(struct xbd_softc *sc)
if (sc->xbd_disk == NULL) {
device_printf(dev, "%juMB <%s> at %s",
- (uintmax_t) sectors / (1048576 / sector_size),
+ (uintmax_t)((sectors << XBD_SECTOR_SHFT) / 1048576),
device_get_desc(dev),
xenbus_get_node(dev));
bus_print_child_footer(device_get_parent(dev), dev);
- xbd_instance_create(sc, sectors, sc->xbd_vdevice, binfo,
+ err = xbd_instance_create(sc, sectors, sc->xbd_vdevice, binfo,
sector_size, phys_sector_size);
+ if (err != 0) {
+ xenbus_dev_fatal(dev, err, "Unable to create instance");
+ return;
+ }
}
(void)xenbus_set_state(dev, XenbusStateConnected);
diff --git a/sys/dev/xen/bus/xen_intr.c b/sys/dev/xen/bus/xen_intr.c
index bfe080b16f03..cb30b6efa484 100644
--- a/sys/dev/xen/bus/xen_intr.c
+++ b/sys/dev/xen/bus/xen_intr.c
@@ -45,12 +45,12 @@
#include <sys/proc.h>
#include <sys/smp.h>
#include <sys/refcount.h>
+#include <sys/stdarg.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/smp.h>
-#include <machine/stdarg.h>
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
diff --git a/sys/dev/xen/bus/xenpv.c b/sys/dev/xen/bus/xenpv.c
index 169e52f3a879..f710b0f91140 100644
--- a/sys/dev/xen/bus/xenpv.c
+++ b/sys/dev/xen/bus/xenpv.c
@@ -65,6 +65,16 @@
#define LOW_MEM_LIMIT 0
#endif
+/*
+ * Memory ranges available for creating external mappings (foreign or grant
+ * pages for example).
+ */
+static struct rman unpopulated_mem = {
+ .rm_end = ~0,
+ .rm_type = RMAN_ARRAY,
+ .rm_descr = "Xen scratch memory",
+};
+
static void
xenpv_identify(driver_t *driver, device_t parent)
{
@@ -91,23 +101,43 @@ xenpv_probe(device_t dev)
return (BUS_PROBE_NOWILDCARD);
}
+/* Dummy init for arches that don't have a specific implementation. */
+int __weak_symbol
+xen_arch_init_physmem(device_t dev, struct rman *mem)
+{
+
+ return (0);
+}
+
static int
xenpv_attach(device_t dev)
{
- int error;
+ int error = rman_init(&unpopulated_mem);
+
+ if (error != 0)
+ return (error);
+
+ error = xen_arch_init_physmem(dev, &unpopulated_mem);
+ if (error != 0)
+ return (error);
/*
* Let our child drivers identify any child devices that they
* can find. Once that is done attach any devices that we
* found.
*/
- error = bus_generic_probe(dev);
- if (error)
- return (error);
+ bus_identify_children(dev);
+ bus_attach_children(dev);
- error = bus_generic_attach(dev);
+ return (0);
+}
- return (error);
+static int
+release_unpopulated_mem(device_t dev, struct resource *res)
+{
+
+ return (rman_is_region_manager(res, &unpopulated_mem) ?
+ rman_release_resource(res) : bus_release_resource(dev, res));
}
static struct resource *
@@ -117,17 +147,48 @@ xenpv_alloc_physmem(device_t dev, device_t child, int *res_id, size_t size)
vm_paddr_t phys_addr;
void *virt_addr;
int error;
+ const unsigned int flags = RF_ACTIVE | RF_UNMAPPED |
+ RF_ALIGNMENT_LOG2(PAGE_SHIFT);
+
+ KASSERT((size & PAGE_MASK) == 0, ("unaligned size requested"));
+ size = round_page(size);
+
+ /* Attempt to allocate from arch resource manager. */
+ res = rman_reserve_resource(&unpopulated_mem, 0, ~0, size, flags,
+ child);
+ if (res != NULL) {
+ rman_set_rid(res, *res_id);
+ rman_set_type(res, SYS_RES_MEMORY);
+ } else {
+ static bool warned = false;
- res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id, LOW_MEM_LIMIT,
- ~0, size, RF_ACTIVE | RF_UNMAPPED);
- if (res == NULL)
+ /* Fallback to generic MMIO allocator. */
+ if (__predict_false(!warned)) {
+ warned = true;
+ device_printf(dev,
+ "unable to allocate from arch specific routine, "
+ "fall back to unused memory areas\n");
+ }
+ res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id,
+ LOW_MEM_LIMIT, ~0, size, flags);
+ }
+
+ if (res == NULL) {
+ device_printf(dev,
+ "failed to allocate Xen unpopulated memory\n");
return (NULL);
+ }
phys_addr = rman_get_start(res);
error = vm_phys_fictitious_reg_range(phys_addr, phys_addr + size,
VM_MEMATTR_XEN);
if (error) {
- bus_release_resource(child, SYS_RES_MEMORY, *res_id, res);
+ int error = release_unpopulated_mem(child, res);
+
+ if (error != 0)
+ device_printf(dev, "failed to release resource: %d\n",
+ error);
+
return (NULL);
}
virt_addr = pmap_mapdev_attr(phys_addr, size, VM_MEMATTR_XEN);
@@ -150,7 +211,8 @@ xenpv_free_physmem(device_t dev, device_t child, int res_id, struct resource *re
pmap_unmapdev(virt_addr, size);
vm_phys_fictitious_unreg_range(phys_addr, phys_addr + size);
- return (bus_release_resource(child, SYS_RES_MEMORY, res_id, res));
+
+ return (release_unpopulated_mem(child, res));
}
static device_method_t xenpv_methods[] = {
diff --git a/sys/dev/xen/console/xen_console.c b/sys/dev/xen/console/xen_console.c
index f1a298a2aefa..1d12d6caa257 100644
--- a/sys/dev/xen/console/xen_console.c
+++ b/sys/dev/xen/console/xen_console.c
@@ -42,8 +42,7 @@
#include <sys/kdb.h>
#include <sys/proc.h>
#include <sys/reboot.h>
-
-#include <machine/stdarg.h>
+#include <sys/stdarg.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index 1dc1df935b84..123df4992894 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause AND BSD-4-Clause
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 Justin T. Gibbs, Spectra Logic Corporation
* All rights reserved.
@@ -31,39 +31,6 @@
*/
/*-
- * PV suspend/resume support:
- *
- * Copyright (c) 2004 Christian Limpach.
- * Copyright (c) 2004-2006,2008 Kip Macy
- * 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.
- */
-
-/*-
* HVM suspend/resume support:
*
* Copyright (c) 2008 Citrix Systems, Inc.
@@ -394,6 +361,20 @@ xctrl_on_watch_event(struct xs_watch *watch, const char **vec, unsigned int len)
}
/*------------------ Private Device Attachment Functions --------------------*/
+
+static void
+notify_support(void)
+{
+ /*
+ * Notify kernel is ready to handle "control/shutdown" events. Ignore
+ * errors if the nodes haven't been created by the toolstack, as the
+ * parent "control" directory should be read-only for the guest.
+ */
+ xs_write(XST_NIL, "control", "feature-poweroff", "1");
+ xs_write(XST_NIL, "control", "feature-reboot", "1");
+ xs_write(XST_NIL, "control", "feature-suspend", "1");
+}
+
/**
* \brief Identify instances of this device type in the system.
*
@@ -455,6 +436,8 @@ xctrl_attach(device_t dev)
EVENTHANDLER_REGISTER(shutdown_final, xctrl_shutdown_final, NULL,
SHUTDOWN_PRI_LAST);
+ notify_support();
+
return (0);
}
@@ -479,6 +462,14 @@ xctrl_detach(device_t dev)
return (0);
}
+static int
+xctrl_resume(device_t dev)
+{
+ notify_support();
+
+ return (0);
+}
+
/*-------------------- Private Device Attachment Data -----------------------*/
static device_method_t xctrl_methods[] = {
/* Device interface */
@@ -486,6 +477,7 @@ static device_method_t xctrl_methods[] = {
DEVMETHOD(device_probe, xctrl_probe),
DEVMETHOD(device_attach, xctrl_attach),
DEVMETHOD(device_detach, xctrl_detach),
+ DEVMETHOD(device_resume, xctrl_resume),
DEVMETHOD_END
};
diff --git a/sys/dev/xen/debug/debug.c b/sys/dev/xen/debug/debug.c
index f17d0c612262..2889b5efdba7 100644
--- a/sys/dev/xen/debug/debug.c
+++ b/sys/dev/xen/debug/debug.c
@@ -58,8 +58,11 @@ static struct sbuf *buf;
static int
xendebug_drain(void *arg, const char *str, int len)
{
-
- HYPERVISOR_console_write(__DECONST(char *, str), len);
+ /*
+ * Use xen_emergency_print() instead of xc_printf() to avoid the
+ * overhead of parsing a format string when it's not needed.
+ */
+ xen_emergency_print(str, len);
return (len);
}
@@ -75,10 +78,9 @@ xendebug_filter(void *arg __unused)
stack_save(&st);
mtx_lock_spin(&lock);
- sbuf_clear(buf);
xc_printf("Printing stack trace vCPU%u\n", XEN_VCPUID());
stack_sbuf_print_ddb(buf, &st);
- sbuf_finish(buf);
+ sbuf_drain(buf);
mtx_unlock_spin(&lock);
#endif
diff --git a/sys/dev/xen/efi/pvefi.c b/sys/dev/xen/efi/pvefi.c
index f400060c1aac..b69fcd5b80ac 100644
--- a/sys/dev/xen/efi/pvefi.c
+++ b/sys/dev/xen/efi/pvefi.c
@@ -122,7 +122,7 @@ set_time(struct efi_tm *tm)
}
static int
-var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
+var_get(efi_char *name, efi_guid_t *vendor, uint32_t *attrib,
size_t *datasize, void *data)
{
struct xen_platform_op op = {
@@ -151,7 +151,7 @@ var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
}
static int
-var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
+var_nextname(size_t *namesize, efi_char *name, efi_guid_t *vendor)
{
struct xen_platform_op op = {
.cmd = XENPF_efi_runtime_call,
@@ -177,7 +177,7 @@ var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
}
static int
-var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
+var_set(efi_char *name, efi_guid_t *vendor, uint32_t attrib,
size_t datasize, void *data)
{
struct xen_platform_op op = {
diff --git a/sys/dev/xen/gntdev/gntdev.c b/sys/dev/xen/gntdev/gntdev.c
index 4530feb1c76d..e3bc1ecf35ab 100644
--- a/sys/dev/xen/gntdev/gntdev.c
+++ b/sys/dev/xen/gntdev/gntdev.c
@@ -563,7 +563,6 @@ notify_unmap_cleanup(struct gntdev_gmap *gmap)
{
uint32_t i;
int error, count;
- vm_page_t m;
struct gnttab_unmap_grant_ref *unmap_ops;
unmap_ops = malloc(sizeof(struct gnttab_unmap_grant_ref) * gmap->count,
@@ -592,17 +591,7 @@ notify_unmap_cleanup(struct gntdev_gmap *gmap)
}
/* Free the pages. */
- VM_OBJECT_WLOCK(gmap->map->mem);
-retry:
- for (i = 0; i < gmap->count; i++) {
- m = vm_page_lookup(gmap->map->mem, i);
- if (m == NULL)
- continue;
- if (vm_page_busy_acquire(m, VM_ALLOC_WAITFAIL) == 0)
- goto retry;
- cdev_pager_free_page(gmap->map->mem, m);
- }
- VM_OBJECT_WUNLOCK(gmap->map->mem);
+ cdev_mgtdev_pager_free_pages(gmap->map->mem);
/* Perform unmap hypercall. */
error = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 6ac6ecc3bdb7..3bc3679eb0db 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -335,8 +335,16 @@ static void mbuf_release(struct mbuf *m)
KASSERT(ref != NULL, ("Cannot find refcount"));
KASSERT(ref->count > 0, ("Invalid reference count"));
- if (--ref->count == 0)
+ if (--ref->count == 0) {
+ /*
+ * Explicitly free the tag while we hold the tx queue lock.
+ * This ensures that the tag is deleted promptly in case
+ * something else is holding extra references to the mbuf chain,
+ * such as netmap.
+ */
+ m_tag_delete(m, &ref->tag);
m_freem(m);
+ }
}
static void tag_free(struct m_tag *t)
@@ -1021,27 +1029,6 @@ out:
return (error);
}
-#ifdef INET
-static u_int
-netfront_addr_cb(void *arg, struct ifaddr *a, u_int count)
-{
- arp_ifinit((if_t)arg, a);
- return (1);
-}
-/**
- * If this interface has an ipv4 address, send an arp for it. This
- * helps to get the network going again after migrating hosts.
- */
-static void
-netfront_send_fake_arp(device_t dev, struct netfront_info *info)
-{
- if_t ifp;
-
- ifp = info->xn_ifp;
- if_foreach_addr_type(ifp, AF_INET, netfront_addr_cb, ifp);
-}
-#endif
-
/**
* Callback received when the backend's state changes.
*/
@@ -1082,7 +1069,12 @@ netfront_backend_changed(device_t dev, XenbusState newstate)
break;
case XenbusStateConnected:
#ifdef INET
- netfront_send_fake_arp(dev, sc);
+ /*
+ * If this interface has an ipv4 address, send an arp for it.
+ * This helps to get the network going again after migrating
+ * hosts.
+ */
+ EVENTHANDLER_INVOKE(iflladdr_event, sc->xn_ifp);
#endif
break;
}
diff --git a/sys/dev/xen/pcifront/pcifront.c b/sys/dev/xen/pcifront/pcifront.c
new file mode 100644
index 000000000000..76339cd3d361
--- /dev/null
+++ b/sys/dev/xen/pcifront/pcifront.c
@@ -0,0 +1,690 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2006, Cisco Systems, Inc.
+ * 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. Neither the name of Cisco Systems, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/frame.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/intr_machdep.h>
+
+#include <machine/xen-os.h>
+#include <machine/hypervisor.h>
+#include <machine/hypervisor-ifs.h>
+#include <machine/xen_intr.h>
+#include <machine/evtchn.h>
+#include <machine/xenbus.h>
+#include <machine/gnttab.h>
+#include <machine/xen-public/memory.h>
+#include <machine/xen-public/io/pciif.h>
+
+#include <sys/pciio.h>
+#include <dev/pci/pcivar.h>
+#include "pcib_if.h"
+
+#ifdef XEN_PCIDEV_FE_DEBUG
+#define DPRINTF(fmt, args...) \
+ printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
+#else
+#define DPRINTF(fmt, args...) ((void)0)
+#endif
+#define WPRINTF(fmt, args...) \
+ printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
+
+#define INVALID_GRANT_REF (0)
+#define INVALID_EVTCHN (-1)
+#define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
+
+struct pcifront_device {
+ STAILQ_ENTRY(pcifront_device) next;
+
+ struct xenbus_device *xdev;
+
+ int unit;
+ int evtchn;
+ int gnt_ref;
+
+ /* Lock this when doing any operations in sh_info */
+ struct mtx sh_info_lock;
+ struct xen_pci_sharedinfo *sh_info;
+
+ device_t ndev;
+
+ int ref_cnt;
+};
+
+static STAILQ_HEAD(pcifront_dlist, pcifront_device) pdev_list = STAILQ_HEAD_INITIALIZER(pdev_list);
+
+struct xpcib_softc {
+ int domain;
+ int bus;
+ struct pcifront_device *pdev;
+};
+
+/* Allocate a PCI device structure */
+static struct pcifront_device *
+alloc_pdev(struct xenbus_device *xdev)
+{
+ struct pcifront_device *pdev = NULL;
+ int err, unit;
+
+ err = sscanf(xdev->nodename, "device/pci/%d", &unit);
+ if (err != 1) {
+ if (err == 0)
+ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err, "Error scanning pci device instance number");
+ goto out;
+ }
+
+ pdev = (struct pcifront_device *)malloc(sizeof(struct pcifront_device), M_DEVBUF, M_NOWAIT);
+ if (pdev == NULL) {
+ err = -ENOMEM;
+ xenbus_dev_fatal(xdev, err, "Error allocating pcifront_device struct");
+ goto out;
+ }
+ pdev->unit = unit;
+ pdev->xdev = xdev;
+ pdev->ref_cnt = 1;
+
+ pdev->sh_info = (struct xen_pci_sharedinfo *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
+ if (pdev->sh_info == NULL) {
+ free(pdev, M_DEVBUF);
+ pdev = NULL;
+ err = -ENOMEM;
+ xenbus_dev_fatal(xdev, err, "Error allocating sh_info struct");
+ goto out;
+ }
+ pdev->sh_info->flags = 0;
+
+ xdev->data = pdev;
+
+ mtx_init(&pdev->sh_info_lock, "info_lock", "pci shared dev info lock", MTX_DEF);
+
+ pdev->evtchn = INVALID_EVTCHN;
+ pdev->gnt_ref = INVALID_GRANT_REF;
+
+ STAILQ_INSERT_TAIL(&pdev_list, pdev, next);
+
+ DPRINTF("Allocated pdev @ 0x%p (unit=%d)\n", pdev, unit);
+
+ out:
+ return pdev;
+}
+
+/* Hold a reference to a pcifront device */
+static void
+get_pdev(struct pcifront_device *pdev)
+{
+ pdev->ref_cnt++;
+}
+
+/* Release a reference to a pcifront device */
+static void
+put_pdev(struct pcifront_device *pdev)
+{
+ if (--pdev->ref_cnt > 0)
+ return;
+
+ DPRINTF("freeing pdev @ 0x%p (ref_cnt=%d)\n", pdev, pdev->ref_cnt);
+
+ if (pdev->evtchn != INVALID_EVTCHN)
+ xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
+
+ if (pdev->gnt_ref != INVALID_GRANT_REF)
+ gnttab_end_foreign_access(pdev->gnt_ref, 0, (void *)pdev->sh_info);
+
+ pdev->xdev->data = NULL;
+
+ free(pdev, M_DEVBUF);
+}
+
+/* Write to the xenbus info needed by backend */
+static int
+pcifront_publish_info(struct pcifront_device *pdev)
+{
+ int err = 0;
+ struct xenbus_transaction *trans;
+
+ err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
+ if (err < 0) {
+ WPRINTF("error granting access to ring page\n");
+ goto out;
+ }
+
+ pdev->gnt_ref = err;
+
+ err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
+ if (err)
+ goto out;
+
+ do_publish:
+ trans = xenbus_transaction_start();
+ if (IS_ERR(trans)) {
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Error writing configuration for backend "
+ "(start transaction)");
+ goto out;
+ }
+
+ err = xenbus_printf(trans, pdev->xdev->nodename,
+ "pci-op-ref", "%u", pdev->gnt_ref);
+ if (!err)
+ err = xenbus_printf(trans, pdev->xdev->nodename,
+ "event-channel", "%u", pdev->evtchn);
+ if (!err)
+ err = xenbus_printf(trans, pdev->xdev->nodename,
+ "magic", XEN_PCI_MAGIC);
+ if (!err)
+ err = xenbus_switch_state(pdev->xdev, trans,
+ XenbusStateInitialised);
+
+ if (err) {
+ xenbus_transaction_end(trans, 1);
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Error writing configuration for backend");
+ goto out;
+ } else {
+ err = xenbus_transaction_end(trans, 0);
+ if (err == -EAGAIN)
+ goto do_publish;
+ else if (err) {
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Error completing transaction for backend");
+ goto out;
+ }
+ }
+
+ out:
+ return err;
+}
+
+/* The backend is now connected so complete the connection process on our side */
+static int
+pcifront_connect(struct pcifront_device *pdev)
+{
+ device_t nexus;
+ devclass_t nexus_devclass;
+
+ /* We will add our device as a child of the nexus0 device */
+ if (!(nexus_devclass = devclass_find("nexus")) ||
+ !(nexus = devclass_get_device(nexus_devclass, 0))) {
+ WPRINTF("could not find nexus0!\n");
+ return -1;
+ }
+
+ /* Create a newbus device representing this frontend instance */
+ pdev->ndev = BUS_ADD_CHILD(nexus, 0, "xpcife", pdev->unit);
+ if (!pdev->ndev) {
+ WPRINTF("could not create xpcife%d!\n", pdev->unit);
+ return -EFAULT;
+ }
+ get_pdev(pdev);
+ device_set_ivars(pdev->ndev, pdev);
+
+ /* Good to go connected now */
+ xenbus_switch_state(pdev->xdev, NULL, XenbusStateConnected);
+
+ printf("pcifront: connected to %s\n", pdev->xdev->nodename);
+
+ mtx_lock(&Giant);
+ device_probe_and_attach(pdev->ndev);
+ mtx_unlock(&Giant);
+
+ return 0;
+}
+
+/* The backend is closing so process a disconnect */
+static int
+pcifront_disconnect(struct pcifront_device *pdev)
+{
+ int err = 0;
+ XenbusState prev_state;
+
+ prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
+
+ if (prev_state < XenbusStateClosing) {
+ err = xenbus_switch_state(pdev->xdev, NULL, XenbusStateClosing);
+ if (!err && prev_state == XenbusStateConnected) {
+ /* TODO - need to detach the newbus devices */
+ }
+ }
+
+ return err;
+}
+
+/* Process a probe from the xenbus */
+static int
+pcifront_probe(struct xenbus_device *xdev,
+ const struct xenbus_device_id *id)
+{
+ int err = 0;
+ struct pcifront_device *pdev;
+
+ DPRINTF("xenbus probing\n");
+
+ if ((pdev = alloc_pdev(xdev)) == NULL)
+ goto out;
+
+ err = pcifront_publish_info(pdev);
+
+ out:
+ if (err)
+ put_pdev(pdev);
+ return err;
+}
+
+/* Remove the xenbus PCI device */
+static int
+pcifront_remove(struct xenbus_device *xdev)
+{
+ DPRINTF("removing xenbus device node (%s)\n", xdev->nodename);
+ if (xdev->data)
+ put_pdev(xdev->data);
+ return 0;
+}
+
+/* Called by xenbus when our backend node changes state */
+static void
+pcifront_backend_changed(struct xenbus_device *xdev,
+ XenbusState be_state)
+{
+ struct pcifront_device *pdev = xdev->data;
+
+ switch (be_state) {
+ case XenbusStateClosing:
+ DPRINTF("backend closing (%s)\n", xdev->nodename);
+ pcifront_disconnect(pdev);
+ break;
+
+ case XenbusStateClosed:
+ DPRINTF("backend closed (%s)\n", xdev->nodename);
+ pcifront_disconnect(pdev);
+ break;
+
+ case XenbusStateConnected:
+ DPRINTF("backend connected (%s)\n", xdev->nodename);
+ pcifront_connect(pdev);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Process PCI operation */
+static int
+do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
+{
+ int err = 0;
+ struct xen_pci_op *active_op = &pdev->sh_info->op;
+ evtchn_port_t port = pdev->evtchn;
+ time_t timeout;
+
+ mtx_lock(&pdev->sh_info_lock);
+
+ memcpy(active_op, op, sizeof(struct xen_pci_op));
+
+ /* Go */
+ wmb();
+ set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
+ notify_remote_via_evtchn(port);
+
+ timeout = time_uptime + 2;
+
+ clear_evtchn(port);
+
+ /* Spin while waiting for the answer */
+ while (test_bit
+ (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
+ int err = HYPERVISOR_poll(&port, 1, 3 * hz);
+ if (err)
+ panic("Failed HYPERVISOR_poll: err=%d", err);
+ clear_evtchn(port);
+ if (time_uptime > timeout) {
+ WPRINTF("pciback not responding!!!\n");
+ clear_bit(_XEN_PCIF_active,
+ (unsigned long *)&pdev->sh_info->flags);
+ err = XEN_PCI_ERR_dev_not_found;
+ goto out;
+ }
+ }
+
+ memcpy(op, active_op, sizeof(struct xen_pci_op));
+
+ err = op->err;
+ out:
+ mtx_unlock(&pdev->sh_info_lock);
+ return err;
+}
+
+/* ** XenBus Driver registration ** */
+
+static struct xenbus_device_id pcifront_ids[] = {
+ { "pci" },
+ { "" }
+};
+
+static struct xenbus_driver pcifront = {
+ .name = "pcifront",
+ .ids = pcifront_ids,
+ .probe = pcifront_probe,
+ .remove = pcifront_remove,
+ .otherend_changed = pcifront_backend_changed,
+};
+
+/* Register the driver with xenbus during sys init */
+static void
+pcifront_init(void *unused)
+{
+ if ((xen_start_info->flags & SIF_INITDOMAIN))
+ return;
+
+ DPRINTF("xenbus registering\n");
+
+ xenbus_register_frontend(&pcifront);
+}
+
+SYSINIT(pciif, SI_SUB_PSEUDO, SI_ORDER_ANY, pcifront_init, NULL)
+
+/* Newbus xpcife device driver probe */
+static int
+xpcife_probe(device_t dev)
+{
+#ifdef XEN_PCIDEV_FE_DEBUG
+ struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
+ DPRINTF("xpcife probe (unit=%d)\n", pdev->unit);
+#endif
+ return (BUS_PROBE_NOWILDCARD);
+}
+
+/* Newbus xpcife device driver attach */
+static int
+xpcife_attach(device_t dev)
+{
+ struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
+ int i, num_roots, len, err;
+ char str[64];
+ unsigned int domain, bus;
+
+ DPRINTF("xpcife attach (unit=%d)\n", pdev->unit);
+
+ err = xenbus_scanf(NULL, pdev->xdev->otherend,
+ "root_num", "%d", &num_roots);
+ if (err != 1) {
+ if (err == 0)
+ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Error reading number of PCI roots");
+ goto out;
+ }
+
+ /* Add a pcib device for each root */
+ for (i = 0; i < num_roots; i++) {
+ device_t child;
+
+ len = snprintf(str, sizeof(str), "root-%d", i);
+ if (unlikely(len >= (sizeof(str) - 1))) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = xenbus_scanf(NULL, pdev->xdev->otherend, str,
+ "%x:%x", &domain, &bus);
+ if (err != 2) {
+ if (err >= 0)
+ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Error reading PCI root %d", i);
+ goto out;
+ }
+ err = 0;
+ if (domain != pdev->xdev->otherend_id) {
+ err = -EINVAL;
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Domain mismatch %d != %d", domain, pdev->xdev->otherend_id);
+ goto out;
+ }
+
+ child = device_add_child(dev, "pcib", bus);
+ if (!child) {
+ err = -ENOMEM;
+ xenbus_dev_fatal(pdev->xdev, err,
+ "Unable to create pcib%d", bus);
+ goto out;
+ }
+ }
+
+ out:
+ bus_attach_children(dev);
+ return (0);
+}
+
+static devclass_t xpcife_devclass;
+
+static device_method_t xpcife_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xpcife_probe),
+ DEVMETHOD(device_attach, xpcife_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ /* Bus interface */
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ DEVMETHOD_END
+};
+
+static driver_t xpcife_driver = {
+ "xpcife",
+ xpcife_methods,
+ 0,
+};
+
+DRIVER_MODULE(xpcife, nexus, xpcife_driver, xpcife_devclass, 0, 0);
+
+/* Newbus xen pcib device driver probe */
+static int
+xpcib_probe(device_t dev)
+{
+ struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
+ struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(device_get_parent(dev));
+
+ DPRINTF("xpcib probe (bus=%d)\n", device_get_unit(dev));
+
+ sc->domain = pdev->xdev->otherend_id;
+ sc->bus = device_get_unit(dev);
+ sc->pdev = pdev;
+
+ return 0;
+}
+
+/* Newbus xen pcib device driver attach */
+static int
+xpcib_attach(device_t dev)
+{
+ struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
+
+ DPRINTF("xpcib attach (bus=%d)\n", sc->bus);
+
+ device_add_child(dev, "pci", DEVICE_UNIT_ANY);
+ bus_attach_children(dev);
+ return (0);
+}
+
+static int
+xpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = sc->bus;
+ return 0;
+ }
+ return ENOENT;
+}
+
+/* Return the number of slots supported */
+static int
+xpcib_maxslots(device_t dev)
+{
+ return 31;
+}
+
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+
+/* Read configuration space register */
+static u_int32_t
+xpcib_read_config(device_t dev, int bus, int slot, int func,
+ int reg, int bytes)
+{
+ struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
+ struct xen_pci_op op = {
+ .cmd = XEN_PCI_OP_conf_read,
+ .domain = sc->domain,
+ .bus = sc->bus,
+ .devfn = PCI_DEVFN(slot, func),
+ .offset = reg,
+ .size = bytes,
+ };
+ int err;
+
+ err = do_pci_op(sc->pdev, &op);
+
+ DPRINTF("read config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
+ bus, slot, func, reg, bytes, op.value, err);
+
+ if (err)
+ op.value = ~0;
+
+ return op.value;
+}
+
+/* Write configuration space register */
+static void
+xpcib_write_config(device_t dev, int bus, int slot, int func,
+ int reg, u_int32_t data, int bytes)
+{
+ struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
+ struct xen_pci_op op = {
+ .cmd = XEN_PCI_OP_conf_write,
+ .domain = sc->domain,
+ .bus = sc->bus,
+ .devfn = PCI_DEVFN(slot, func),
+ .offset = reg,
+ .size = bytes,
+ .value = data,
+ };
+ int err;
+
+ err = do_pci_op(sc->pdev, &op);
+
+ DPRINTF("write config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
+ bus, slot, func, reg, bytes, data, err);
+}
+
+static int
+xpcib_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(dev);
+ pcicfgregs *cfg = &dinfo->cfg;
+
+ DPRINTF("route intr (pin=%d, line=%d)\n", pin, cfg->intline);
+
+ return cfg->intline;
+}
+
+static device_method_t xpcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xpcib_probe),
+ DEVMETHOD(device_attach, xpcib_attach),
+ DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, xpcib_read_ivar),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, xpcib_maxslots),
+ DEVMETHOD(pcib_read_config, xpcib_read_config),
+ DEVMETHOD(pcib_write_config, xpcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, xpcib_route_interrupt),
+ DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
+
+ DEVMETHOD_END
+};
+
+static devclass_t xpcib_devclass;
+
+DEFINE_CLASS_0(pcib, xpcib_driver, xpcib_methods, sizeof(struct xpcib_softc));
+DRIVER_MODULE(pcib, xpcife, xpcib_driver, xpcib_devclass, 0, 0);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/sys/dev/xen/privcmd/privcmd.c b/sys/dev/xen/privcmd/privcmd.c
index 02e268b23d42..922d24b39432 100644
--- a/sys/dev/xen/privcmd/privcmd.c
+++ b/sys/dev/xen/privcmd/privcmd.c
@@ -120,25 +120,13 @@ privcmd_pg_dtor(void *handle)
struct privcmd_map *map = handle;
int error __diagused;
vm_size_t i;
- vm_page_t m;
/*
* Remove the mappings from the used pages. This will remove the
* underlying p2m bindings in Xen second stage translation.
*/
if (map->mapped == true) {
- VM_OBJECT_WLOCK(map->mem);
-retry:
- for (i = 0; i < map->size; i++) {
- m = vm_page_lookup(map->mem, i);
- if (m == NULL)
- continue;
- if (vm_page_busy_acquire(m, VM_ALLOC_WAITFAIL) == 0)
- goto retry;
- cdev_pager_free_page(map->mem, m);
- }
- VM_OBJECT_WUNLOCK(map->mem);
-
+ cdev_mgtdev_pager_free_pages(map->mem);
for (i = 0; i < map->size; i++) {
rm.gpfn = atop(map->phys_base_addr) + i;
HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &rm);
diff --git a/sys/dev/xen/xenpci/xenpci.c b/sys/dev/xen/xenpci/xenpci.c
index b7a810bf9e15..f4cbd927bd63 100644
--- a/sys/dev/xen/xenpci/xenpci.c
+++ b/sys/dev/xen/xenpci/xenpci.c
@@ -31,13 +31,12 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/stdarg.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
-#include <machine/stdarg.h>
-
#include <xen/xen-os.h>
#include <xen/features.h>
#include <xen/hypervisor.h>
@@ -127,8 +126,9 @@ errexit:
static int
xenpci_probe(device_t dev)
{
+ uint32_t device_id = pci_get_devid(dev);
- if (pci_get_devid(dev) != 0x00015853)
+ if (device_id != 0x00015853 && device_id != 0x00025853)
return (ENXIO);
device_set_desc(dev, "Xen Platform Device");
diff --git a/sys/dev/xen/xenstore/xenstore.c b/sys/dev/xen/xenstore/xenstore.c
index 811aa1859d41..e5187466f1fe 100644
--- a/sys/dev/xen/xenstore/xenstore.c
+++ b/sys/dev/xen/xenstore/xenstore.c
@@ -45,10 +45,9 @@
#include <sys/uio.h>
#include <sys/unistd.h>
#include <sys/queue.h>
+#include <sys/stdarg.h>
#include <sys/taskqueue.h>
-#include <machine/stdarg.h>
-
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/xen_intr.h>
@@ -1068,8 +1067,8 @@ static void
xs_attach_deferred(void *arg)
{
- bus_generic_probe(xs.xs_dev);
- bus_generic_attach(xs.xs_dev);
+ bus_identify_children(xs.xs_dev);
+ bus_attach_children(xs.xs_dev);
config_intrhook_disestablish(&xs.xs_attachcb);
}
@@ -1079,8 +1078,8 @@ xs_attach_late(void *arg, int pending)
{
KASSERT((pending == 1), ("xs late attach queued several times"));
- bus_generic_probe(xs.xs_dev);
- bus_generic_attach(xs.xs_dev);
+ bus_identify_children(xs.xs_dev);
+ bus_attach_children(xs.xs_dev);
}
/**