changeset 10880:76b7c881fd34

Branch merge
author tide@localhost
date Mon, 21 Sep 2009 11:26:40 -0400
parents 790152ecf13b (current diff) 8513e8d83d7c (diff)
children 70f7defc280d
files usr/src/cmd/ssh/include/daemon.h usr/src/cmd/ssh/libopenbsd-compat/common/daemon.c usr/src/uts/common/io/tpm/tpm.c usr/src/uts/common/syscall/uadmin.c usr/src/uts/intel/amd_iommu/Makefile usr/src/uts/intel/io/amd_iommu/amd_iommu.c usr/src/uts/intel/io/amd_iommu/amd_iommu.conf usr/src/uts/intel/io/amd_iommu/amd_iommu_acpi.c usr/src/uts/intel/io/amd_iommu/amd_iommu_acpi.h usr/src/uts/intel/io/amd_iommu/amd_iommu_cmd.c usr/src/uts/intel/io/amd_iommu/amd_iommu_impl.c usr/src/uts/intel/io/amd_iommu/amd_iommu_impl.h usr/src/uts/intel/io/amd_iommu/amd_iommu_log.c usr/src/uts/intel/io/amd_iommu/amd_iommu_log.h usr/src/uts/intel/io/amd_iommu/amd_iommu_page_tables.c usr/src/uts/intel/io/amd_iommu/amd_iommu_page_tables.h usr/src/uts/intel/sys/amd_iommu.h
diffstat 179 files changed, 12587 insertions(+), 9473 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/auditd/auditd.xml	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/auditd/auditd.xml	Mon Sep 21 11:26:40 2009 -0400
@@ -1,15 +1,14 @@
 <?xml version="1.0"?>
 <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
 <!--
- Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  Use is subject to license terms.
 
  CDDL HEADER START
 
  The contents of this file are subject to the terms of the
- Common Development and Distribution License, Version 1.0 only
- (the "License").  You may not use this file except in compliance
- with the License.
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
 
  You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  or http://www.opensolaris.org/os/licensing.
@@ -24,8 +23,6 @@
 
  CDDL HEADER END
 
-    ident	"%Z%%M%	%I%	%E% SMI"
-
     NOTE:  This service manifest is not editable; its contents will
     be overwritten by package or patch operations, including
     operating system upgrade.  Make customizations in a different
@@ -60,7 +57,7 @@
 	<dependency
 		name='syslog'
 		type='service'
-		grouping='require_all'
+		grouping='optional_all'
 		restart_on='none'>
 		<service_fmri value='svc:/system/system-log' />
 	</dependency>
--- a/usr/src/cmd/autopush/autopush.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/autopush/autopush.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,8 +27,6 @@
 /*	  All Rights Reserved  	*/
 
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * autopush(1) is the command interface to the STREAMS autopush
  * mechanism.  The autopush command can be used to configure autopush
@@ -74,6 +71,7 @@
 #include <string.h>
 #include <locale.h>
 #include <sys/stat.h>
+#include <zone.h>
 
 #define	OPTIONS	"M:f:gm:r"	/* command line options for getopt(3C) */
 #define	COMMENT	'#'
@@ -207,6 +205,13 @@
 		usage();
 		exit(1);
 	}
+
+	if (getzoneid() != GLOBAL_ZONEID) {
+		(void) fprintf(stderr, gettext("autopush "
+		    "can only be run from the global zone.\n"));
+		exit(1);
+	}
+
 	if (fflag)
 		exitcode = set_info(filenamep);
 	else if (rflag)
--- a/usr/src/cmd/boot/filelist/i386/filelist.ramdisk	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk	Mon Sep 21 11:26:40 2009 -0400
@@ -7,6 +7,7 @@
 etc/devices/mdi_ib_cache
 etc/devices/mdi_scsi_vhci_cache
 etc/devices/retire_store
+etc/devices/pci_unitaddr_persistent
 etc/driver_aliases
 etc/driver_classes
 etc/mach
--- a/usr/src/cmd/boot/installgrub/installgrub.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/boot/installgrub/installgrub.c	Mon Sep 21 11:26:40 2009 -0400
@@ -228,11 +228,13 @@
 get_start_sector(int fd)
 {
 	static unsigned int start_sect = 0;
-	uint32_t secnum, numsec;
-	int i, pno, rval, ext_sol_part_found = 0;
+	uint32_t secnum = 0, numsec = 0;
+	int i, pno, rval, log_part = 0;
 	struct mboot *mboot;
 	struct ipart *part;
 	ext_part_t *epp;
+	struct part_info dkpi;
+	struct extpart_info edkpi;
 
 	if (start_sect)
 		return (start_sect);
@@ -241,24 +243,84 @@
 	for (i = 0; i < FD_NUMPART; i++) {
 		part = (struct ipart *)mboot->parts + i;
 		if (is_bootpar) {
-			if (part->systid == 0xbe)
-				break;
+			if (part->systid == 0xbe) {
+				start_sect = part->relsect;
+				partition = i;
+				goto found_part;
+			}
+		}
+	}
+
+	/*
+	 * We will not support x86 boot partition on extended partitions
+	 */
+	if (is_bootpar) {
+		(void) fprintf(stderr, NOBOOTPAR);
+		exit(-1);
+	}
+
+	/*
+	 * Not an x86 boot partition. Search for Solaris fdisk partition
+	 * Get the solaris partition information from the device
+	 * and compare the offset of S2 with offset of solaris partition
+	 * from fdisk partition table.
+	 */
+	if (ioctl(fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
+		if (ioctl(fd, DKIOCPARTINFO, &dkpi) < 0) {
+			(void) fprintf(stderr, PART_FAIL);
+			exit(-1);
+		} else {
+			edkpi.p_start = dkpi.p_start;
 		}
 	}
 
-	/* Read extended partition to find a solaris partition */
+	for (i = 0; i < FD_NUMPART; i++) {
+		part = (struct ipart *)mboot->parts + i;
+
+		if (part->relsect == 0) {
+			(void) fprintf(stderr, BAD_PART, i);
+			exit(-1);
+		}
+
+		if (edkpi.p_start >= part->relsect &&
+		    edkpi.p_start < (part->relsect + part->numsect)) {
+			/* Found the partition */
+			break;
+		}
+	}
+
+	if (i == FD_NUMPART) {
+		/* No solaris fdisk partitions (primary or logical) */
+		(void) fprintf(stderr, NOSOLPAR);
+		exit(-1);
+	}
+
+	/*
+	 * We have found a Solaris fdisk partition (primary or extended)
+	 * Handle the simple case first: Solaris in a primary partition
+	 */
+	if (!fdisk_is_dos_extended(part->systid)) {
+		start_sect = part->relsect;
+		partition = i;
+		goto found_part;
+	}
+
+	/*
+	 * Solaris in a logical partition. Find that partition in the
+	 * extended part.
+	 */
 	if ((rval = libfdisk_init(&epp, device_p0, NULL, FDISK_READ_DISK))
 	    != FDISK_SUCCESS) {
 		switch (rval) {
 			/*
-			 * FDISK_EBADLOGDRIVE and FDISK_ENOLOGDRIVE can
-			 * be considered as soft errors and hence
-			 * we do not exit
+			 * The first 2 cases are not an error per-se, just that
+			 * there is no Solaris logical partition
 			 */
 			case FDISK_EBADLOGDRIVE:
-				break;
 			case FDISK_ENOLOGDRIVE:
-				break;
+				(void) fprintf(stderr, NOSOLPAR);
+				exit(-1);
+				/*NOTREACHED*/
 			case FDISK_ENOVGEOM:
 				(void) fprintf(stderr, NO_VIRT_GEOM);
 				exit(1);
@@ -279,54 +341,18 @@
 	}
 
 	rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec);
-	if (rval == FDISK_SUCCESS) {
-		ext_sol_part_found = 1;
+	if (rval != FDISK_SUCCESS) {
+		/* No solaris logical partition */
+		(void) fprintf(stderr, NOSOLPAR);
+		exit(-1);
 	}
 	libfdisk_fini(&epp);
 
-	/*
-	 * If there is no boot partition, find the solaris partition
-	 */
-
-	if (i == FD_NUMPART) {
-		struct part_info dkpi;
-		struct extpart_info edkpi;
-
-		/*
-		 * Get the solaris partition information from the device
-		 * and compare the offset of S2 with offset of solaris partition
-		 * from fdisk partition table.
-		 */
-		if (ioctl(fd, DKIOCEXTPARTINFO, &edkpi) < 0) {
-			if (ioctl(fd, DKIOCPARTINFO, &dkpi) < 0) {
-				(void) fprintf(stderr, PART_FAIL);
-				exit(-1);
-			} else {
-				edkpi.p_start = dkpi.p_start;
-			}
-		}
+	start_sect = secnum;
+	partition = pno - 1;
+	log_part = 1;
 
-		for (i = 0; i < FD_NUMPART; i++) {
-			part = (struct ipart *)mboot->parts + i;
-
-			if (part->relsect == 0) {
-				(void) fprintf(stderr, BAD_PART, i);
-				exit(-1);
-			}
-
-			if (edkpi.p_start >= part->relsect &&
-			    edkpi.p_start < (part->relsect + part->numsect)) {
-				/* Found the partition */
-				break;
-			}
-		}
-	}
-
-	if ((i == FD_NUMPART) && (!ext_sol_part_found)) {
-		(void) fprintf(stderr, BOOTPAR);
-		exit(-1);
-	}
-
+found_part:
 	/* get confirmation for -m */
 	if (write_mboot && !force_mboot) {
 		(void) fprintf(stdout, MBOOT_PROMPT);
@@ -336,16 +362,21 @@
 		}
 	}
 
-	if (fdisk_is_dos_extended(part->systid)) {
-		start_sect = secnum;
-		partition = pno;
-	} else {
-		start_sect = part->relsect;
-		partition = i;
+	/*
+	 * Currently if Solaris is in an extended partition we need to
+	 * write GRUB to the MBR. Check for this.
+	 */
+	if (log_part && !write_mboot) {
+		(void) fprintf(stderr, EXTSOLPAR);
+		exit(-1);
 	}
 
-	if (part->bootid != 128 && write_mboot == 0) {
-		(void) fprintf(stdout, BOOTPAR_INACTIVE, i + 1);
+	/*
+	 * warn, if Solaris in primary partition and GRUB not in MBR and
+	 * partition is not active
+	 */
+	if (!log_part && part->bootid != 128 && !write_mboot) {
+		(void) fprintf(stdout, SOLPAR_INACTIVE, partition + 1);
 	}
 
 	return (start_sect);
--- a/usr/src/cmd/boot/installgrub/message.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/boot/installgrub/message.h	Mon Sep 21 11:26:40 2009 -0400
@@ -34,13 +34,20 @@
 
 #define	DRY_RUN	gettext("dry run--nothing will be written to disk\n")
 
-#define	BOOTPAR	gettext("Solaris partition not found. Abort operation.\n")
+#define	NOSOLPAR	\
+	gettext("Solaris partition not found. Aborting operation.\n")
 
-#define	BOOTPAR_INACTIVE	gettext("Solaris boot partition inactive.\n")
+#define	NOBOOTPAR	\
+	gettext("Solaris x86 boot partition not found. Aborting operation.\n")
+
+#define	SOLPAR_INACTIVE	gettext("Solaris fdisk partition is inactive.\n")
 
 #define	BOOTPAR_NOTFOUND	\
     gettext("Solaris boot partition not found on %s\n")
 
+#define	EXTSOLPAR	\
+	gettext("Solaris in extended partition. -m (MBR) option required\n")
+
 #define	NOT_RAW_DEVICE	gettext("device %s is not a char special device\n")
 
 #define	NOT_ROOT_SLICE	gettext("raw device must be a root slice (not s2)\n")
@@ -112,6 +119,8 @@
 
 #define	LIBFDISK_INIT_FAIL	gettext("Failed to initialize libfdisk.\n")
 
+
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/cmd/cmd-inet/usr.lib/wpad/wpa_supplicant.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/cmd-inet/usr.lib/wpad/wpa_supplicant.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -762,34 +762,6 @@
 	free(config);
 }
 
-static int
-daemon(boolean_t nochdir, boolean_t noclose)
-{
-	int retv;
-
-	if ((retv = fork()) == -1)
-		return (-1);
-	if (retv != 0)
-		_exit(EXIT_SUCCESS);
-	if (setsid() == -1)
-		return (-1);
-
-	if (!nochdir && chdir("/") == -1)
-		return (-1);
-
-	if (!noclose) {
-		(void) close(0);
-		(void) close(1);
-		(void) close(2);
-		if ((retv = open("/dev/null", O_RDWR)) != -1) {
-			(void) dup2(retv, 1);
-			(void) dup2(retv, 2);
-		}
-	}
-
-	return (0);
-}
-
 /*
  * make sure wpad is running under SMF context.
  */
--- a/usr/src/cmd/cmd-inet/usr.sbin/in.routed/main.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/main.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Copyright (c) 1983, 1988, 1993
@@ -38,8 +38,6 @@
  * " The Regents of the University of California.  All rights reserved.\n";
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include "defs.h"
 #include "pathnames.h"
 #include <signal.h>
@@ -104,35 +102,6 @@
 static void	sigalrm(int);
 static void	sigterm(int);
 
-static int
-daemon(boolean_t nochdir, boolean_t noclose)
-{
-	int retv;
-
-	if ((retv = fork()) == -1)
-		return (-1);
-	if (retv != 0)
-		_exit(EXIT_SUCCESS);
-	if (setsid() == -1)
-		return (-1);
-	if ((retv = fork()) == -1)
-		return (-1);
-	if (retv != 0)
-		_exit(EXIT_SUCCESS);
-	if (!nochdir && chdir("/") == -1)
-		return (-1);
-	if (!noclose) {
-		(void) close(0);
-		(void) close(1);
-		(void) close(2);
-		if ((retv = open("/dev/null", O_RDWR)) != -1) {
-			(void) dup2(retv, 1);
-			(void) dup2(retv, 2);
-		}
-	}
-	return (0);
-}
-
 int
 main(int argc, char *argv[])
 {
@@ -310,9 +279,9 @@
 		goto usage;
 	if (argc != 0) {
 usage:
-		(void) fprintf(stderr,
-		    gettext("usage: in.routed [-AdghmnqsStVvz] "
-			"[-T <tracefile>]\n"));
+		(void) fprintf(stderr, gettext(
+		    "usage: in.routed [-AdghmnqsStVvz] "
+		    "[-T <tracefile>]\n"));
 		(void) fprintf(stderr,
 		    gettext("\t[-F <net>[/<mask>][,<metric>]] [-P <parms>]\n"));
 		logbad(_B_FALSE, gettext("excess arguments"));
@@ -358,7 +327,7 @@
 		msglog("signal: %s", rip_strerror(sigerr));
 
 	/* get into the background */
-	if (background && daemon(_B_FALSE, _B_FALSE) < 0)
+	if (background && daemon(0, 0) < 0)
 		BADERR(_B_FALSE, "daemon()");
 
 	/* Store our process id, blow away any existing file if it exists. */
--- a/usr/src/cmd/devfsadm/audio_link.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/devfsadm/audio_link.c	Mon Sep 21 11:26:40 2009 -0400
@@ -68,33 +68,32 @@
 	 */
 
 	/* /dev/audio, /dev/audioctl, /dev/dsp */
-	{ "audio", "^(audio|audioctl|dsp)$",
-	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_link
+	{ "audio", "^audio$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
 	},
-	/* /dev/mixer0, /dev/dsp0 */
-	{ "audio", "^(mixer|dsp)[0-9]+$",
-	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_link
-	},
-	/* /dev/sound/0, 0ctl */
-	{ "audio", "^sound/[0-9]+(ctl)?$",
-	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_link
+	{ "audio", "^audioctl$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
 	},
-	/* /dev/mixer */
-	{ "pseudo", "^(mixer)$",
-	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_link
+	{ "audio", "^dsp$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
 	},
-
-	/*
-	 * Primary links.
-	 */
-
-	/* /dev/sndstat */
-	{ "pseudo", "^sndstat$",
+	{ "audio", "^mixer",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
+	},
+	{ "audio", "^sndstat$",
 	    RM_PRE|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
 	},
-	/* /dev/sound/audio810:0, 0ctl, etc */
-	{ "audio", "^sound/.*:[0-9]+(ctl|dsp|mixer)?$",
-	    RM_PRE|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
+	{ "audio", "^mixer[0-9]+$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
+	},
+	{ "audio", "^dsp[0-9]+$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
+	},
+	{ "audio", "^sound/[0-9]+$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
+	},
+	{ "audio", "^sound/[0-9]+ctl$",
+	    RM_POST|RM_HOT|RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
 	},
 };
 
--- a/usr/src/cmd/devfsadm/devfsadm.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/devfsadm/devfsadm.c	Mon Sep 21 11:26:40 2009 -0400
@@ -42,6 +42,7 @@
 #include <utime.h>
 #include <sys/param.h>
 #include <bsm/libbsm.h>
+#include <zone.h>
 #include "devfsadm_impl.h"
 
 /* externs from devalloc.c */
@@ -267,6 +268,11 @@
 		/*NOTREACHED*/
 	}
 
+	if (getzoneid() != GLOBAL_ZONEID) {
+		err_print(MUST_BE_GLOBAL_ZONE);
+		devfsadm_exit(1);
+	}
+
 	/*
 	 * Close all files except stdin/stdout/stderr
 	 */
--- a/usr/src/cmd/devfsadm/message.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/devfsadm/message.h	Mon Sep 21 11:26:40 2009 -0400
@@ -255,6 +255,9 @@
 #define	ZONE_PATHCHECK \
     gettext("cannot manage root path '%s': path is part of zone '%s'\n")
 
+#define	MUST_BE_GLOBAL_ZONE \
+    gettext("can only be run from the global zone\n")
+
 #define	DEVNAME_CONTACT_FAILED \
     gettext("cannot talk to devname fs %s: %s\n")
 
--- a/usr/src/cmd/fm/fmd/common/fmd_xprt.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/fm/fmd/common/fmd_xprt.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1173,6 +1173,7 @@
 	uint8_t *proxy_asru = NULL;
 	int got_proxy_asru = 0;
 	int got_hc_rsrc = 0;
+	int got_hc_asru = 0;
 	int got_present_rsrc = 0;
 	uint8_t *diag_asru = NULL;
 	char *scheme;
@@ -1230,7 +1231,7 @@
 			    nvlist_lookup_string(asru, FM_FMRI_SCHEME,
 			    &scheme) == 0 &&
 			    strcmp(scheme, FM_FMRI_SCHEME_HC) == 0) {
-				got_hc_rsrc = 1;
+				got_hc_asru = 1;
 				if (xip->xi_flags & FMD_XPRT_EXTERNAL)
 					continue;
 				if (topo_fmri_present(thp, asru, &err) != 0)
@@ -1266,7 +1267,8 @@
 	 * If we're set up only to report hc-scheme faults, and
 	 * there aren't any, then just drop the event.
 	 */
-	if (got_hc_rsrc == 0 && (xip->xi_flags & FMD_XPRT_HCONLY)) {
+	if (got_hc_rsrc == 0 && got_hc_asru == 0 &&
+	    (xip->xi_flags & FMD_XPRT_HCONLY)) {
 		if (nelem > 0) {
 			fmd_free(proxy_asru, sizeof (uint8_t) * nelem);
 			fmd_free(diag_asru, sizeof (uint8_t) * nelem);
@@ -1333,10 +1335,13 @@
 			(void) nvlist_add_nvlist(flt_copy, FM_FAULT_ASRU,
 			    asrua[i]);
 			nvlist_free(asrua[i]);
-		} else if (nvlist_lookup_nvlist(flt_copy, FM_FAULT_ASRU,
+		} else if (got_hc_asru == 0 &&
+		    nvlist_lookup_nvlist(flt_copy, FM_FAULT_ASRU,
 		    &asru) == 0 && asru != NULL) {
 			/*
-			 * keep asru from diag side, but but mark as no retire
+			 * If we have an asru from diag side, but it's not
+			 * in hc scheme, then we can't be sure what it
+			 * represents, so mark as no retire.
 			 */
 			(void) nvlist_add_boolean_value(flt_copy,
 			    FM_SUSPECT_RETIRE, B_FALSE);
--- a/usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/fm/modules/common/zfs-diagnosis/zfs_de.c	Mon Sep 21 11:26:40 2009 -0400
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <assert.h>
 #include <stddef.h>
 #include <strings.h>
@@ -710,12 +708,11 @@
 };
 
 static const fmd_prop_t fmd_props[] = {
-	{ "case_timeout", FMD_TYPE_TIME, "5sec" },
 	{ "checksum_N", FMD_TYPE_UINT32, "10" },
 	{ "checksum_T", FMD_TYPE_TIME, "10min" },
 	{ "io_N", FMD_TYPE_UINT32, "10" },
 	{ "io_T", FMD_TYPE_TIME, "10min" },
-	{ "remove_timeout", FMD_TYPE_TIME, "5sec" },
+	{ "remove_timeout", FMD_TYPE_TIME, "15sec" },
 	{ NULL, 0, NULL }
 };
 
--- a/usr/src/cmd/fm/modules/sun4v/cpumem-diagnosis/cmd_memerr_arch.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/fm/modules/sun4v/cpumem-diagnosis/cmd_memerr_arch.c	Mon Sep 21 11:26:40 2009 -0400
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -292,8 +292,9 @@
 cmd_ce(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
     cmd_errcl_t clcode)
 {
-	if (strcmp(class, "ereport.cpu.ultraSPARC-T2plus.dsc") == 0)
-		return (CMD_EVD_UNUSED); /* drop VF dsc's */
+	if ((strcmp(class, "ereport.cpu.ultraSPARC-T2plus.dsc") == 0) ||
+	    (strcmp(class, "ereport.cpu.ultraSPARC-T2.dsc") == 0))
+		return (CMD_EVD_UNUSED); /* drop T2/T2+ dsc's */
 	else
 		return (xe_common(hdl, ep, nvl, class, clcode, cmd_ce_common));
 }
--- a/usr/src/cmd/halt/halt.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/halt/halt.c	Mon Sep 21 11:26:40 2009 -0400
@@ -381,6 +381,42 @@
 		(void) sigsend(P_CTID, next->ctid, SIGCONT);
 }
 
+#define	FMRI_GDM "svc:/application/graphical-login/gdm:default"
+
+/*
+ * If gdm is running, try to stop gdm.
+ * Returns  0 on success, -1 on failure.
+ */
+static int
+stop_gdm()
+{
+	char *gdm_state = NULL;
+	int retry = 0;
+
+	/*
+	 * If gdm is running, try to stop gdm.
+	 */
+	while ((gdm_state = smf_get_state(FMRI_GDM)) != NULL &&
+	    strcmp(gdm_state, SCF_STATE_STRING_ONLINE) == 0 && retry++ < 5) {
+		if (smf_disable_instance(FMRI_GDM, SMF_TEMPORARY) != 0) {
+			(void) fprintf(stderr,
+			    gettext("%s: Failed to stop %s: %s.\n"),
+			    cmdname, FMRI_GDM, scf_strerror(scf_error()));
+			return (-1);
+		}
+		(void) sleep(1);
+	}
+
+	if (retry >= 5) {
+		(void) fprintf(stderr, gettext("%s: Failed to stop %s.\n"),
+		    cmdname, FMRI_GDM);
+		return (-1);
+	}
+
+	return (0);
+}
+
+
 static void
 stop_restarters()
 {
@@ -1482,7 +1518,29 @@
 			(void) fprintf(stderr,
 			    gettext("%s: could not create %s.\n"),
 			    cmdname, resetting);
+	}
 
+	/*
+	 * Make sure we don't get stopped by a jobcontrol shell
+	 * once we start killing everybody.
+	 */
+	(void) signal(SIGTSTP, SIG_IGN);
+	(void) signal(SIGTTIN, SIG_IGN);
+	(void) signal(SIGTTOU, SIG_IGN);
+	(void) signal(SIGPIPE, SIG_IGN);
+	(void) signal(SIGTERM, SIG_IGN);
+
+	/*
+	 * Try to stop gdm so X has a chance to return the screen and
+	 * keyboard to a sane state.
+	 */
+	if (fast_reboot && stop_gdm() != 0) {
+		(void) fprintf(stderr,
+		    gettext("%s: Falling back to regular reboot.\n"), cmdname);
+		fast_reboot = 0;
+	}
+
+	if (cmd != A_DUMP) {
 		/*
 		 * Stop all restarters so they do not try to restart services
 		 * that are terminated.
@@ -1502,16 +1560,6 @@
 	}
 
 	/*
-	 * Make sure we don't get stopped by a jobcontrol shell
-	 * once we start killing everybody.
-	 */
-	(void) signal(SIGTSTP, SIG_IGN);
-	(void) signal(SIGTTIN, SIG_IGN);
-	(void) signal(SIGTTOU, SIG_IGN);
-	(void) signal(SIGPIPE, SIG_IGN);
-	(void) signal(SIGTERM, SIG_IGN);
-
-	/*
 	 * If we're not forcing a crash dump, give everyone 5 seconds to
 	 * handle a SIGTERM and clean up properly.
 	 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/common/modules/rootnex/intel_iommu.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,883 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ * All rights reserved.
+ */
+#include <sys/mdb_modapi.h>
+#include <sys/list.h>
+#include <sys/note.h>
+#include <sys/dditypes.h>
+#include <sys/ddi_impldefs.h>
+#include <sys/intel_iommu.h>
+#include <sys/iommulib.h>
+#include <stddef.h>
+
+/*
+ * Does Intel IOMMU works on this system?
+ */
+static boolean_t iommu_support = B_FALSE;
+
+static void
+iomuvtop_help(void)
+{
+	mdb_printf("print physical mapping of IO virtual address\n\n"
+	    "Usage:\n\n"
+	    "  address::iomuvtop <iova>\n\n"
+	    "Where, \"address\" is the address of the devinfo node, "
+	    "while \"iova\" is the DMA virtual address.\n");
+}
+
+static boolean_t
+iommu_supported(void)
+{
+	if (iommu_support == B_FALSE)
+		mdb_printf("No Intel IOMMU active on this system\n");
+	return (iommu_support);
+}
+
+/*
+ * print_device_scope_cb()
+ *   call back for print_device_scope()
+ */
+static int
+print_device_scope_cb(uintptr_t addr, pci_dev_scope_t *devs, void *cbdata)
+{
+	_NOTE(ARGUNUSED(addr))
+
+	mdb_printf((char *)cbdata);
+	mdb_printf("BDF[%x:%x:%x],type[%x]\n",
+	    devs->pds_bus,
+	    devs->pds_dev,
+	    devs->pds_func,
+	    devs->pds_type);
+
+	return (WALK_NEXT);
+}
+
+/*
+ * print_device_scope()
+ *   a common function to print device scope of a drhd or rmrr
+ */
+static void
+print_device_scope(const char *pre, uintptr_t addr)
+{
+	mdb_pwalk("list",
+	    (mdb_walk_cb_t)print_device_scope_cb, (void *)pre, addr);
+}
+
+/*
+ * parse_hw_capa()
+ * parse_hw_excapa()
+ *
+ *  Given the capability and extension capability register contents,
+ *  parse and print supported features in <output>
+ *
+ *  Please refer to chapter 10.4.2/3 in "Intel virutalization technology
+ *  for direct IO specification" for register details
+ */
+static void
+parse_hw_capa(uint64_t capa)
+{
+	char string[128];
+	size_t len;
+
+	strcpy(string, "  Hardware Capability:\t\t");
+	if (IOMMU_CAP_GET_DRD(capa))
+		strcat(string, "DRD ");
+	if (IOMMU_CAP_GET_DWD(capa))
+		strcat(string, "DWD ");
+	if (IOMMU_CAP_GET_PSI(capa))
+		strcat(string, "PSI ");
+	if (IOMMU_CAP_GET_ISOCH(capa))
+		strcat(string, "ISOCH ");
+	if (IOMMU_CAP_GET_ZLR(capa))
+		strcat(string, "ZLR ");
+	if (IOMMU_CAP_GET_CM(capa))
+		strcat(string, "CM ");
+	if (IOMMU_CAP_GET_PHMR(capa))
+		strcat(string, "PHMR ");
+	if (IOMMU_CAP_GET_PLMR(capa))
+		strcat(string, "PLMR ");
+	if (IOMMU_CAP_GET_RWBF(capa))
+		strcat(string, "RWBF ");
+	if (IOMMU_CAP_GET_AFL(capa))
+		strcat(string, "AFL ");
+
+	len = strlen(string);
+	if ((len > 1) &&
+	    (string[len - 1] == ' '))
+		string[len - 1] = 0;
+
+	strcat(string, "\n");
+	mdb_printf(string);
+}
+
+static void
+parse_hw_excapa(uint64_t excapa)
+{
+	char string[128];
+	size_t len;
+
+	strcpy(string, "  Hardware Ex-Capability:\t");
+	if (IOMMU_ECAP_GET_SC(excapa))
+		strcat(string, "SC ");
+	if (IOMMU_ECAP_GET_PT(excapa))
+		strcat(string, "PT ");
+	if (IOMMU_ECAP_GET_CH(excapa))
+		strcat(string, "CH ");
+	if (IOMMU_ECAP_GET_EIM(excapa))
+		strcat(string, "EIM ");
+	if (IOMMU_ECAP_GET_IR(excapa))
+		strcat(string, "IR ");
+	if (IOMMU_ECAP_GET_DI(excapa))
+		strcat(string, "DI ");
+	if (IOMMU_ECAP_GET_QI(excapa))
+		strcat(string, "QI ");
+	if (IOMMU_ECAP_GET_C(excapa))
+		strcat(string, "C ");
+
+	len = strlen(string);
+	if ((len > 1) &&
+	    (string[len - 1] == ' '))
+		string[len - 1] = 0;
+
+	strcat(string, "\n");
+	mdb_printf(string);
+}
+
+typedef enum {
+	ERROR_SCOPE,
+	INCLUDE_ALL_SCOPE,
+	DEV_SCOPE
+} iomu_scope_t;
+
+/*
+ * print_iommu_state()
+ *  Given an iommu_state structure, parse and print iommu information
+ *
+ *  Returns:
+ *   INCLUDE_ALL_SCOPE if include all is set
+ *   DEV_SCOPE if not set
+ *   ERROR_SCOPE on error.
+ */
+static iomu_scope_t
+print_iommu_state(intel_iommu_state_t *iommu, drhd_info_t *drhd)
+{
+	if ((iommu == NULL) || (drhd == NULL)) {
+		mdb_warn("Internal error - NULL iommu state pointer passed\n");
+		return (ERROR_SCOPE);
+	}
+
+	mdb_printf("Intel DMA remapping unit\n");
+	mdb_printf("  IOMMU Status:\t\t\t%s\n",
+	    (iommu->iu_enabled & DMAR_ENABLE) ? "Enabled" : "Disabled");
+	mdb_printf("  Queued Invalid:\t\t%s\n",
+	    (iommu->iu_enabled & QINV_ENABLE) ? "Enabled" : "Disabled");
+	mdb_printf("  Interrupt remapping:\t\t%s\n",
+	    (iommu->iu_enabled & INTRR_ENABLE) ? "Enabled" : "Disabled");
+	mdb_printf("  Register Physical Address:\t%p\n",
+	    (uintptr_t)drhd->di_reg_base);
+	mdb_printf("  Register Virtual Address:\t%p\n",
+	    (uintptr_t)iommu->iu_reg_address);
+	parse_hw_capa(iommu->iu_capability);
+	parse_hw_excapa(iommu->iu_excapability);
+	mdb_printf("  Root Entry Table:\t\t%p\n",
+	    (uintptr_t)iommu->iu_root_entry_paddr);
+	mdb_printf("  Guest Address Width:\t\t%d\n", iommu->iu_gaw);
+	mdb_printf("  Adjust Guest Address Width:\t%d\n", iommu->iu_agaw);
+	mdb_printf("  Page Table Level:\t\t%d\n", iommu->iu_level);
+	mdb_printf("  Max Domain Supported:\t\t%d\n", iommu->iu_max_domain);
+	mdb_printf("  System Coherence:\t\t%s\n",
+	    iommu->iu_coherency ? "Yes" : "No");
+	mdb_printf("  Include All unit:\t\t%s\n",
+	    drhd->di_include_all ? "Yes" : "No");
+	mdb_printf("  Devinfo Node:\t\t\t%p\n",
+	    (intptr_t)drhd->di_dip);
+
+	if (iommu->iu_enabled & QINV_ENABLE) {
+		struct inv_queue_state qi_state;
+		if (iommu->iu_inv_queue &&
+		    mdb_vread(&qi_state, sizeof (qi_state),
+		    (intptr_t)iommu->iu_inv_queue) == sizeof (qi_state)) {
+			mdb_printf("  Qinv Table:\t\t\tpaddr:%p, "
+			    "vaddr:%p, size:%x\n",
+			    (uintptr_t)qi_state.iq_table.paddr,
+			    (uintptr_t)qi_state.iq_table.vaddr,
+			    qi_state.iq_table.size);
+			mdb_printf("  Sync Table:\t\t\tpaddr:%p, "
+			    "vaddr:%p, size:%x\n",
+			    (uintptr_t)qi_state.iq_sync.paddr,
+			    (uintptr_t)qi_state.iq_sync.vaddr,
+			    qi_state.iq_sync.size);
+		} else {
+			mdb_warn("failed to read iommu invalidation "
+			    "queue state at %p\n",
+			    (uintptr_t)iommu->iu_inv_queue);
+			return (ERROR_SCOPE);
+		}
+	}
+
+	return (drhd->di_include_all ? INCLUDE_ALL_SCOPE : DEV_SCOPE);
+}
+
+/*
+ * dcmd: iomuprt
+ */
+static int
+iomuprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(argv))
+	intel_iommu_state_t iommu;
+	drhd_info_t drhd;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((argc != 0) || !(flags & DCMD_ADDRSPEC))
+		return (DCMD_USAGE);
+
+	if (!DCMD_HDRSPEC(flags))
+		mdb_printf("\n");
+
+	if ((mdb_vread(&iommu, sizeof (iommu), addr) == sizeof (iommu)) &&
+	    (iommu.iu_drhd != NULL) &&
+	    (mdb_vread(&drhd, sizeof (drhd),
+	    (intptr_t)iommu.iu_drhd) == sizeof (drhd))) {
+		switch (print_iommu_state(&iommu, &drhd)) {
+		case DEV_SCOPE:
+			/*
+			 * Use actual address of list_t in kernel for walker
+			 */
+			print_device_scope("  Device Scope:\t\t\t",
+			    (uintptr_t)((char *)iommu.iu_drhd +
+			    offsetof(drhd_info_t, di_dev_list)));
+			break;
+		case ERROR_SCOPE:
+			return (DCMD_ERR);
+		default:
+			break;
+		}
+	} else {
+		mdb_warn("failed to read iommu state at %p\n", addr);
+		return (DCMD_ERR);
+	}
+
+	return (DCMD_OK);
+}
+
+/*
+ * print_iommu_addr()
+ * callback to print addresses of IOMMU unit software structures
+ */
+static int
+print_iommu_addr(uintptr_t addr, intel_iommu_state_t *ip, void *cbdata)
+{
+	_NOTE(ARGUNUSED(cbdata))
+	_NOTE(ARGUNUSED(ip))
+	intel_iommu_state_t iommu;
+
+	if (mdb_vread(&iommu, sizeof (iommu), addr) != sizeof (iommu)) {
+		mdb_warn("failed to read IOMMU structure at %p\n", addr);
+		return (WALK_ERR);
+	}
+
+	mdb_printf("%p\n", addr);
+
+	return (WALK_NEXT);
+}
+
+/*
+ * dcmd: iomunits
+ */
+static int
+iomunits(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(addr))
+	_NOTE(ARGUNUSED(argv))
+	GElf_Sym sym;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((flags & DCMD_ADDRSPEC) || (argc != 0)) {
+		return (DCMD_USAGE);
+	}
+
+	if (mdb_lookup_by_name("iommu_states", &sym) == -1) {
+		mdb_warn("failed to find symbol iommu_states\n");
+		return (DCMD_ERR);
+	}
+
+	addr = (uintptr_t)sym.st_value;
+	if (mdb_pwalk("list", (mdb_walk_cb_t)print_iommu_addr, NULL, addr)) {
+		mdb_warn("couldn't walk IOMMU state structures\n");
+		return (DCMD_ERR);
+	}
+	return (DCMD_OK);
+}
+
+
+
+/*
+ * print_domain_state()
+ *   Given an device domain structure, parse and print information
+ */
+static void
+print_domain_state(dmar_domain_state_t *domain)
+{
+	if (domain == NULL) {
+		mdb_warn("Internal error: NULL domain pointer passed\n");
+		return;
+	}
+
+	mdb_printf("IOMMU device domain:\n");
+	mdb_printf("Domain ID:\t\t%d\n", domain->dm_domain_id);
+	mdb_printf("Bind IOMMU:\t\t%p\n", (uintptr_t)domain->dm_iommu);
+	mdb_printf("DVMA vmem:\t\t%p\n",
+	    (uintptr_t)domain->dm_dvma_map);
+	mdb_printf("Top Level Page Table:\t%p\n",
+	    (uintptr_t)domain->dm_page_table_paddr);
+	mdb_printf("Identity Mapping:\t\t%s\n",
+	    domain->dm_identity ? "YES" : "NO");
+}
+
+/*
+ * dcmd: iomudomprt
+ */
+static int
+iomudomprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(argv))
+	dmar_domain_state_t domain;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((argc != 0) || !(flags & DCMD_ADDRSPEC))
+		return (DCMD_USAGE);
+
+	if (!DCMD_HDRSPEC(flags))
+		mdb_printf("\n");
+
+	if (mdb_vread(&domain, sizeof (domain), addr) == sizeof (domain)) {
+		print_domain_state(&domain);
+	} else {
+		mdb_warn("failed to read domain at %p\n", addr);
+		return (DCMD_ERR);
+	}
+
+	return (DCMD_OK);
+}
+
+/*
+ * print_domain_addr()
+ */
+static int
+print_domain_addr(uintptr_t addr, dmar_domain_state_t *domp, void *cbdata)
+{
+	_NOTE(ARGUNUSED(domp))
+	_NOTE(ARGUNUSED(cbdata))
+	dmar_domain_state_t domain;
+
+	if (iommu_supported() == B_FALSE)
+		return (WALK_NEXT);
+
+	if (mdb_vread(&domain, sizeof (domain), addr) != sizeof (domain)) {
+		mdb_warn("failed to read domain at %p\n", addr);
+		return (WALK_ERR);
+	}
+
+	mdb_printf("%p\n", addr);
+
+	return (WALK_NEXT);
+}
+
+/*
+ * dcmd: iomudoms
+ */
+static int
+iomudoms(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(addr))
+	_NOTE(ARGUNUSED(argv))
+	GElf_Sym sym;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((flags & DCMD_ADDRSPEC) || (argc != 0)) {
+		return (DCMD_USAGE);
+	}
+
+	if (mdb_lookup_by_name("domain_states", &sym) == -1) {
+		mdb_warn("failed to find symbol domain_states\n");
+		return (DCMD_ERR);
+	}
+
+	addr = (uintptr_t)sym.st_value;
+	if (mdb_pwalk("list", (mdb_walk_cb_t)print_domain_addr, NULL, addr))
+		return (DCMD_ERR);
+	return (DCMD_OK);
+}
+
+/*
+ * print_rmrr_info()
+ */
+static void
+print_rmrr_info(rmrr_info_t *rmrr)
+{
+	mdb_printf("Reserved Memory Region Reporting:\n");
+	mdb_printf("  Segment:\t%d\n", rmrr->ri_segment);
+	mdb_printf("  BaseAddr:\t%p\n", (uintptr_t)rmrr->ri_baseaddr);
+	mdb_printf("  LimiAddr:\t%p\n", (uintptr_t)rmrr->ri_limiaddr);
+}
+
+/*
+ * print_rmrr_addr()
+ *   list walk callback for list_rmrr
+ */
+static int
+print_rmrr_addr(uintptr_t addr, rmrr_info_t *rp, void *cbdata)
+{
+	_NOTE(ARGUNUSED(rp))
+	_NOTE(ARGUNUSED(cbdata))
+	rmrr_info_t rmrr;
+
+	if (mdb_vread(&rmrr, sizeof (rmrr), addr) != sizeof (rmrr)) {
+		mdb_warn("failed to read RMRR structure at %p\n", addr);
+		return (WALK_ERR);
+	}
+
+	mdb_printf("%p\n", addr);
+
+	return (WALK_NEXT);
+}
+
+/*
+ * dcmd: iomurmrrs
+ */
+static int
+iomurmrrs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(addr))
+	_NOTE(ARGUNUSED(argv))
+	GElf_Sym sym;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((flags & DCMD_ADDRSPEC) || (argc != 0)) {
+		return (DCMD_USAGE);
+	}
+
+	if (mdb_lookup_by_name("rmrr_states", &sym) == -1) {
+		mdb_warn("failed to find symbol rmrr_states\n");
+		return (DCMD_ERR);
+	}
+
+	addr = (uintptr_t)sym.st_value;
+	if (mdb_pwalk("list", (mdb_walk_cb_t)print_rmrr_addr, NULL, addr))
+		return (DCMD_ERR);
+	return (DCMD_OK);
+}
+
+/*
+ * dcmd: iomurmrrprt: Given an RMRR address print the RMRR.
+ */
+static int
+iomurmrrprt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(argv))
+	uintptr_t dev_list_addr;
+	rmrr_info_t rmrr;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if (!(flags & DCMD_ADDRSPEC) || (argc != 0)) {
+		return (DCMD_USAGE);
+	}
+
+	if (mdb_vread(&rmrr, sizeof (rmrr), addr) != sizeof (rmrr)) {
+		mdb_warn("failed to read RMRR structure at %p\n", addr);
+		return (DCMD_ERR);
+	}
+
+	dev_list_addr = addr + offsetof(rmrr_info_t, ri_dev_list);
+	print_rmrr_info(&rmrr);
+	print_device_scope("  DevScope:\t", dev_list_addr);
+
+	return (DCMD_OK);
+}
+
+/*
+ * iova_level_to_offset()
+ *   Given an iova and page table level, return the corresponding offset
+ */
+static int
+iova_level_to_offset(uintptr_t iova, int level)
+{
+	int start, offset;
+
+	start = (level - 1) * IOMMU_LEVEL_STRIDE + IOMMU_PAGE_SHIFT;
+	offset = (iova >> start) & IOMMU_LEVEL_OFFSET;
+
+	return (offset);
+}
+
+/*
+ * iovtp_read_table_entry()
+ */
+static int
+iovtp_read_table_entry(uint64_t ptaddr, size_t offset,
+    void *ent_buf, size_t ent_size)
+{
+	if (mdb_pread(ent_buf, ent_size, ptaddr + offset * ent_size)
+	    != ent_size) {
+		return (B_FALSE);
+	} else {
+		return (B_TRUE);
+	}
+}
+
+/*
+ * dcmd: iomuvtop
+ */
+static int
+iomuvtop(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	iommu_private_t private;
+	dmar_domain_state_t domain;
+	struct dev_info dinfo;
+	intel_iommu_state_t iommu;
+	int i, level, offset;
+	uintptr_t iova;
+	uint64_t ptaddr, ptentr;
+	int bus, devfn;
+
+	struct root_context_entry {
+		uint64_t asr;
+		uint64_t pro;
+	} rc_entry;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if (!(flags & DCMD_ADDRSPEC) || (argc != 1)) {
+		return (DCMD_USAGE);
+	}
+
+	iova = (argv[0].a_type == MDB_TYPE_IMMEDIATE) ?
+	    (uintptr_t)argv[0].a_un.a_val :
+	    (uintptr_t)mdb_strtoull(argv->a_un.a_str);
+
+	/* read iommu private */
+	if ((mdb_vread(&dinfo, sizeof (dinfo), addr) != sizeof (dinfo)) ||
+	    (dinfo.devi_iommu_private == NULL) ||
+	    (mdb_vread(&private, sizeof (private),
+	    (uintptr_t)dinfo.devi_iommu_private) != sizeof (private))) {
+		mdb_warn("failed to read iommu private structure for "
+		    "devinfo node at address %p\n", addr);
+		return (DCMD_ERR);
+	}
+
+	bus = private.idp_bus;
+	devfn = private.idp_devfn;
+
+	/* read domain */
+	if (private.idp_intel_domain == NULL) {
+		mdb_printf("IOMMU domain for this device has not yet been "
+		    "allocated.\nNo mapped physical address for this vaddr\n");
+		return (DCMD_OK);
+	}
+
+	if (mdb_vread(&domain, sizeof (domain),
+	    (uintptr_t)private.idp_intel_domain)
+	    != sizeof (domain)) {
+		mdb_warn("failed to read domain structure at %p\n",
+		    (uintptr_t)private.idp_intel_domain);
+		return (DCMD_ERR);
+	}
+
+	/* read iommu */
+	if (mdb_vread(&iommu, sizeof (iommu), (uintptr_t)domain.dm_iommu)
+	    != sizeof (iommu)) {
+		mdb_warn("failed to read iommu structure at %p\n",
+		    (uintptr_t)domain.dm_iommu);
+		return (DCMD_ERR);
+	}
+
+	mdb_printf("Level\tPageTableAddress\tOffset\tPageTableEntry\n");
+
+	/* walk and print root context tabls */
+	ptaddr = iommu.iu_root_entry_paddr;
+	if (iovtp_read_table_entry(ptaddr, bus, &rc_entry, sizeof (rc_entry))
+	    == B_FALSE) {
+		mdb_warn("failed to read root table entry for bus %x "
+		    "at %p\n", bus, (uintptr_t)ptaddr);
+		return (DCMD_ERR);
+	}
+	mdb_printf("Root\t%p\t\t%x\tlow :%p\n", (uintptr_t)ptaddr,
+	    bus, (uintptr_t)rc_entry.asr);
+	mdb_printf("Root\t%p\t\t%x\thigh:%p\n", (uintptr_t)ptaddr,
+	    bus, (uintptr_t)rc_entry.pro);
+
+	ptaddr = rc_entry.asr & IOMMU_PAGE_MASK;
+	if (iovtp_read_table_entry(ptaddr, devfn, &rc_entry, sizeof (rc_entry))
+	    == B_FALSE) {
+		mdb_warn("failed to read context table entry for "
+		    "device-function %x at %p\n", devfn, (uintptr_t)ptaddr);
+		return (DCMD_ERR);
+	}
+	mdb_printf("Context\t%p\t\t%x\tlow :%p\n", (uintptr_t)ptaddr,
+	    devfn, (uintptr_t)rc_entry.asr);
+	mdb_printf("Context\t%p\t\t%x\thigh:%p\n", (uintptr_t)ptaddr,
+	    devfn, (uintptr_t)rc_entry.pro);
+
+	/* walk and print page tables */
+	ptaddr = rc_entry.asr & IOMMU_PAGE_MASK;
+
+	/*
+	 * Toppest level page table address should be the same
+	 * as that stored in domain structure
+	 */
+	if (ptaddr != domain.dm_page_table_paddr) {
+		mdb_warn("The top level page table retrieved from context"
+		    " table doesn't match that from the domain structure."
+		    " Aborting PA lookup.\n");
+		return (DCMD_ERR);
+	}
+
+	level = iommu.iu_level;
+	for (i = level; i > 0; i--) {
+		if (!ptaddr) {
+			mdb_printf("\nNULL page table entry encountered at "
+			" page table level %d. Aborting PA lookup.\n", i);
+			return (DCMD_OK);
+		}
+		offset = iova_level_to_offset(iova, i);
+		if (iovtp_read_table_entry(ptaddr, offset, &ptentr,
+		    sizeof (ptentr)) == B_FALSE) {
+			mdb_warn("failed to read page table entry "
+			    "(level %d) at %p\n", i, (uintptr_t)ptaddr);
+			return (DCMD_ERR);
+		}
+		mdb_printf("%x\t%p\t\t%x\t%p\n", i, (uintptr_t)ptaddr,
+		    offset, (uintptr_t)ptentr);
+		ptaddr = ptentr & IOMMU_PAGE_MASK;
+	}
+
+	return (DCMD_OK);
+}
+
+typedef struct bdf_cb_data {
+	int	dc_seg;
+	int	dc_bus;
+	int	dc_devfunc;
+	int	dc_match;
+} bdf_cb_data_t;
+
+/*
+ * match_bdf()
+ *   call back function that matches BDF
+ */
+static int
+match_bdf(uintptr_t addr, struct dev_info *dev, bdf_cb_data_t *cbdata)
+{
+	_NOTE(ARGUNUSED(addr))
+	/* if there is iommu private, get it */
+	if (dev->devi_iommu_private != NULL) {
+		iommu_private_t private;
+		if (mdb_vread((void*)&private, sizeof (private),
+		    (uintptr_t)dev->devi_iommu_private) != sizeof (private)) {
+			mdb_warn("failed to read iommu private at %p\n",
+			    (uintptr_t)dev->devi_iommu_private);
+			return (WALK_ERR);
+		}
+
+		if (private.idp_seg == cbdata->dc_seg &&
+		    private.idp_bus == cbdata->dc_bus &&
+		    private.idp_devfn == cbdata->dc_devfunc) {
+			if (cbdata->dc_match == 0) {
+				mdb_printf("%p\n", addr);
+				cbdata->dc_match = 1;
+			} else {
+				mdb_warn("More than one devinfo node matches "
+				    "a single pci device. Aborting devinfo "
+				    "lookup\n");
+				return (WALK_ERR);
+			}
+		}
+	}
+
+	return (WALK_NEXT);
+}
+
+/*
+ * dcmd: bdf2devinfo
+ */
+static int
+bdf2devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(addr))
+	bdf_cb_data_t cbdata;
+	uint_t i, bdf[4];
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if ((flags & DCMD_ADDRSPEC) || (argc != 4)) {
+		return (DCMD_USAGE);
+	}
+
+	for (i = 0; i < 4; i++) {
+		bdf[i] = (argv[i].a_type == MDB_TYPE_IMMEDIATE) ?
+		    (int)argv[i].a_un.a_val :
+		    (int)mdb_strtoull(argv[i].a_un.a_str);
+	}
+
+	if ((bdf[0] != 0) || (bdf[1] > 255) || (bdf[2] > 31) || (bdf[3] > 7)) {
+		mdb_warn("invalid pci segment, bus, device, function"
+		    "tuple (%x, %x, %x, %x)\n", bdf[0], bdf[1], bdf[2], bdf[3]);
+		return (DCMD_USAGE);
+	}
+
+
+	cbdata.dc_seg = bdf[0];
+	cbdata.dc_bus = bdf[1];
+	cbdata.dc_devfunc = bdf[2] << 3 | bdf[3];
+	cbdata.dc_match = 0;
+
+	if (mdb_readvar(&addr, "top_devinfo") == -1) {
+		mdb_warn("failed to read 'top_devinfo'\n");
+		return (DCMD_ERR);
+	}
+
+	if (mdb_pwalk("devinfo",
+	    (mdb_walk_cb_t)match_bdf, &cbdata, addr)) {
+		mdb_warn("couldn't walk devinfo tree\n");
+		return (DCMD_ERR);
+	}
+
+	if (cbdata.dc_match == 0)
+		mdb_printf("No devinfo node found for %x:%x:%x:%x\n",
+		    bdf[0], bdf[1], bdf[2], bdf[3]);
+
+	return (DCMD_OK);
+}
+
+/*
+ * dcmd: iomudip2dom
+ */
+static int
+iomudip2dom(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+	_NOTE(ARGUNUSED(argv))
+	struct dev_info dinfo;
+	iommu_private_t private;
+
+	if (iommu_supported() == B_FALSE)
+		return (DCMD_OK);
+
+	if (!(flags & DCMD_ADDRSPEC) || (argc != 0)) {
+		return (DCMD_USAGE);
+	}
+
+	/* read iommu private */
+	if ((mdb_vread(&dinfo, sizeof (dinfo), addr) != sizeof (dinfo)) ||
+	    (dinfo.devi_iommu_private == NULL) ||
+	    (mdb_vread(&private, sizeof (private),
+	    (uintptr_t)dinfo.devi_iommu_private) != sizeof (private))) {
+		mdb_warn("failed to read iommu private structure for "
+		    "devinfo node at %p\n", addr);
+		return (DCMD_ERR);
+	}
+
+	/* read domain */
+	if (private.idp_intel_domain != NULL) {
+		mdb_printf("%p\n", (uintptr_t)private.idp_intel_domain);
+	} else {
+		mdb_printf("No domain dedicated for this device\n");
+	}
+
+	return (DCMD_OK);
+}
+
+static const mdb_dcmd_t dcmds[] = {
+	{ "iomunits", NULL,
+		"list addresses of software state structure for all IOMMUs",
+		iomunits },
+	{ "iomuprt", "?",
+		"given an IOMMU's state structure address, print its contents",
+		iomuprt},
+	{ "iomudoms", NULL,
+		"list addresses of all IOMMU domain software structures",
+		iomudoms },
+	{ "iomudomprt", "?",
+		"given an IOMMU's domain struct address, print its contents",
+		iomudomprt },
+	{ "iomurmrrs", NULL,
+		"list addresses of all Intel IOMMU RMRR software structures",
+		iomurmrrs },
+	{ "iomurmrrprt", NULL,
+		"given an IOMMU RMRR structure address, print its contents",
+		iomurmrrprt },
+	{ "iomuvtop", "?<iova>",
+		"print physical address of an IO virtual address",
+		iomuvtop, iomuvtop_help },
+	{ "bdf2devinfo", "[segment] [bus] [dev] [func]",
+		"given its pci segment/bus/dev/func, print the devinfo node",
+		bdf2devinfo },
+	{ "iomudip2dom", "?",
+		"given a devinfo node, print the address of its IOMMU domain",
+		iomudip2dom },
+	{ NULL }
+};
+
+static const mdb_walker_t walkers[] = {
+	{ NULL }
+};
+
+static const mdb_modinfo_t modinfo = {
+	MDB_API_VERSION, dcmds, walkers
+};
+
+const mdb_modinfo_t *
+_mdb_init(void)
+{
+	GElf_Sym sym;
+
+	/* check to see if kernel supports iommu */
+	if (mdb_lookup_by_name("intel_iommu_support", &sym) != -1) {
+		if (mdb_vread(&iommu_support, sizeof (boolean_t),
+		    (uintptr_t)sym.st_value) != sizeof (boolean_t)) {
+			iommu_support = B_FALSE;
+		}
+	}
+
+	return (&modinfo);
+}
--- a/usr/src/cmd/mdb/intel/amd64/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/mdb/intel/amd64/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -20,14 +19,13 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 include ../../Makefile.common
 
-MODULES = $(COMMON_MODULES_PROC) $(COMMON_MODULES_KVM) uhci
+MODULES = $(COMMON_MODULES_PROC) $(COMMON_MODULES_KVM) uhci rootnex
 
 $(CLOSED_BUILD)MODULES += \
 	$(CLOSED_COMMON_MODULES_KVM:%=$(CLOSED)/cmd/mdb/intel/amd64/%)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/amd64/rootnex/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+
+# Copyright (c) 2009, Intel Corporation.
+# All rights reserved.
+
+MODULE = rootnex.so
+MDBTGT = kvm
+
+MODSRCS = intel_iommu.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
+
+CPPFLAGS += -I$(SRC)/uts/i86pc
--- a/usr/src/cmd/mdb/intel/ia32/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/mdb/intel/ia32/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -19,15 +19,14 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 include ../../Makefile.common
 
 MODULES = $(COMMON_MODULES_PROC) $(COMMON_MODULES_PROC_32BIT) \
-    $(COMMON_MODULES_KVM) uhci
+    $(COMMON_MODULES_KVM) uhci rootnex
 
 $(CLOSED_BUILD)MODULES += \
 	$(CLOSED_COMMON_MODULES_KVM:%=$(CLOSED)/cmd/mdb/intel/ia32/%)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/mdb/intel/ia32/rootnex/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+
+# Copyright (c) 2009, Intel Corporation.
+# All rights reserved.
+
+MODULE = rootnex.so
+MDBTGT = kvm
+
+MODSRCS = intel_iommu.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
+
+CPPFLAGS += -I$(SRC)/uts/i86pc
--- a/usr/src/cmd/modload/add_drv.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/modload/add_drv.c	Mon Sep 21 11:26:40 2009 -0400
@@ -42,6 +42,7 @@
 #include <libdevinfo.h>
 #include <sys/sysmacros.h>
 #include <fcntl.h>
+#include <zone.h>
 #include "addrem.h"
 #include "errmsg.h"
 #include "plcysubr.h"
@@ -200,6 +201,11 @@
 		exit(1);
 	}
 
+	if (getzoneid() != GLOBAL_ZONEID) {
+		(void) fprintf(stderr, gettext(ERR_NOT_GLOBAL_ZONE));
+		exit(1);
+	}
+
 	/*
 	 * Fail if add_drv was invoked with a pathname prepended to the
 	 * driver_name argument.
--- a/usr/src/cmd/modload/errmsg.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/modload/errmsg.h	Mon Sep 21 11:26:40 2009 -0400
@@ -63,6 +63,8 @@
 #define	ERR_FORK_FAIL	"Fork failed; cannot exec : %s\n"
 #define	ERR_PROG_IN_USE	"add_drv/rem_drv currently busy; try later\n"
 #define	ERR_NOT_ROOT	"You must be root to run this program.\n"
+#define	ERR_NOT_GLOBAL_ZONE	\
+"add_drv/rem_drv can only be run from the global zone.\n"
 #define	ERR_BAD_LINE	"Bad line in file %s : %s\n"
 #define	ERR_CANNOT_OPEN	"Cannot open (%s): %s.\n"
 #define	ERR_MIS_TOK	"Option (%s) : missing token: (%s)\n"
--- a/usr/src/cmd/modload/modload.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/modload/modload.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/param.h>
@@ -37,6 +34,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <zone.h>
 
 void	l_exec_userfile(char *execfile, int id, char **envp);
 void	l_usage();
@@ -75,6 +73,11 @@
 			l_usage();
 		}
 	}
+
+	if (getzoneid() != GLOBAL_ZONEID) {
+		fatal("modload can only be run from the global zone\n");
+	}
+
 	modpath = argv[optind];
 
 	if (modpath == NULL) {
--- a/usr/src/cmd/modload/modunload.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/modload/modunload.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -36,6 +33,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/modctl.h>
+#include <zone.h>
 
 void	usage();
 void	exec_userfile(char *execfile, int id, char **envp);
@@ -70,6 +68,10 @@
 		}
 	}
 
+	if (getzoneid() != GLOBAL_ZONEID) {
+		fatal("modunload can only be run from the global zone\n");
+	}
+
 	if (execfile) {
 		child = fork();
 		if (child == -1)
@@ -90,10 +92,10 @@
 	 * Unload the module.
 	 */
 	if (modctl(MODUNLOAD, id) < 0) {
-	    if (errno == EPERM)
-		fatal("Insufficient privileges to unload a module\n");
-	    else if (id != 0)
-		error("can't unload the module");
+		if (errno == EPERM)
+			fatal("Insufficient privileges to unload a module\n");
+		else if (id != 0)
+			error("can't unload the module");
 	}
 
 	return (0);			/* success */
--- a/usr/src/cmd/modload/rem_drv.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/modload/rem_drv.c	Mon Sep 21 11:26:40 2009 -0400
@@ -42,6 +42,7 @@
 #include <sys/modctl.h>
 #include <sys/instance.h>
 #include <libdevinfo.h>
+#include <zone.h>
 
 #include "addrem.h"
 #include "errmsg.h"
@@ -120,6 +121,11 @@
 		exit(1);
 	}
 
+	if (getzoneid() != GLOBAL_ZONEID) {
+		(void) fprintf(stderr, gettext(ERR_NOT_GLOBAL_ZONE));
+		exit(1);
+	}
+
 	/* set up add_drv filenames */
 	if ((build_filenames(basedir)) == ERROR) {
 		exit(1);
--- a/usr/src/cmd/print/bsd-sysv-commands/lpstat.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/print/bsd-sysv-commands/lpstat.c	Mon Sep 21 11:26:40 2009 -0400
@@ -403,7 +403,7 @@
 
 	switch (pstat) {
 	case 0x03:	/* idle */
-		printf(gettext("idle. enabled"));
+		printf(gettext("is idle. enabled"));
 		break;
 	case 0x04: /* processing */
 		status = papiPrinterListJobs(svc, name, NULL,
--- a/usr/src/cmd/rmvolmgr/rmvolmgr.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/rmvolmgr/rmvolmgr.c	Mon Sep 21 11:26:40 2009 -0400
@@ -74,7 +74,6 @@
 static boolean_t	rmm_prop_eject_button = B_TRUE;
 
 static void	get_smf_properties();
-static int	daemon(int nochdir, int noclose);
 static void	rmm_device_added(LibHalContext *ctx, const char *udi);
 static void	rmm_device_removed(LibHalContext *ctx, const char *udi);
 static void	rmm_property_modified(LibHalContext *ctx, const char *udi,
@@ -594,50 +593,6 @@
 	}
 }
 
-static int
-daemon(int nochdir, int noclose)
-{
-	int fd;
-
-	switch (fork()) {
-	case -1:
-		return (-1);
-	case 0:
-		break;
-	default:
-		exit(0);
-	}
-
-	if (setsid() == -1)
-		return (-1);
-
-	if (!nochdir)
-		(void) chdir("/");
-
-	if (!noclose) {
-		struct stat64 st;
-
-		if (((fd = open("/dev/null", O_RDWR, 0)) != -1) &&
-		    (fstat64(fd, &st) == 0)) {
-			if (S_ISCHR(st.st_mode) != 0) {
-				(void) dup2(fd, STDIN_FILENO);
-				(void) dup2(fd, STDOUT_FILENO);
-				(void) dup2(fd, STDERR_FILENO);
-				if (fd > 2)
-					(void) close(fd);
-			} else {
-				(void) close(fd);
-				(void) __set_errno(ENODEV);
-				return (-1);
-			}
-		} else {
-			(void) close(fd);
-			return (-1);
-		}
-	}
-	return (0);
-}
-
 int
 main(int argc, char **argv)
 {
--- a/usr/src/cmd/sgs/include/debug.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/include/debug.h	Mon Sep 21 11:26:40 2009 -0400
@@ -424,6 +424,7 @@
 #define	Dbg_syms_spec_title	Dbg64_syms_spec_title
 #define	Dbg_syms_updated	Dbg64_syms_updated
 #define	Dbg_syms_up_title	Dbg64_syms_up_title
+#define	Dbg_syms_wrap		Dbg64_syms_wrap
 
 #define	Dbg_util_call_array	Dbg64_util_call_array
 #define	Dbg_util_call_fini	Dbg64_util_call_fini
@@ -632,6 +633,7 @@
 #define	Dbg_syms_spec_title	Dbg32_syms_spec_title
 #define	Dbg_syms_updated	Dbg32_syms_updated
 #define	Dbg_syms_up_title	Dbg32_syms_up_title
+#define	Dbg_syms_wrap		Dbg32_syms_wrap
 
 #define	Dbg_util_call_array	Dbg32_util_call_array
 #define	Dbg_util_call_fini	Dbg32_util_call_fini
@@ -896,6 +898,7 @@
 extern	void	Dbg_syms_spec_title(Lm_list *);
 extern	void	Dbg_syms_updated(Ofl_desc *, Sym_desc *, const char *);
 extern	void	Dbg_syms_up_title(Lm_list *);
+extern	void	Dbg_syms_wrap(Lm_list *, Word, const char *, const char *);
 
 extern	void	Dbg_tls_modactivity(Lm_list *, void *, uint_t);
 extern	void	Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t);
--- a/usr/src/cmd/sgs/include/libld.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/include/libld.h	Mon Sep 21 11:26:40 2009 -0400
@@ -150,6 +150,20 @@
 } Rlxrel_cache;
 
 /*
+ * Nodes in an ofl_wrap AVL tree
+ *
+ * wsn_name is the name of the symbol to be wrapped. wsn_wrapname is used
+ * when we need to refer to the wrap symbol, and consists of the symbol
+ * name with a __wrap_ prefix.
+ */
+typedef struct wrap_sym_node {
+	avl_node_t	wsn_avlnode;	/* AVL book-keeping */
+	const char	*wsn_name;	/* Symbol name: XXX */
+	const char	*wsn_wrapname;	/* Wrap symbol name: __wrap_XXX */
+} WrapSymNode;
+
+
+/*
  * Output file processing structure
  */
 typedef Lword ofl_flag_t;
@@ -304,6 +318,7 @@
 					/*	sloppy_comdat_reloc() */
 	APlist		*ofl_maptext;	/* mapfile added text sections */
 	APlist		*ofl_mapdata;	/* mapfile added data sections */
+	avl_tree_t	*ofl_wrap;	/* -z wrap symbols  */
 };
 
 #define	FLG_OF_DYNAMIC	0x00000001	/* generate dynamic output module */
--- a/usr/src/cmd/sgs/libld/Makefile.com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/Makefile.com	Mon Sep 21 11:26:40 2009 -0400
@@ -33,14 +33,14 @@
 		libs32.o	files32.o	map32.o		order32.o \
 		outfile32.o	place32.o	relocate32.o	resolve32.o \
 		sections32.o	sunwmove32.o	support32.o	syms32.o \
-		update32.o	unwind32.o	version32.o
+		update32.o	unwind32.o	version32.o	wrap32.o
 
 COMOBJS64 =	args64.o	entry64.o	exit64.o	groups64.o \
 		ldentry64.o	ldlibs64.o	ldmachdep64.o	ldmain64.o \
 		libs64.o	files64.o	map64.o		order64.o \
 		outfile64.o 	place64.o	relocate64.o	resolve64.o \
 		sections64.o	sunwmove64.o	support64.o	syms64.o \
-		update64.o	unwind64.o	version64.o
+		update64.o	unwind64.o	version64.o	wrap64.o
 
 TOOLOBJS =	alist.o		assfail.o	findprime.o	string_table.o \
 		strhash.o
--- a/usr/src/cmd/sgs/libld/common/_libld.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/_libld.h	Mon Sep 21 11:26:40 2009 -0400
@@ -617,6 +617,7 @@
 #define	ld_vers_promote		ld64_vers_promote
 #define	ld_vers_sym_process	ld64_vers_sym_process
 #define	ld_vers_verify		ld64_vers_verify
+#define	ld_wrap_enter		ld64_wrap_enter
 
 #else
 
@@ -705,6 +706,7 @@
 #define	ld_vers_promote		ld32_vers_promote
 #define	ld_vers_sym_process	ld32_vers_sym_process
 #define	ld_vers_verify		ld32_vers_verify
+#define	ld_wrap_enter		ld32_wrap_enter
 
 #endif
 
@@ -834,6 +836,7 @@
 			    Ofl_desc *);
 extern int		ld_vers_sym_process(Lm_list *, Is_desc *, Ifl_desc *);
 extern int		ld_vers_verify(Ofl_desc *);
+extern WrapSymNode	*ld_wrap_enter(Ofl_desc *, const char *);
 
 extern uintptr_t	add_regsym(Sym_desc *, Ofl_desc *);
 extern Word		hashbkts(Word);
--- a/usr/src/cmd/sgs/libld/common/args.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/args.c	Mon Sep 21 11:26:40 2009 -0400
@@ -55,6 +55,21 @@
  *    -z nosighandler		suppress the registration of the signal handler
  *				used to manage SIGBUS.
  */
+
+/*
+ * The following flags are committed, and will not be removed, but are
+ * not publically documented, either because they are obsolete, or because
+ * they exist to work around defects in other software and are not of
+ * sufficient interest otherwise.
+ *
+ *    OPTION			MEANING
+ *
+ *    -Wl,...			compiler drivers and configuration tools
+ *				have been known to pass this compiler option
+ *				to ld(1).  Strip off the "-Wl," prefix and
+ *			        process the remainder (...) as a normal option.
+ */
+
 #include	<sys/link.h>
 #include	<stdio.h>
 #include	<fcntl.h>
@@ -198,6 +213,7 @@
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZT));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTO));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZTW));
+	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZWRAP));
 	(void) fprintf(stderr, MSG_INTL(MSG_ARG_DETAIL_ZV));
 }
 
@@ -1299,6 +1315,17 @@
 					/* Don't report cascading errors */
 					ofl->ofl_ars_gsandx = -1;
 				}
+
+			/*
+			 * If -z wrap is seen, enter the symbol to be wrapped
+			 * into the wrap AVL tree.
+			 */
+			} else if (strncmp(optarg, MSG_ORIG(MSG_ARG_WRAP),
+			    MSG_ARG_WRAP_SIZE) == 0) {
+				if (ld_wrap_enter(ofl,
+				    optarg + MSG_ARG_WRAP_SIZE) == NULL)
+					return (S_ERROR);
+
 			/*
 			 * The following options just need validation as they
 			 * are interpreted on the second pass through the
--- a/usr/src/cmd/sgs/libld/common/ldmain.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/ldmain.c	Mon Sep 21 11:26:40 2009 -0400
@@ -408,9 +408,8 @@
 	 * our memory consumption and freeing are doing.  We should be able to
 	 * free all the memory that has been allocated as part of the link-edit
 	 * process.
-	 *
-	 * ofl_cleanup(ofl);
 	 */
+	/* ld_ofl_cleanup(ofl); */
 	return (0);
 }
 
--- a/usr/src/cmd/sgs/libld/common/libld.msg	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/libld.msg	Mon Sep 21 11:26:40 2009 -0400
@@ -228,6 +228,8 @@
 			 text\n"
 @ MSG_ARG_DETAIL_ZTW	"\t[-z textwarn]\twarn if there are relocations \
 			 against text\n"
+@ MSG_ARG_DETAIL_ZWRAP	"\t[-z wrap=symbol], [-wrap=symbol], [--wrap=symbol]\n\
+			 \t\t\twrap symbol references\n"
 @ MSG_ARG_DETAIL_ZV	"\t[-z verbose]\t\
 			 generate warnings for suspicious processings\n"
 
@@ -652,11 +654,14 @@
 @ MSG_STR_ISALIST	"$ISALIST"
 @ MSG_STR_OSNAME	"$OSNAME"
 @ MSG_STR_OSREL		"$OSREL"
+@ MSG_STR_UU_REAL_U	"__real_"
+@ MSG_STR_UU_WRAP_U	"__wrap_"
 
 @ MSG_FMT_ARMEM		"%s(%s)"
 @ MSG_FMT_COLPATH	"%s:%s"
 @ MSG_FMT_SYMNAM	"`%s'"
 @ MSG_FMT_NULLSYMNAM	"%s[%d]"
+@ MSG_FMT_STRCAT	"%s%s"
 
 @ MSG_PTH_RTLD		"/usr/lib/ld.so.1"
 
@@ -1211,6 +1216,7 @@
 @ MSG_ARG_NOSIGHANDLER	"nosighandler"
 @ MSG_ARG_GLOBAUDIT	"globalaudit"
 @ MSG_ARG_TARGET	"target="
+@ MSG_ARG_WRAP		"wrap="
 @ MSG_ARG_HELP		"help"
 @ MSG_ARG_GROUP		"group"
 @ MSG_ARG_REDUCE	"reduce"
@@ -1243,6 +1249,7 @@
 @ MSG_ARG_T_UNDEF	"-undefined"
 @ MSG_ARG_T_VERSION	"-version"
 @ MSG_ARG_T_WHOLEARC	"-whole-archive"
+@ MSG_ARG_T_WRAP	"-wrap"
 @ MSG_ARG_T_OPAR	"("
 @ MSG_ARG_T_CPAR	")"
 
--- a/usr/src/cmd/sgs/libld/common/syms.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/syms.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2312,6 +2312,48 @@
 		}
 
 		/*
+		 * The '-z wrap=XXX' option emulates the GNU ld --wrap=XXX
+		 * option. When XXX is the symbol to be wrapped:
+		 *
+		 * -	An undefined reference to XXX is converted to __wrap_XXX
+		 * -	An undefined reference to __real_XXX is converted to XXX
+		 *
+		 * The idea is that the user can supply a wrapper function
+		 * __wrap_XXX that does some work, and then uses the name
+		 * __real_XXX to pass the call on to the real function. The
+		 * wrapper objects are linked with the original unmodified
+		 * objects to produce a wrapped version of the output object.
+		 */
+		if (ofl->ofl_wrap && name[0] && (shndx == SHN_UNDEF)) {
+			WrapSymNode wsn, *wsnp;
+
+			/*
+			 * If this is the __real_XXX form, advance the
+			 * pointer to reference the wrapped name.
+			 */
+			wsn.wsn_name = name;
+			if ((*name == '_') &&
+			    (strncmp(name, MSG_ORIG(MSG_STR_UU_REAL_U),
+			    MSG_STR_UU_REAL_U_SIZE) == 0))
+				wsn.wsn_name += MSG_STR_UU_REAL_U_SIZE;
+
+			/*
+			 * Is this symbol in the wrap AVL tree? If so, map
+			 * XXX to __wrap_XXX, and __real_XXX to XXX. Note that
+			 * wsn.wsn_name will equal the current value of name
+			 * if the __real_ prefix is not present.
+			 */
+			if ((wsnp = avl_find(ofl->ofl_wrap, &wsn, 0)) != NULL) {
+				const char *old_name = name;
+
+				name = (wsn.wsn_name == name) ?
+				    wsnp->wsn_wrapname : wsn.wsn_name;
+				DBG_CALL(Dbg_syms_wrap(ofl->ofl_lml, ndx,
+				    old_name, name));
+			}
+		}
+
+		/*
 		 * Determine and validate the symbols binding.
 		 */
 		bind = ELF_ST_BIND(sym->st_info);
--- a/usr/src/cmd/sgs/libld/common/util.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/libld/common/util.c	Mon Sep 21 11:26:40 2009 -0400
@@ -279,13 +279,48 @@
 }
 
 /*
+ * The GNU ld '-wrap=XXX' and '--wrap=XXX' options correspond to our
+ * '-z wrap=XXX'. When str2chr() does this conversion, we end up with
+ * the return character set to 'z' and optarg set to 'XXX'. This callback
+ * changes optarg to include the missing wrap= prefix.
+ *
+ * exit:
+ *	Returns c on success, or '?' on error.
+ */
+static int
+str2chr_wrap_cb(int c)
+{
+	char    *str;
+	size_t  len = MSG_ARG_WRAP_SIZE + strlen(optarg) + 1;
+
+	if ((str = libld_malloc(len)) == NULL)
+		return ('?');
+	(void) snprintf(str, len, MSG_ORIG(MSG_FMT_STRCAT),
+	    MSG_ORIG(MSG_ARG_WRAP), optarg);
+	optarg = str;
+	return (c);
+}
+
+/*
  * Determine whether this string, possibly with an associated option, should be
  * translated to an option character.  If so, update the optind and optarg
  * as described for short options in getopt(3c).
+ *
+ * entry:
+ *	lml - Link map list for debug messages
+ *	ndx - Starting optind for current item
+ *	argc, argv - Command line arguments
+ *	arg - Option to be examined
+ *	c, opt - Option character (c) and corresponding long name (opt)
+ *	optsz - 0 if option does not accept a value. If option does
+ *		accept a value, strlen(opt), giving the offset to the
+ *		value if the option and value are combined in one string.
+ *	cbfunc - NULL, or pointer to function to call if a translation is
+ *		successful.
  */
 static int
 str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c,
-    const char *opt, size_t optsz)
+    const char *opt, size_t optsz, int cbfunc(int))
 {
 	if (optsz == 0) {
 		/*
@@ -331,6 +366,10 @@
 					return ('?');
 			}
 		}
+
+		if (cbfunc != NULL)
+			c = (*cbfunc)(c);
+
 		return (c);
 	}
 	return (0);
@@ -362,20 +401,28 @@
 			/* Translate -rpath <optarg> to -R <optarg> */
 			if ((c = str2chr(lml, ndx, argc, argv, arg, 'R',
 			    MSG_ORIG(MSG_ARG_T_RPATH),
-			    MSG_ARG_T_RPATH_SIZE)) != 0) {
+			    MSG_ARG_T_RPATH_SIZE, NULL)) != 0) {
 				return (c);
 			}
 			break;
 		case 's':
 			/* Translate -shared to -G */
 			if ((c = str2chr(lml, ndx, argc, argv, arg, 'G',
-			    MSG_ORIG(MSG_ARG_T_SHARED), 0)) != 0) {
+			    MSG_ORIG(MSG_ARG_T_SHARED), 0, NULL)) != 0) {
 				return (c);
 
 			/* Translate -soname <optarg> to -h <optarg> */
 			} else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h',
 			    MSG_ORIG(MSG_ARG_T_SONAME),
-			    MSG_ARG_T_SONAME_SIZE)) != 0) {
+			    MSG_ARG_T_SONAME_SIZE, NULL)) != 0) {
+				return (c);
+			}
+			break;
+		case 'w':
+			/* Translate -wrap to -z wrap= */
+			if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
+			    MSG_ORIG(MSG_ARG_T_WRAP) + 1,
+			    MSG_ARG_T_WRAP_SIZE - 1, str2chr_wrap_cb)) != 0) {
 				return (c);
 			}
 			break;
@@ -384,7 +431,8 @@
 			 * Translate -( to -z rescan-start
 			 */
 			if ((c = str2chr(lml, ndx, argc, argv,
-			    arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0)) != 0) {
+			    arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0, NULL)) !=
+			    0) {
 				optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START);
 				return (c);
 			}
@@ -394,7 +442,8 @@
 			 * Translate -) to -z rescan-end
 			 */
 			if ((c = str2chr(lml, ndx, argc, argv,
-			    arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0)) != 0) {
+			    arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0, NULL)) !=
+			    0) {
 				optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END);
 				return (c);
 			}
@@ -407,7 +456,8 @@
 				 * -zmuldefs
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_MULDEFS), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_MULDEFS), 0, NULL)) !=
+				    0) {
 					optarg =
 					    (char *)MSG_ORIG(MSG_ARG_MULDEFS);
 					return (c);
@@ -418,7 +468,7 @@
 				 */
 				} else if ((c = str2chr(lml, argc, ndx, argv,
 				    arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR),
-				    MSG_ARG_T_AUXFLTR_SIZE)) != 0) {
+				    MSG_ARG_T_AUXFLTR_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
@@ -429,7 +479,7 @@
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'I',
 				    MSG_ORIG(MSG_ARG_T_INTERP),
-				    MSG_ARG_T_INTERP_SIZE)) != 0) {
+				    MSG_ARG_T_INTERP_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
@@ -437,15 +487,15 @@
 				/* Translate --entry <optarg> to -e <optarg> */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'e',
 				    MSG_ORIG(MSG_ARG_T_ENTRY),
-				    MSG_ARG_T_ENTRY_SIZE)) != 0) {
+				    MSG_ARG_T_ENTRY_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				/*
 				 * Translate --end-group to -z rescan-end
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv,
-				    arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_ENDGROUP), 0)) != 0) {
+				    arg, 'z', MSG_ORIG(MSG_ARG_T_ENDGROUP),
+				    0, NULL)) != 0) {
 					optarg = (char *)
 					    MSG_ORIG(MSG_ARG_RESCAN_END);
 					return (c);
@@ -455,14 +505,15 @@
 				/* Translate --filter <optarg> to -F <optarg> */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'F',
 				    MSG_ORIG(MSG_ARG_T_STDFLTR),
-				    MSG_ARG_T_STDFLTR_SIZE)) != 0) {
+				    MSG_ARG_T_STDFLTR_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
 			case 'h':
 				/* Translate --help to -zhelp */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_HELP), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_HELP), 0, NULL)) !=
+				    0) {
 					optarg = (char *)MSG_ORIG(MSG_ARG_HELP);
 					return (c);
 				}
@@ -473,7 +524,7 @@
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'l',
 				    MSG_ORIG(MSG_ARG_T_LIBRARY),
-				    MSG_ARG_T_LIBRARY_SIZE)) != 0) {
+				    MSG_ARG_T_LIBRARY_SIZE, NULL)) != 0) {
 					return (c);
 
 				/*
@@ -482,14 +533,15 @@
 				 */
 				} else if ((c = str2chr(lml, ndx, argc, argv,
 				    arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH),
-				    MSG_ARG_T_LIBPATH_SIZE)) != 0) {
+				    MSG_ARG_T_LIBPATH_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
 			case 'n':
 				/* Translate --no-undefined to -zdefs */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_NOUNDEF), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_NOUNDEF), 0, NULL)) !=
+				    0) {
 					optarg = (char *)MSG_ORIG(MSG_ARG_DEFS);
 					return (c);
 
@@ -498,8 +550,8 @@
 				 * -z defaultextract
 				 */
 				} else if ((c = str2chr(lml, ndx, argc, argv,
-				    arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_NOWHOLEARC), 0)) != 0) {
+				    arg, 'z', MSG_ORIG(MSG_ARG_T_NOWHOLEARC),
+				    0, NULL)) != 0) {
 					optarg =
 					    (char *)MSG_ORIG(MSG_ARG_DFLEXTRT);
 					return (c);
@@ -509,29 +561,31 @@
 				/* Translate --output <optarg> to -o <optarg> */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'o',
 				    MSG_ORIG(MSG_ARG_T_OUTPUT),
-				    MSG_ARG_T_OUTPUT_SIZE)) != 0) {
+				    MSG_ARG_T_OUTPUT_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
 			case 'r':
 				/* Translate --relocatable to -r */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'r',
-				    MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0,
+				    NULL)) != 0) {
 					return (c);
 				}
 				break;
 			case 's':
 				/* Translate --strip-all to -s */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 's',
-				    MSG_ORIG(MSG_ARG_T_STRIP), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_STRIP), 0, NULL)) !=
+				    0) {
 					return (c);
 				}
 				/*
 				 * Translate --start-group to -z rescan-start
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv,
-				    arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_STARTGROUP), 0)) != 0) {
+				    arg, 'z', MSG_ORIG(MSG_ARG_T_STARTGROUP),
+				    0, NULL)) != 0) {
 					optarg = (char *)
 					    MSG_ORIG(MSG_ARG_RESCAN_START);
 					return (c);
@@ -544,14 +598,15 @@
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'u',
 				    MSG_ORIG(MSG_ARG_T_UNDEF),
-				    MSG_ARG_T_UNDEF_SIZE)) != 0) {
+				    MSG_ARG_T_UNDEF_SIZE, NULL)) != 0) {
 					return (c);
 				}
 				break;
 			case 'v':
 				/* Translate --version to -V */
 				if ((c = str2chr(lml, ndx, argc, argv, arg, 'V',
-				    MSG_ORIG(MSG_ARG_T_VERSION), 0)) != 0) {
+				    MSG_ORIG(MSG_ARG_T_VERSION), 0, NULL)) !=
+				    0) {
 					return (c);
 				}
 				break;
@@ -560,17 +615,27 @@
 				 * Translate --whole-archive to -z alltextract
 				 */
 				if ((c = str2chr(lml, ndx, argc, argv,
-				    arg, 'z',
-				    MSG_ORIG(MSG_ARG_T_WHOLEARC), 0)) != 0) {
+				    arg, 'z', MSG_ORIG(MSG_ARG_T_WHOLEARC),
+				    0, NULL)) != 0) {
 					optarg =
 					    (char *)MSG_ORIG(MSG_ARG_ALLEXTRT);
 					return (c);
 				}
+				/*
+				 * Translate --wrap to -z wrap=
+				 */
+				if ((c = str2chr(lml, ndx, argc, argv,
+				    arg, 'z', MSG_ORIG(MSG_ARG_T_WRAP),
+				    MSG_ARG_T_WRAP_SIZE, str2chr_wrap_cb)) !=
+				    0) {
+					return (c);
+				}
 				break;
 			}
 			break;
 		}
 	}
+
 	if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) {
 		/*
 		 * It is possible that a "-Wl," argument has been used to
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/sgs/libld/common/wrap.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "msg.h"
+#include "_libld.h"
+
+/*
+ * GNU ld --wrap support, also known as -z wrap.
+ *
+ * We maintain an AVL tree of wrapped symbol names. Every undefined
+ * symbol is tested against this tree, and those that match have
+ * their names modified to produce the wrapping effect:
+ *
+ * -	An undefined reference to XXX is converted to __wrap_XXX
+ * -	An undefined reference to __real_XXX is converted to XXX
+ *
+ * This operation has a cost, but that is mitigated by two factors:
+ *
+ * -	This is a test feature, not used for production code, so somewhat
+ *	longer link times are tolerable.
+ * -	The cost of this feature is only paid when it is used. Otherwise,
+ *	the sole overhead is the cost of testing the NULL AVL tree pointer
+ *	during symbol processing.
+ */
+
+
+/*
+ * AVL comparison function for WrapSymNode items.
+ *
+ * entry:
+ *	n1, n2 - pointers to nodes to be compared
+ *
+ * exit:
+ *	Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
+ */
+static int
+wrap_cmp(const void *n1, const void *n2)
+{
+	int		rc;
+
+	rc = strcmp(((WrapSymNode *)n1)->wsn_name,
+	    ((WrapSymNode *)n2)->wsn_name);
+
+	if (rc > 0)
+		return (1);
+	if (rc < 0)
+		return (-1);
+	return (0);
+}
+
+/*
+ * Enter a -z wrap symbol into the ofl_wrap AVL tree
+ *
+ * entry:
+ *	ofl - Output file descriptor
+ *	name - Name of symbol to be entered. Caller must ensure that
+ *		memory used to hold name remains available for the life
+ *		of the link-edit process.
+ *
+ * exit:
+ *	On success, updates ofl->wrap_cache with a pointer to the
+ *	resulting WrapSymNode, and returns that pointer. On failure,
+ *	returns NULL.
+ */
+WrapSymNode *
+ld_wrap_enter(Ofl_desc *ofl, const char *name)
+{
+	WrapSymNode	*wsnp, wsn;
+	avl_index_t	where;
+	size_t		name_len, wrapname_len;
+	char		*tmpname;
+
+	/* If this is the first wrap symbol, create the AVL tree */
+	if (ofl->ofl_wrap == NULL) {
+		ofl->ofl_wrap = libld_calloc(1, sizeof (*ofl->ofl_wrap));
+		if (ofl->ofl_wrap == NULL)
+			return (NULL);
+		avl_create(ofl->ofl_wrap, wrap_cmp, sizeof (WrapSymNode),
+		    SGSOFFSETOF(WrapSymNode, wsn_avlnode));
+	}
+
+	/* Have we already entered this one? */
+	wsn.wsn_name = name;
+	if ((wsnp = avl_find(ofl->ofl_wrap, &wsn, &where)) != NULL)
+		return (wsnp);
+
+	/*
+	 * Allocate a new node, along with room for the wrapped name.
+	 * Since strings have byte alignment, we can allocate it immediately
+	 * following the AVL node without the need for alignment padding.
+	 */
+	name_len = strlen(wsn.wsn_name);
+	wrapname_len = MSG_STR_UU_WRAP_U_SIZE + name_len + 1;
+	if ((wsnp = libld_calloc(1, sizeof (*wsnp) + wrapname_len)) == NULL)
+		return (NULL);
+	wsnp->wsn_name = name;
+
+	wsnp->wsn_wrapname = tmpname = (char *)(wsnp + 1);
+	(void) snprintf(tmpname, wrapname_len, MSG_ORIG(MSG_FMT_STRCAT),
+	    MSG_ORIG(MSG_STR_UU_WRAP_U), name);
+
+	/* Insert the new node */
+	avl_insert(ofl->ofl_wrap, wsnp, where);
+	return (wsnp);
+}
--- a/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/liblddbg/common/liblddbg.msg	Mon Sep 21 11:26:40 2009 -0400
@@ -953,6 +953,7 @@
 			 discarded file=%s"
 @ MSG_SYM_DISCARD_DUP	"symbol[%d]=%s;  discarded duplicate: originates from \
 			 file=%s"
+@ MSG_SYM_WRAP		"symbol[%d]=%s renamed to %s (-z wrap)"
 
 @ MSG_SYM_AOUT		"symbol=%s;  (original AOUT name)"
 @ MSG_SYM_LOOKUP	"symbol=%s;  lookup in file=%s  [ %s ]"
--- a/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/liblddbg/common/llib-llddbg	Mon Sep 21 11:26:40 2009 -0400
@@ -404,6 +404,8 @@
 void	Dbg64_syms_updated(Ofl_desc *, Sym_desc *, const char *);
 void	Dbg32_syms_up_title(Lm_list *);
 void	Dbg64_syms_up_title(Lm_list *);
+void	Dbg32_syms_wrap(Lm_list *, Elf32_Word, const char *, const char *);
+void	Dbg64_syms_wrap(Lm_list *, Elf64_Word, const char *, const char *);
 
 void	Dbg32_util_broadcast(Rt_map *);
 void	Dbg64_util_broadcast(Rt_map *);
--- a/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/liblddbg/common/mapfile-vers	Mon Sep 21 11:26:40 2009 -0400
@@ -41,7 +41,7 @@
 # MAPFILE HEADER END
 #
 
-SUNWprivate_4.73 {
+SUNWprivate_4.74 {
 	global:
 		dbg_desc = NODIRECT;	# interposed - ld.so.1(1)
 		dbg_print = NODIRECT;	# interposed - ld(1) and ld.so.1(1)
@@ -399,6 +399,8 @@
 		Dbg64_syms_updated;
 		Dbg32_syms_up_title;
 		Dbg64_syms_up_title;
+		Dbg32_syms_wrap;
+		Dbg64_syms_wrap;
 
 		Dbg_tls_modactivity;
 		Dbg_tls_static_block;
--- a/usr/src/cmd/sgs/liblddbg/common/syms.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/liblddbg/common/syms.c	Mon Sep 21 11:26:40 2009 -0400
@@ -284,6 +284,16 @@
 }
 
 void
+Dbg_syms_wrap(Lm_list *lml, Word ndx, const char *orig_name, const char *name)
+{
+	if (DBG_NOTCLASS(DBG_C_SYMBOLS))
+		return;
+
+	dbg_print(lml, MSG_INTL(MSG_SYM_WRAP), EC_WORD(ndx),
+	    Dbg_demangle_name(orig_name), Dbg_demangle_name(name));
+}
+
+void
 Dbg_syms_sec_title(Lm_list *lml)
 {
 	if (DBG_NOTCLASS(DBG_C_SYMBOLS))
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README	Mon Sep 21 11:26:40 2009 -0400
@@ -1531,3 +1531,5 @@
 6834197 ld pukes when given an empty plate
 6516644 per-symbol filtering shouldn't be allowed in executables
 6878605 ld should accept '%' syntax when matching input SHT_PROGBITS sections
+6850768 ld option to autogenerate wrappers/interposers similar to GNU ld --wrap
+	PSARC/2009/493 ld -z wrap option
--- a/usr/src/cmd/ssh/include/config.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/ssh/include/config.h	Mon Sep 21 11:26:40 2009 -0400
@@ -279,9 +279,6 @@
 /* Define if your libraries define login() */
 /* #undef HAVE_LOGIN */
 
-/* Define if your libraries define daemon() */
-/* #undef HAVE_DAEMON */
-
 /* Define if your libraries define getpagesize() */
 #define	HAVE_GETPAGESIZE 1
 
--- a/usr/src/cmd/ssh/include/daemon.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/* $Id: daemon.h,v 1.2 2001/02/09 01:55:36 djm Exp $ */
-
-#ifndef	_DAEMON_H
-#define	_DAEMON_H
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#ifndef HAVE_DAEMON
-int daemon(int nochdir, int noclose);
-#endif /* !HAVE_DAEMON */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DAEMON_H */
--- a/usr/src/cmd/ssh/include/openbsd-compat.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/ssh/include/openbsd-compat.h	Mon Sep 21 11:26:40 2009 -0400
@@ -44,7 +44,6 @@
 #include "strlcat.h"
 #include "strmode.h"
 #include "mktemp.h"
-#include "daemon.h"
 #include "dirname.h"
 #include "base64.h"
 #include "sigact.h"
--- a/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/ssh/libopenbsd-compat/Makefile.com	Mon Sep 21 11:26:40 2009 -0400
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # cmd/ssh/libopenbsd-compat/Makefile.com
@@ -41,7 +41,6 @@
 		xmmap.o \
 		base64.o \
 		bindresvport.o \
-		daemon.o \
 		dirname.o \
 		getcwd.o \
 		getgrouplist.o \
--- a/usr/src/cmd/ssh/libopenbsd-compat/common/daemon.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  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 the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "includes.h"
-
-#ifndef HAVE_DAEMON
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: daemon.c,v 1.2 1996/08/19 08:22:13 tholo Exp $";
-#endif /* LIBC_SCCS and not lint */
-
-int
-daemon(nochdir, noclose)
-	int nochdir, noclose;
-{
-	int fd;
-
-	switch (fork()) {
-	case -1:
-		return (-1);
-	case 0:
-#ifdef HAVE_CYGWIN
-		register_9x_service();
-#endif
-		break;
-	default:
-#ifdef HAVE_CYGWIN
-		/*
-		 * This sleep avoids a race condition which kills the
-		 * child process if parent is started by a NT/W2K service.
-		 */
-		sleep(1);
-#endif
-		_exit(0);
-	}
-
-	if (setsid() == -1)
-		return (-1);
-
-	if (!nochdir)
-		(void)chdir("/");
-
-	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
-		(void)dup2(fd, STDIN_FILENO);
-		(void)dup2(fd, STDOUT_FILENO);
-		(void)dup2(fd, STDERR_FILENO);
-		if (fd > 2)
-			(void)close (fd);
-	}
-	return (0);
-}
-
-#endif /* !HAVE_DAEMON */
-
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
--- a/usr/src/cmd/ssh/libopenbsd-compat/common/llib-lopenbsd-compat	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/ssh/libopenbsd-compat/common/llib-lopenbsd-compat	Mon Sep 21 11:26:40 2009 -0400
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,7 +38,6 @@
 #include <bsd-waitpid.h>
 #include <config.h>
 #include <crc32.h>
-#include <daemon.h>
 #include <deattack.h>
 #include <defines.h>
 #include <dirname.h>
--- a/usr/src/cmd/ssh/libssh/common/llib-lssh	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/ssh/libssh/common/llib-lssh	Mon Sep 21 11:26:40 2009 -0400
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -53,7 +53,6 @@
 #include <compress.h>
 #include <config.h>
 #include <crc32.h>
-#include <daemon.h>
 #include <deattack.h>
 #include <defines.h>
 #include <dh.h>
--- a/usr/src/cmd/uadmin/uadmin.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/cmd/uadmin/uadmin.c	Mon Sep 21 11:26:40 2009 -0400
@@ -67,10 +67,6 @@
 	adt_event_data_t *event = NULL; /* event to be generated */
 	au_event_t event_id;
 	enum adt_uadmin_fcn fcn_id;
-#ifdef	__i386
-	uint8_t boot_config = 0;
-#endif /* __i386 */
-
 
 	if (argc < 3 || argc > 4) {
 		(void) fprintf(stderr, Usage, argv[0]);
@@ -208,10 +204,16 @@
 		}
 #ifdef	__i386
 	} else if (cmd == A_CONFIG) {
+		uint8_t boot_config = 0;
+		uint8_t boot_config_ovr = 0;
+
 		switch (fcn) {
 		case AD_UPDATE_BOOT_CONFIG:
 			fcn_id = ADT_UADMIN_FCN_AD_UPDATE_BOOT_CONFIG;
 			scf_get_boot_config(&boot_config);
+			boot_config_ovr = boot_config;
+			scf_get_boot_config_ovr(&boot_config_ovr);
+			boot_config &= boot_config_ovr;
 			mdep = (uintptr_t)(&boot_config);
 			break;
 		}
--- a/usr/src/common/zfs/zfs_prop.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/common/zfs/zfs_prop.c	Mon Sep 21 11:26:40 2009 -0400
@@ -335,6 +335,10 @@
 	    ZFS_TYPE_DATASET, "GUID");
 	register_hidden(ZFS_PROP_USERACCOUNTING, "useraccounting",
 	    PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, NULL);
+	register_hidden(ZFS_PROP_UNIQUE, "unique", PROP_TYPE_NUMBER,
+	    PROP_READONLY, ZFS_TYPE_DATASET, NULL);
+	register_hidden(ZFS_PROP_OBJSETID, "objsetid", PROP_TYPE_NUMBER,
+	    PROP_READONLY, ZFS_TYPE_DATASET, "OBJSETID");
 
 	/* oddball properties */
 	register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0, NULL,
--- a/usr/src/head/stdlib.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/head/stdlib.h	Mon Sep 21 11:26:40 2009 -0400
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -30,8 +30,6 @@
 #ifndef _STDLIB_H
 #define	_STDLIB_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.22	*/
-
 #include <iso/stdlib_iso.h>
 #include <iso/stdlib_c99.h>
 
@@ -215,6 +213,7 @@
 #if defined(__EXTENSIONS__) || \
 	(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
 extern void closefrom(int);
+extern int daemon(int, int);
 extern int dup2(int, int);
 extern int fdwalk(int (*)(void *, int), void *);
 extern char *qecvt(long double, int, int *, int *);
@@ -317,6 +316,7 @@
 
 #if defined(__EXTENSIONS__) || !defined(__XOPEN_OR_POSIX)
 extern void closefrom();
+extern int daemon();
 extern int dup2();
 extern int fdwalk();
 extern char *qecvt();
--- a/usr/src/lib/libc/amd64/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -378,6 +378,7 @@
 	csetlen.o		\
 	ctime.o			\
 	ctime_r.o		\
+	daemon.o		\
 	deflt.o			\
 	directio.o		\
 	dirname.o		\
--- a/usr/src/lib/libc/amd64/gen/proc64_id.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/proc64_id.c	Mon Sep 21 11:26:40 2009 -0400
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright (c) 2008, Intel Corporation.
+ * Copyright (c) 2009, Intel Corporation.
  * All rights reserved.
  */
 
@@ -226,6 +226,7 @@
 		if (cpuid_info.edx & CPUID_INTC_EDX_SSE2) {
 			use_sse |= USE_SSE2;
 		}
+		use_sse |= USE_BSF;
 		__intel_set_memops_method(use_sse);
 	} else {
 		__set_cache_sizes(INTEL_DFLT_L1_CACHE_SIZE,
--- a/usr/src/lib/libc/amd64/gen/proc64_id.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/proc64_id.h	Mon Sep 21 11:26:40 2009 -0400
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright (c) 2008, Intel Corporation
+ * Copyright (c) 2009, Intel Corporation
  * All rights reserved.
  */
 
@@ -38,7 +38,7 @@
 #endif
 
 /*
- * Defines to determine what SSE instructions can be used for memops or strops.
+ * Defines to determine what SSE instructions can be used for memops or strops
  */
 #define	NO_SSE		0x00	/* Default -- Don't use SSE instructions */
 #define	USE_SSE2	0x01	/* SSE2 */
@@ -46,6 +46,7 @@
 #define	USE_SSSE3	0x04	/* Supplemental SSE3 */
 #define	USE_SSE4_1	0x08	/* SSE 4.1 */
 #define	USE_SSE4_2	0x10	/* SSE 4.2 */
+#define	USE_BSF		0x20	/* USE BSF class of instructions */
 
 /*
  * Cache size defaults for Core 2 Duo
--- a/usr/src/lib/libc/amd64/gen/proc64_support.s	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/proc64_support.s	Mon Sep 21 11:26:40 2009 -0400
@@ -25,7 +25,7 @@
  */
 
 /*
- * Copyright (c) 2008, Intel Corporation
+ * Copyright (c) 2009, Intel Corporation
  * All rights reserved.
  */
 
@@ -38,8 +38,6 @@
  * cache size information. Cache information used by memset, strcpy, etc..
  */
 
-	.file	"proc64_support.s"
-
 #include <sys/asm_linkage.h>
 #include "proc64_id.h"
 
--- a/usr/src/lib/libc/amd64/gen/strcmp.s	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/strcmp.s	Mon Sep 21 11:26:40 2009 -0400
@@ -1,540 +1,2049 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
  */
 
 /*
- * Copyright (c) 2002 Advanced Micro Devices, Inc.
- * 
+ * Copyright (c) 2009, Intel Corporation
  * All rights reserved.
- * 
- * Redistribution and  use in source and binary  forms, with or
- * without  modification,  are   permitted  provided  that  the
- * following conditions are met:
- * 
- * + Redistributions  of source  code  must  retain  the  above
- *   copyright  notice,   this  list  of   conditions  and  the
- *   following disclaimer.
- * 
- * + 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.
- * 
- * + Neither the  name of Advanced Micro Devices,  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  ADVANCED  MICRO  DEVICES,
- * INC.  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.
- * 
- * It is  licensee's responsibility  to comply with  any export
- * regulations applicable in licensee's jurisdiction.
  */
 
-	.file	"strcmp.s"
+/*
+ *	str[n]cmp - compare chars between two string
+ */
 
 #include "SYS.h"
-#include "cache.h"
+#include "proc64_id.h"
 
 #define LABEL(s) .strcmp/**/s
 
 #ifdef USE_AS_STRNCMP
+	/*
+	 * Since the counter, %r11, is unsigned, we branch to strcmp_exitz
+	 * if the new counter > the old one or is 0. 
+	 */
+#define UPDATE_STRNCMP_COUNTER				\
+	/* calculate left number to compare */		\
+	lea	-16(%rcx, %r11), %r9;			\
+	cmp	%r9, %r11;				\
+	jb	LABEL(strcmp_exitz);			\
+	test	%r9, %r9;				\
+	je	LABEL(strcmp_exitz);			\
+	mov	%r9, %r11
+#else
+#define UPDATE_STRNCMP_COUNTER
+#endif
+
+	/*
+	 * This implementation uses SSE to compare up to 16 bytes at a time.
+	 */
+#ifdef USE_AS_STRNCMP
 	ENTRY(strncmp)
+	test	%rdx, %rdx
+	je	LABEL(strcmp_exitz)
+	mov	%rdx, %r11
 #else
 	ENTRY(strcmp)			/* (const char *, const char *) */
 #endif
-        xor     %ecx, %ecx
+	mov	%esi, %ecx
+	mov	%edi, %eax
+	and	$0x3f, %rcx		/* rsi alignment in cache line */
+	and	$0x3f, %rax		/* rdi alignment in cache line */
+	cmp	$0x30, %ecx
+	ja	LABEL(crosscache)	/* rsi: 16-byte load will cross cache line */
+	cmp	$0x30, %eax
+	ja	LABEL(crosscache)	/* rdi: 16-byte load will cross cache line */
+	movlpd	(%rdi), %xmm1
+	movlpd	(%rsi), %xmm2
+	movhpd	8(%rdi), %xmm1
+	movhpd	8(%rsi), %xmm2
+	pxor	%xmm0, %xmm0		/* clear %xmm0 for null char checks */
+	pcmpeqb	%xmm1, %xmm0		/* Any null chars? */
+	pcmpeqb	%xmm2, %xmm1		/* compare first 16 bytes for equality */
+	psubb	%xmm0, %xmm1		/* packed sub of comparison results*/
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx		/* if first 16 bytes are same, edx == 0xffff */
+	jnz	LABEL(less16bytes)	/* If not, found mismatch or null char */
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)	/* finish comparision */
+#endif
+	add	$16, %rsi		/* prepare to search next 16 bytes */
+	add	$16, %rdi		/* prepare to search next 16 bytes */
+
+	/*
+	 * Determine rdi and rsi string offsets from 16-byte alignment.
+	 * Use relative offset difference between the two to determine which case
+	 * below to use.
+	 */
+	.p2align 4
+LABEL(crosscache):
+	and	$0xfffffffffffffff0, %rsi	/* force %rsi to be 16 byte aligned */
+	and	$0xfffffffffffffff0, %rdi	/* force %rdi to be 16 byte aligned */
+	mov	$0xffff, %edx			/* for equivalent offset */
+	xor	%r8d, %r8d
+	and	$0xf, %ecx			/* offset of rsi */
+	and	$0xf, %eax			/* offset of rdi */
+	cmp	%eax, %ecx
+	je	LABEL(ashr_0)			/* both strings have the same alignment */
+	ja	LABEL(bigger)
+	mov	%edx, %r8d			/* r8d is offset flag for exit tail */
+	xchg	%ecx, %eax
+	xchg	%rsi, %rdi
+LABEL(bigger):
+	mov	%rcx, %r9
+	sub	%rax, %r9
+	lea	LABEL(unaligned_table)(%rip), %r10
+	movslq	(%r10, %r9, 4), %r9
+	lea	(%r10, %r9), %r10
+	jmp	*%r10				/* jump to corresponding case */
+
+/*
+ * ashr_0 handles the following cases:
+ * 	str1 offset = str2 offset
+ */
+	.p2align 4
+LABEL(ashr_0):
+	movdqa	(%rsi), %xmm1
+	pxor	%xmm0, %xmm0			/* clear %xmm0 for null char check */
+	pcmpeqb	%xmm1, %xmm0			/* Any null chars? */
+	pcmpeqb	(%rdi), %xmm1			/* compare 16 bytes for equality */
+	psubb	%xmm0, %xmm1			/* packed sub of comparison results*/
+	pmovmskb %xmm1, %r9d
+	shr	%cl, %edx			/* adjust 0xffff for offset */
+	shr	%cl, %r9d			/* adjust for 16-byte offset */
+	sub	%r9d, %edx
+	/*
+	 * edx must be the same with r9d if in left byte (16-rcx) is equal to
+	 * the start from (16-rax) and no null char was seen.
+	 */
+	jne	LABEL(less32bytes)		/* mismatch or null char */
+	UPDATE_STRNCMP_COUNTER
+	mov	$16, %rcx
+	mov	$16, %r9
+	pxor	%xmm0, %xmm0			/* clear xmm0, may have changed above */
+
+	/*
+	 * Now both strings are aligned at 16-byte boundary. Loop over strings
+	 * checking 32-bytes per iteration.
+	 */
+	.p2align 4
+LABEL(loop_ashr_0):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)		/* mismatch or null char seen */
 
 #ifdef USE_AS_STRNCMP
-	test	%rdx, %rdx		/* (const char *, const char *, size_t) */
-        mov	%r14, -8 (%rsp)
-	mov	%rdx, %r14
-	mov	%edx, %eax
-	jz	LABEL(exitz)		/* early exit */
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
+	add	$16, %rcx
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	add	$16, %rcx
+	jmp	LABEL(loop_ashr_0)
 
-LABEL(aligntry):
-        mov     %rsi, %r8		/* align by "source" */
-        and     $8 - 1, %r8		/* between 0 and 8 characters compared */
-	jz	LABEL(alignafter)
+/*
+ * ashr_1 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 15
+ */
+	.p2align 4
+LABEL(ashr_1):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0		/* Any null chars? */
+	pslldq	$15, %xmm2		/* shift first string to align with second */	
+	pcmpeqb	%xmm1, %xmm2		/* compare 16 bytes for equality */
+	psubb	%xmm0, %xmm2		/* packed sub of comparison results*/
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx		/* adjust 0xffff for offset */
+	shr	%cl, %r9d		/* adjust for 16-byte offset */
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)	/* mismatch or null char seen */
+	movdqa	(%rdi), %xmm3
+	UPDATE_STRNCMP_COUNTER
 
-LABEL(align):
-        sub     $8, %r8
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx		/* index for loads */	
+	mov	$1, %r9d		/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	1(%rdi), %r10	 
+	and	$0xfff, %r10		/* offset into 4K page */
+	sub	$0x1000, %r10		/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-        .p2align 4
+	.p2align 4
+LABEL(loop_ashr_1):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_1)	/* cross page boundary */	
+
+LABEL(gobble_ashr_1):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4		 /* store for next cycle */
 
-LABEL(alignloop):
-        mov     (%rsi, %rcx), %al
-        mov	(%rdi, %rcx), %dl
+	psrldq	$1, %xmm3		
+	pslldq	$15, %xmm2		
+	por	%xmm3, %xmm2		/* merge into one 16byte value */
+
+	pcmpeqb	%xmm1, %xmm0	
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exitafter)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_1)	/* cross page boundary */	
 
-        cmp     %dl, %al		/* check if same character */
-        jne     LABEL(exitafter)
-        test    %al, %al		/* check if character a NUL */
-        jz      LABEL(exitafter)
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4		/* store for next cycle */
 
-        inc     %ecx
+	psrldq	$1, %xmm3			
+	pslldq 	$15, %xmm2		
+	por	%xmm3, %xmm2		/* merge into one 16byte value */
 
-        inc     %r8
-        jnz     LABEL(alignloop)
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-        test	%r14, %r14
-        jz	LABEL(exitafter)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3		
+	jmp	LABEL(loop_ashr_1)		
+
+	/*
+	 * Nibble avoids loads across page boundary. This is to avoid a potential
+	 * access into unmapped memory.
+	 */
+	.p2align 4
+LABEL(nibble_ashr_1):
+	psrldq	$1, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x7fff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$15, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_1)	
+
+/*
+ * ashr_2 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 14
+ */
+	.p2align 4
+LABEL(ashr_2):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$14, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$2, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	2(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_2):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_2)	
+
+LABEL(gobble_ashr_2):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$2, %xmm3		
+	pslldq	$14, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0	
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        .p2align 4
-
-LABEL(alignafter):
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
 
-        mov	%r15, -32 (%rsp)
-        mov	%rbp, -24 (%rsp)
-        mov	%rbx, -16 (%rsp)
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_2)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-LABEL(pagealigntry):			/* page align by "destination" */
-        lea	(%rdi, %rcx), %ebp
-	mov	$AMD64PAGESIZE, %r15d
-        and     $AMD64PAGEMASK, %ebp
-        sub	%r15d, %ebp
-	/*
-	 * When we go to 64gobble, %ebp was adjusted at the top of 64loop.
-	 * When we go to 64nibble(crossing page boundary), we'll compare
-	 * 128 byte since we'll fall through to 64gobble. Therefore, %ebp
-	 * needs to be re-adjusted(add 64) when we fall into 64nibble.
-	 * It can be done by adjusting %r15 since %r15 is only used to
-	 * rewind %ebp when crossing page boundary.
-	 */
-	sub	$64, %r15d
+	psrldq	$2, %xmm3			
+	pslldq 	$14, %xmm2		
+	por	%xmm3, %xmm2
 
-LABEL(64):                              /* 64-byte */
-	mov     $0xfefefefefefefeff, %rbx /* magic number */
-
-        .p2align 4
-
-LABEL(64loop):
-	add	$64, %ebp		/* check if "destination" crosses a page unevenly */
-	jle	LABEL(64gobble)
-
-        sub	%r15d, %ebp
-        lea	64 (%rcx), %r8
-
-        .p2align 4
-
-LABEL(64nibble):
-        mov     (%rsi, %rcx), %al
-        mov	(%rdi, %rcx), %dl
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jle	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al		/* check if same character */
-        jne     LABEL(exit)
-        test    %al, %al		/* check if character a NUL */
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
+	jmp	LABEL(loop_ashr_2)		
 
-        inc	%ecx
+	.p2align 4
+LABEL(nibble_ashr_2):
+	psrldq	$2, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x3fff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$14, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_2)	
 
-        cmp	%ecx, %r8d
-        ja	LABEL(64nibble)
+/*
+ * ashr_3 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 13
+ */
+	.p2align 4
+LABEL(ashr_3):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$13, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        .p2align 4
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$3, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	3(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-LABEL(64gobble):
-        mov     (%rsi, %rcx), %rax
-        mov     (%rdi, %rcx), %rdx
+	.p2align 4
+LABEL(loop_ashr_3):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_3)	
+
+LABEL(gobble_ashr_3):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$3, %xmm3		
+	pslldq	$13, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_3)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$3, %xmm3			
+	pslldq 	$13, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_3)		
+
+	.p2align 4
+LABEL(nibble_ashr_3):
+	psrldq	$3, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x1fff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$13, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_3)	
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+/*
+ * ashr_4 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 12
+ */
+	.p2align 4
+LABEL(ashr_4):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$12, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$4, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	4(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_4):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_4)	
+
+LABEL(gobble_ashr_4):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$4, %xmm3		
+	pslldq	$12, %xmm2		
+	por	%xmm3, %xmm2
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_4)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$4, %xmm3			
+	pslldq 	$12, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_4)		
+
+	.p2align 4
+LABEL(nibble_ashr_4):
+	psrldq	$4, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x0fff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$12, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_4)	
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+/*
+ * ashr_5 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 11
+ */
+	.p2align 4
+LABEL(ashr_5):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$11, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$5, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	5(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_5):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_5)	
+
+LABEL(gobble_ashr_5):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$5, %xmm3		
+	pslldq	$11, %xmm2		
+	por	%xmm3, %xmm2
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_5)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$5, %xmm3			
+	pslldq 	$11, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_5)		
+
+	.p2align 4
+LABEL(nibble_ashr_5):
+	psrldq	$5, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x07ff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$11, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_5)	
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+/*
+ * ashr_6 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 10
+ */
+	.p2align 4
+LABEL(ashr_6):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$10, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$6, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	6(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_6):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_6)	
+
+LABEL(gobble_ashr_6):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$6, %xmm3		
+	pslldq	$10, %xmm2		
+	por	%xmm3, %xmm2
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_6)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$6, %xmm3			
+	pslldq 	$10, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
+	jmp	LABEL(loop_ashr_6)		
+
+	.p2align 4
+LABEL(nibble_ashr_6):
+	psrldq	$6, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x03ff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$10, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_6)	
+
+/*
+ * ashr_7 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 9
+ */
+	.p2align 4
+LABEL(ashr_7):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$9, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$7, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	7(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_7):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_7)	
+
+LABEL(gobble_ashr_7):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$7, %xmm3		
+	pslldq	$9, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_7)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+	psrldq	$7, %xmm3			
+	pslldq 	$9, %xmm2		
+	por	%xmm3, %xmm2
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
-
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
-
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_7)		
+
+	.p2align 4
+LABEL(nibble_ashr_7):
+	psrldq	$7, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x01ff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$9, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_7)	
+
+/*
+ * ashr_8 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 8
+ */
+	.p2align 4
+LABEL(ashr_8):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$8, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$8, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	8(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_8):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_8)	
+
+LABEL(gobble_ashr_8):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$8, %xmm3		
+	pslldq	$8, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3	
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_8)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$8, %xmm3			
+	pslldq 	$8, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_8)		
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+	.p2align 4
+LABEL(nibble_ashr_8):
+	psrldq	$8, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x00ff, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$8, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_8)	
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+/*
+ * ashr_9 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 7
+ */
+	.p2align 4
+LABEL(ashr_9):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$7, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$9, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	9(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	.p2align 4
+LABEL(loop_ashr_9):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_9)	
+
+LABEL(gobble_ashr_9):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$9, %xmm3		
+	pslldq	$7, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_9)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$9, %xmm3			
+	pslldq 	$7, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3		/* store for next cycle */
+	jmp	LABEL(loop_ashr_9)		
+
+	.p2align 4
+LABEL(nibble_ashr_9):
+	psrldq	$9, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x007f, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$7, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_9)	
+
+/*
+ * ashr_10 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 6
+ */
+	.p2align 4
+LABEL(ashr_10):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$6, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$10, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	10(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_10):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_10)	
+
+LABEL(gobble_ashr_10):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$10, %xmm3		
+	pslldq	$6, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_10)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$10, %xmm3			
+	pslldq 	$6, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_10)		
+
+	.p2align 4
+LABEL(nibble_ashr_10):
+	psrldq	$10, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x003f, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$6, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_10)	
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+/*
+ * ashr_11 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 5
+ */
+	.p2align 4
+LABEL(ashr_11):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$5, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$11, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	11(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	.p2align 4
+LABEL(loop_ashr_11):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_11)	
+
+LABEL(gobble_ashr_11):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$11, %xmm3		
+	pslldq	$5, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_11)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$11, %xmm3			
+	pslldq 	$5, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_11)		
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
+	.p2align 4
+LABEL(nibble_ashr_11):
+	psrldq	$11, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x001f, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$5, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_11)	
 
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+/*
+ * ashr_12 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 4
+ */
+	.p2align 4
+LABEL(ashr_12):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$4, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$12, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	12(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
+	.p2align 4
+LABEL(loop_ashr_12):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_12)	
+
+LABEL(gobble_ashr_12):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        mov     8 (%rsi, %rcx), %rax
-        mov     8 (%rdi, %rcx), %rdx
-        add     $8, %ecx
+	psrldq	$12, %xmm3		
+	pslldq	$4, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0	
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	sub	$8, %r14
-	jle	LABEL(tail)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_12)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$12, %xmm3			
+	pslldq 	$4, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
+#ifdef USE_AS_STRNCMP
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        mov     %rbx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_12)		
 
-        mov     %rbx, %r9
-        add     %rdx, %r9
-        sbb     %r11, %r11
-
-        xor     %rax, %r8
-        or      %rbx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
+	.p2align 4
+LABEL(nibble_ashr_12):
+	psrldq	$12, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x000f, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$4, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_12)	
 
-        xor     %rdx, %r9
-        or      %rbx, %r9
-        sub     %r11, %r9
-        jnz     LABEL(tail)
+/*
+ * ashr_13 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 3
+ */
+	.p2align 4
+LABEL(ashr_13):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$3, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
 
-        cmp     %rdx, %rax
-        jne     LABEL(tail)
-
-        add	$8, %ecx
+	UPDATE_STRNCMP_COUNTER
 
-        jmp	LABEL(64loop)
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$13, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	13(%rdi), %r10	 
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
 
-LABEL(64after):
+	.p2align 4
+LABEL(loop_ashr_13):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_13)	
 
-LABEL(tailtry):
+LABEL(gobble_ashr_13):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$13, %xmm3		
+	pslldq	$3, %xmm2		
+	por	%xmm3, %xmm2
 
-LABEL(tail):				/* byte tail */
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
+
 #ifdef USE_AS_STRNCMP
-	add	$7, %r14
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al		/* check if same character */
-        jne     LABEL(exit)
-        test    %al, %al		/* check if character a NUL */
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_13)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        shr	$8, %rax
-        shr	$8, %rdx
+	psrldq	$13, %xmm3			
+	pslldq 	$3, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_13)		
+	
+	.p2align 4
+LABEL(nibble_ashr_13):
+	psrldq	$13, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x0007, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$3, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_13)	
 
-        shr	$8, %rax
-        shr	$8, %rdx
+/*
+ * ashr_14 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 2
+ */
+	.p2align 4
+LABEL(ashr_14):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq  $2, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$14, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	14(%rdi), %r10  
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_14):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_14)	
+
+LABEL(gobble_ashr_14):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$14, %xmm3		
+	pslldq	$2, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_14)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        shr	$8, %rax
-        shr	$8, %rdx
+	psrldq	$14, %xmm3			
+	pslldq 	$2, %xmm2		
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_14)		
+
+	.p2align 4
+LABEL(nibble_ashr_14):
+	psrldq	$14, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x0003, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$2, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_14)	
 
-        shr	$8, %rax
-        shr	$8, %rdx
+/*
+ * ashr_15 handles the following cases: 
+ * 	abs(str1 offset - str2 offset) = 1
+ */
+	.p2align 4
+LABEL(ashr_15):
+	pxor	%xmm0, %xmm0
+	movdqa	(%rdi), %xmm2
+	movdqa	(%rsi), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pslldq	$1, %xmm2		
+	pcmpeqb	%xmm1, %xmm2
+	psubb	%xmm0, %xmm2
+	pmovmskb %xmm2, %r9d
+	shr	%cl, %edx
+	shr	%cl, %r9d
+	sub	%r9d, %edx
+	jnz	LABEL(less32bytes)
+
+	movdqa	(%rdi), %xmm3
+
+	UPDATE_STRNCMP_COUNTER
+
+	pxor	%xmm0, %xmm0
+	mov	$16, %rcx	/* index for loads */
+	mov	$15, %r9d	/* rdi bytes already examined. Used in exit code */
+	/*
+	 * Setup %r10 value allows us to detect crossing a page boundary.
+	 * When %r10 goes positive we are crossing a page boundary and
+	 * need to do a nibble.
+	 */
+	lea	15(%rdi), %r10	
+	and	$0xfff, %r10	/* offset into 4K page */
+	sub	$0x1000, %r10	/* subtract 4K pagesize */
+	movdqa	%xmm3, %xmm4
+
+	.p2align 4
+LABEL(loop_ashr_15):
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_15)
+
+LABEL(gobble_ashr_15):
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
+
+	psrldq	$15, %xmm3
+	pslldq	$1, %xmm2
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+
+	add	$16, %r10
+	jg	LABEL(nibble_ashr_15)	/* cross page boundary */
+
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	(%rdi, %rcx), %xmm2
+	movdqa	%xmm2, %xmm4
 
-        shr	$8, %eax
-        shr	$8, %edx
+	psrldq	$15, %xmm3
+	pslldq 	$1, %xmm2
+	por	%xmm3, %xmm2
+
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm2, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0xffff, %edx
+	jnz	LABEL(exit)
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$16, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	add	$16, %rcx
+	movdqa	%xmm4, %xmm3
+	jmp	LABEL(loop_ashr_15)
 
-        shr	$8, %eax
-        shr	$8, %edx
+	.p2align 4
+LABEL(nibble_ashr_15):
+	psrldq	$15, %xmm4		
+	movdqa	(%rsi, %rcx), %xmm1
+	pcmpeqb	%xmm1, %xmm0
+	pcmpeqb	%xmm4, %xmm1
+	psubb	%xmm0, %xmm1
+	pmovmskb %xmm1, %edx
+	sub	$0x0001, %edx
+	jnz	LABEL(exit)
+#ifdef USE_AS_STRNCMP
+	cmp	$1, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+ 	pxor	%xmm0, %xmm0
+	sub	$0x1000, %r10		/* subtract 4K from %r10 */
+	jmp	LABEL(gobble_ashr_15)	
+
+	.p2align 4
+LABEL(exit):
+	lea	-16(%r9, %rcx), %rax	/* locate the exact offset for rdi */
+LABEL(less32bytes):
+	lea	(%rdi, %rax), %rdi	/* locate the exact address for first operand(rdi) */
+	lea	(%rsi, %rcx), %rsi	/* locate the exact address for second operand(rsi) */
+	test	%r8d, %r8d
+	jz	LABEL(ret)
+	xchg	%rsi, %rdi		/* recover original order according to flag(%r8d) */
+
+	.p2align 4
+LABEL(ret):
+LABEL(less16bytes):
+	/*
+	 * Check to see if BSF is fast on this processor. If not, use a different
+	 * exit tail.
+	 */
+	testl	$USE_BSF,.memops_method(%rip)
+	jz	LABEL(AMD_exit)
+	bsf	%rdx, %rdx		/* find and store bit index in %rdx */	
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	%rdx, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif	
+	xor	%ecx, %ecx		/* clear %ecx */
+	xor	%eax, %eax		/* clear %eax */
+
+	movb	(%rsi, %rdx), %cl
+	movb	(%rdi, %rdx), %al
+
+	sub	%ecx, %eax
+	ret
+
+#ifdef USE_AS_STRNCMP
+LABEL(strcmp_exitz):
+	xor	%eax, %eax
+	ret
 #endif
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
-        test    %al, %al
-        jz      LABEL(exit)
+	/*
+	 * This exit tail does not use the bsf instruction.
+	 */
+	.p2align 4
+LABEL(AMD_exit):
+	test	%dl, %dl
+	jz	LABEL(next_8_bytes)
+
+	test	$0x01, %dl
+	jnz	LABEL(Byte0)
+
+	test	$0x02, %dl
+	jnz	LABEL(Byte1)
+
+	test	$0x04, %dl
+	jnz	LABEL(Byte2)
+
+	test	$0x08, %dl
+	jnz	LABEL(Byte3)
+
+	test	$0x10, %dl
+	jnz	LABEL(Byte4)
+
+	test	$0x20, %dl
+	jnz	LABEL(Byte5)
+
+	test	$0x40, %dl
+	jnz	LABEL(Byte6)
+
+#ifdef USE_AS_STRNCMP
+	sub	$7, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	7(%rsi), %ecx
+	movzx	7(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
 
-        shr	$8, %eax
-        shr	$8, %edx
+	.p2align 4
+LABEL(Byte0):
+	/*
+	 * never need to handle byte 0 for strncmpy
+#ifdef USE_AS_STRNCMP
+	sub	$0, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	*/
+	movzx	(%rsi), %ecx
+	movzx	(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
+
+	.p2align 4
+LABEL(Byte1):
+
+#ifdef USE_AS_STRNCMP
+	sub	$1, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	1(%rsi), %ecx
+	movzx	1(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
+
+	.p2align 4
+LABEL(Byte2):
+
+#ifdef USE_AS_STRNCMP
+	sub	$2, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	2(%rsi), %ecx
+	movzx	2(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
+
+	.p2align 4
+LABEL(Byte3):
 
 #ifdef USE_AS_STRNCMP
-	dec	%r14
-	jl	LABEL(exit)
+	sub	$3, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
+	movzx	3(%rsi), %ecx
+	movzx	3(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
 
-        cmp     %dl, %al
-        jne     LABEL(exit)
+	.p2align 4
+LABEL(Byte4):
 
-        .p2align 4,, 15
-
-LABEL(tailafter):
+#ifdef USE_AS_STRNCMP
+	sub	$4, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	4(%rsi), %ecx
+	movzx	4(%rdi), %eax
 
-LABEL(exit):
-	mov	-32 (%rsp), %r15
-	mov	-24 (%rsp), %rbp
-        mov	-16 (%rsp), %rbx
+	sub	%ecx, %eax
+	ret
 
-        .p2align 4,, 3
+	.p2align 4
+LABEL(Byte5):
 
-LABEL(exitafter):
 #ifdef USE_AS_STRNCMP
-	test	%r14, %r14
-	cmovl	%edx, %eax
+	sub	$5, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
+	movzx	5(%rsi), %ecx
+	movzx	5(%rdi), %eax
 
-	movzx	%al, %eax
-	movzx	%dl, %edx
-	sub	%eax, %edx
-	xchg	%edx, %eax
+	sub	%ecx, %eax
+	ret
+
+	.p2align 4
+LABEL(Byte6):
 
 #ifdef USE_AS_STRNCMP
-LABEL(exitz):
-	mov	-8 (%rsp), %r14
+	sub	$6, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	6(%rsi), %ecx
+	movzx	6(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
+
+	.p2align 4
+LABEL(next_8_bytes):
+	add	$8, %rdi
+	add	$8, %rsi
+#ifdef USE_AS_STRNCMP
+	sub	$8, %r11
+	jbe	LABEL(strcmp_exitz)
 #endif
-        ret
+	test	$0x01, %dh
+	jnz	LABEL(Byte0)
+
+	test	$0x02, %dh
+	jnz	LABEL(Byte1)
+
+	test	$0x04, %dh
+	jnz	LABEL(Byte2)
+
+	test	$0x08, %dh
+	jnz	LABEL(Byte3)
+
+	test	$0x10, %dh
+	jnz	LABEL(Byte4)
+
+	test	$0x20, %dh
+	jnz	LABEL(Byte5)
+
+	test	$0x40, %dh
+	jnz	LABEL(Byte6)
 
 #ifdef USE_AS_STRNCMP
+	sub	$7, %r11
+	jbe	LABEL(strcmp_exitz)
+#endif
+	movzx	7(%rsi), %ecx
+	movzx	7(%rdi), %eax
+
+	sub	%ecx, %eax
+	ret
+
+	.pushsection .rodata
+	.p2align 4
+LABEL(unaligned_table):
+	.int	LABEL(ashr_0) - LABEL(unaligned_table)
+	.int	LABEL(ashr_15) - LABEL(unaligned_table)
+	.int	LABEL(ashr_14) - LABEL(unaligned_table)
+	.int	LABEL(ashr_13) - LABEL(unaligned_table)
+	.int	LABEL(ashr_12) - LABEL(unaligned_table)
+	.int	LABEL(ashr_11) - LABEL(unaligned_table)
+	.int	LABEL(ashr_10) - LABEL(unaligned_table)
+	.int	LABEL(ashr_9) - LABEL(unaligned_table)
+	.int	LABEL(ashr_8) - LABEL(unaligned_table)
+	.int	LABEL(ashr_7) - LABEL(unaligned_table)
+	.int	LABEL(ashr_6) - LABEL(unaligned_table)
+	.int	LABEL(ashr_5) - LABEL(unaligned_table)
+	.int	LABEL(ashr_4) - LABEL(unaligned_table)
+	.int	LABEL(ashr_3) - LABEL(unaligned_table)
+	.int	LABEL(ashr_2) - LABEL(unaligned_table)
+	.int	LABEL(ashr_1) - LABEL(unaligned_table)
+	.popsection
+#ifdef USE_AS_STRNCMP
 	SET_SIZE(strncmp)
 #else
 	SET_SIZE(strcmp)		/* (const char *, const char *) */
--- a/usr/src/lib/libc/amd64/gen/strcpy.s	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/strcpy.s	Mon Sep 21 11:26:40 2009 -0400
@@ -1,862 +1,2582 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
  */
 
 /*
- * Copyright (c) 2002 Advanced Micro Devices, Inc.
- * 
+ * Copyright (c) 2009, Intel Corporation
  * All rights reserved.
- * 
- * Redistribution and  use in source and binary  forms, with or
- * without  modification,  are   permitted  provided  that  the
- * following conditions are met:
- * 
- * + Redistributions  of source  code  must  retain  the  above
- *   copyright  notice,   this  list  of   conditions  and  the
- *   following disclaimer.
- * 
- * + 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.
- * 
- * + Neither the  name of Advanced Micro Devices,  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  ADVANCED  MICRO  DEVICES,
- * INC.  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.
- * 
- * It is  licensee's responsibility  to comply with  any export
- * regulations applicable in licensee's jurisdiction.
  */
 
-	.file	"strcpy.s"
-
+/*
+ *	str[n]cpy - copy [n] chars from second operand into first operand
+ */
 #include "SYS.h"
-#include "cache.h"
+#include "proc64_id.h"
 
 #define LABEL(s) .strcpy/**/s
 
 #ifdef USE_AS_STRNCPY
 	ENTRY(strncpy)
+	test	%edx, %edx
+	jz	LABEL(strncpy_exitz)
+	mov	%rdx, %r8
 #else
-	ENTRY(strcpy)                        /* (char *, const char *) */
+	ENTRY(strcpy)				/* (char *, const char *) */
+	xor	%rdx, %rdx
+#endif
+	mov	%esi, %ecx
+	and	$0xfffffffffffffff0, %rsi	/* force rsi 16 byte align */
+	and	$0xf, %rcx
+	mov	%rdi, %rax			/* save destination address for return value */
+
+
+	pxor	%xmm0, %xmm0			/* clear %xmm0 for null char checks */
+	pcmpeqb	(%rsi), %xmm0			/* check 16 bytes in src for null */
+	pmovmskb %xmm0, %edx
+	shr	%cl, %edx			/* adjust for offset from 16byte boundary */
+	test	%edx, %edx			/* edx will be 0 if chars are non-null */
+	jnz	LABEL(less16bytes)		/* null char found in first 16 bytes examined */
+#ifdef USE_AS_STRNCPY
+	/*
+	 * Check if the count is satisfied in first 16 bytes examined.
+	 */
+	lea	-16(%r8, %rcx), %r11
+	cmp	$0, %r11
+	jle	LABEL(less16bytes)
+#endif
+	mov	%rcx, %r9			/* rsi alignment offset */
+	or	%edi, %ecx
+	and	$0xf, %ecx
+	lea	-16(%r9), %r10
+	jz	LABEL(ashr_0)			/* src and dest are both 16 byte aligned */
+
+	neg	%r10				/* max src bytes remaining in current dqword */
+
+	pxor	%xmm0, %xmm0			/* clear %xmm0, may be polluted by unaligned operation */
+	pcmpeqb	16(%rsi), %xmm0			/* check next 16 bytes in src for a null */
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(less32bytes)		/* null char found in first 32 bytes examined */
+
+#ifdef USE_AS_STRNCPY
+	/*
+	 * If strncpy count <= 16 go to exit case
+	 */
+	sub	$16, %r8
+	jbe	LABEL(less32bytes_strncpy_truncation)
+#endif
+	/*
+	 * At least 16 bytes to copy to destination string. Move them now.
+	 * Don't worry about alignment.
+	 */
+	mov	(%rsi, %r9), %rdx
+	mov	%rdx, (%rdi)
+	mov	8(%rsi, %r9), %rdx
+	mov	%rdx, 8(%rdi)
+
+	/*
+	 * so far destination rdi may be aligned by 16, re-calculate rsi and
+	 * jump to corresponding src/dest relative offset case.
+	 * 	rcx is offset of rsi
+	 * 	rdx is offset of rdi
+	 */
+	and	$0xfffffffffffffff0, %rdi	/* force rdi 16 byte align */
+	mov	%rax, %rdx			/* rax contains orignal rdi */
+	xor	%rdi, %rdx			/* same effect as "and $0xf, %rdx" */
+#ifdef USE_AS_STRNCPY
+	/*
+	 * Will now do 16 byte aligned stores. Stores may overlap some bytes
+	 * (ie store twice) if destination was unaligned. Compensate here.
+	 */
+	add	%rdx, %r8			/* compensate for overlap */
+#endif
+
+	add	$16, %rdi			/* next 16 bytes for dest */
+
+	/*
+	 * align src to 16-byte boundary. Could be up or down depending on
+	 * whether src offset - dest offset > 0 (up) or
+	 *  src offset - dest offset < 0 (down).
+	 */
+	sub	%rdx, %r9			/* src offset - dest offset */
+
+	lea	16(%r9, %rsi), %rsi
+	mov	%esi, %ecx			/* for new src offset */
+	and	$0xfffffffffffffff0, %rsi	/* force rsi 16 byte align */
+
+	and	$0xf, %ecx			/* new src offset is 0 if rsi/rdi have same alignment */
+	jz	LABEL(ashr_0)
+
+#ifdef USE_AS_STRNCPY
+	xor	%edx, %edx			/* In case unaligned_exit is taken */
+#endif
+	/*
+	 * Jump to case corresponding to source/dest string relative offsets
+	 * Index = (16 + (src offset - dest offset)) % 16
+	 */
+	lea	-16(%rcx), %r10
+	mov	%rcx, %r9
+	neg	%r10				/* max src bytes remaining in current dqword */
+	lea	LABEL(unaligned_table)(%rip), %r11
+	movslq	(%r11, %rcx, 4), %rcx
+	lea	(%r11, %rcx), %rcx
+	jmp	*%rcx
+
+/*
+ * ashr_0 handles the following cases:
+ * 	src alignment offset = dest alignment offset
+ */
+	.p2align 5
+LABEL(ashr_0):
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_aligned)
+#endif
+	movdqa	(%rsi), %xmm1		/* fetch 16 bytes from src string */
+	movdqa	%xmm1, (%rdi)		/* store 16 bytes into dest string */
+	add	$16, %rsi
+	add	$16, %rdi
+	pcmpeqb	(%rsi), %xmm0		/* check 16 bytes in src for a null */
+	pmovmskb %xmm0, %edx
+
+	test	%edx, %edx		/* edx will be 0 if chars are non-null */
+	jnz	LABEL(aligned_16bytes)	/* exit tail */
+
+LABEL(ashr_0_loop):
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+	jbe	LABEL(strncpy_truncation_aligned)
+#endif
+	movdqa	(%rsi, %rcx), %xmm1
+	movdqa	%xmm1, (%rdi, %rcx)
+	add	$16, %rcx
+	pcmpeqb	(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(aligned_exit)
+
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+	jbe	LABEL(strncpy_truncation_aligned)
+#endif
+	movdqa  (%rsi, %rcx), %xmm1
+	movdqa  %xmm1, (%rdi, %rcx)
+	add	$16, %rcx
+	pcmpeqb  (%rsi, %rcx), %xmm0
+	pmovmskb  %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(aligned_exit)
+
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+	jbe	LABEL(strncpy_truncation_aligned)
+#endif
+	movdqa  (%rsi, %rcx), %xmm1
+	movdqa  %xmm1, (%rdi, %rcx)
+
+	add	$16, %rcx
+	pcmpeqb  (%rsi, %rcx), %xmm0
+	pmovmskb  %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(aligned_exit)
+
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+	jbe	LABEL(strncpy_truncation_aligned)
+#endif
+	movdqa  (%rsi, %rcx), %xmm1
+	movdqa  %xmm1, (%rdi, %rcx)
+	add	$16, %rcx
+	pcmpeqb  (%rsi, %rcx), %xmm0
+	pmovmskb  %xmm0, %edx
+	test	%edx, %edx
+	jz	LABEL(ashr_0_loop)
+	jmp	LABEL(aligned_exit)
+
+
+/*
+ * ashr_15 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 15 
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_15):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_15_use_sse2)
+
+	.p2align 4
+LABEL(ashr_15_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $15, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0f
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $15, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0f
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_15_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_15_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$15, %xmm2
+	pslldq	$1, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$15, %xmm2
+	pslldq	$1, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_15_use_sse2)
+
+
+/*
+ * ashr_14 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 14 
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_14):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_14_use_sse2)
+
+	.p2align 4
+LABEL(ashr_14_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $14, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0e
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $14, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0e
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_14_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_14_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$14, %xmm2
+	pslldq	$2, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$14, %xmm2
+	pslldq	$2, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_14_use_sse2)
+
+
+/*
+ * ashr_13 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 13 
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_13):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_13_use_sse2)
+
+	.p2align 4
+LABEL(ashr_13_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $13, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0d
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
 #endif
 
+	#palignr $13, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0d
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
 #ifdef USE_AS_STRNCPY
-	test	%rdx, %rdx		/* (char *, const char *, size_t) */
-	mov	%rdx, %r11
-	jz	LABEL(exitn)		/* early exit */
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_13_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_13_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$13, %xmm2
+	pslldq	$3, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$13, %xmm2
+	pslldq	$3, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_13_use_sse2)
+
+
+/*
+ * ashr_12 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 12 
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_12):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_12_use_sse2)
+
+	.p2align 4
+LABEL(ashr_12_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $12, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0c
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $12, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0c
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_12_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_12_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$12, %xmm2
+	pslldq	$4, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$12, %xmm2
+	pslldq	$4, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_12_use_sse2)
+
+
+/*
+ * ashr_11 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 11 
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_11):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_11_use_sse2)
+
+	.p2align 4
+LABEL(ashr_11_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $11, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0b
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $11, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0b
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_11_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_11_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$11, %xmm2
+	pslldq	$5, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$11, %xmm2
+	pslldq	$5, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_11_use_sse2)
+
+
+/*
+ * ashr_10 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 10
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_10):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_10_use_sse2)
+
+	.p2align 4
+LABEL(ashr_10_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $10, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0a
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $10, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x0a
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_10_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_10_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$10, %xmm2
+	pslldq	$6, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$10, %xmm2
+	pslldq	$6, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_10_use_sse2)
+
+
+/*
+ * ashr_9 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 9
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_9):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_9_use_sse2)
+
+	.p2align 4
+LABEL(ashr_9_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $9, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x09
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $9, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x09
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_9_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_9_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$9, %xmm2
+	pslldq	$7, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
 #endif
 
-        xor     %edx, %edx
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$9, %xmm2
+	pslldq	$7, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_9_use_sse2)
+
+
+/*
+ * ashr_8 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 8
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_8):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_8_use_sse2)
+
+	.p2align 4
+LABEL(ashr_8_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $8, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x08
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $8, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x08
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_8_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_8_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$8, %xmm2
+	pslldq	$8, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$8, %xmm2
+	pslldq	$8, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_8_use_sse2)
+
+
+/*
+ * ashr_7 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 7
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_7):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_7_use_sse2)
+
+	.p2align 4
+LABEL(ashr_7_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $7, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x07
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $7, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x07
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_7_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_7_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$7, %xmm2
+	pslldq	$9, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$7, %xmm2
+	pslldq	$9, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_7_use_sse2)
+
 
-LABEL(aligntry):
-        mov     %rsi, %r8		/* align by source */
-        and     $7, %r8
-	jz	LABEL(alignafter)
+/*
+ * ashr_6 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 6
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_6):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_6_use_sse2)
+
+	.p2align 4
+LABEL(ashr_6_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $6, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x06
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $6, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x06
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_6_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_6_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$6, %xmm2
+	pslldq	$10, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$6, %xmm2
+	pslldq	$10, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_6_use_sse2)
+
 
-LABEL(align):				/* 8-byte align */
-        sub     $8, %r8
+/*
+ * ashr_5 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 5
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_5):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_5_use_sse2)
+
+	.p2align 4
+LABEL(ashr_5_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $5, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x05
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $5, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x05
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_5_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_5_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$5, %xmm2
+	pslldq	$11, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$5, %xmm2
+	pslldq	$11, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_5_use_sse2)
+
+
+/*
+ * ashr_4 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 4
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_4):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_4_use_sse2)
 
 	.p2align 4
+LABEL(ashr_4_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
 
-LABEL(alignloop):
+	#palignr $4, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x04
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $4, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x04
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_4_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_4_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$4, %xmm2
+	pslldq	$12, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$4, %xmm2
+	pslldq	$12, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_4_use_sse2)
+
+
+/*
+ * ashr_3 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 3
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_3):
+	xor	%ecx, %ecx				/* clear index */
 #ifdef USE_AS_STRNCPY
-	dec	%r11
-	jl	LABEL(exitn)
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_3_use_sse2)
+
+	.p2align 4
+LABEL(ashr_3_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $3, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x03
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $3, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x03
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_3_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_3_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$3, %xmm2
+	pslldq	$13, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$3, %xmm2
+	pslldq	$13, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_3_use_sse2)
+
+
+/*
+ * ashr_2 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 2
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_2):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_2_use_sse2)
+
+	.p2align 4
+LABEL(ashr_2_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
 #endif
 
-        mov     (%rsi, %rdx), %al       /* check if same character */
-        test    %al, %al                /* check if character a NUL */
-        mov     %al, (%rdi, %rdx)
-        jz      LABEL(exit)
+	#palignr $2, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x02
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $2, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x02
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_2_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_2_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$2, %xmm2
+	pslldq	$14, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
 
-        inc     %edx
-        inc     %r8
-        jnz     LABEL(alignloop)
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$2, %xmm2
+	pslldq	$14, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_2_use_sse2)
+
+
+/*
+ * ashr_1 handles the following cases:
+ * 	(16 + (src offset - dest offset)) % 16 = 1
+ *
+ * Based on above operation, start from (%r9 + rsi) to the left of this cache
+ * bank, there is no null byte.
+ */
+	.p2align 4
+LABEL(ashr_1):
+	xor	%ecx, %ecx				/* clear index */
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	testl	$USE_SSSE3, .memops_method(%rip)	/* use sse2 or ssse3? */
+	jz	LABEL(ashr_1_use_sse2)
+
+	.p2align 4
+LABEL(ashr_1_use_ssse3):
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb	%xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	#palignr $1, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x01
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
 
 #ifdef USE_AS_STRNCPY
-	test	%r11, %r11		/* must check remaining size */
-	jz	LABEL(exitn)		/* If we've already done, exit */
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	pcmpeqb %xmm3, %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+	#palignr $1, (%rsi, %rcx), %xmm3
+	.byte	0x66, 0x0F, 0x3A ,0x0F
+	.byte	0x1c, 0x0e, 0x01
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_1_use_ssse3)
+
+	.p2align 4
+LABEL(ashr_1_use_sse2):
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$1, %xmm2
+	pslldq	$15, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	pcmpeqb 16(%rsi, %rcx), %xmm0
+	pmovmskb %xmm0, %edx
+	test	%edx, %edx
+	jnz	LABEL(unaligned_exit)
+#ifdef USE_AS_STRNCPY
+	sub	$16, %r8
+ 	jbe	LABEL(strncpy_truncation_unaligned)
+#endif
+
+	movdqa	16(%rsi, %rcx), %xmm3
+	movdqa	(%rsi, %rcx), %xmm2
+
+	psrldq	$1, %xmm2
+	pslldq	$15, %xmm3
+	por	%xmm2, %xmm3
+
+	movdqa	%xmm3, (%rdi, %rcx)
+	add	$16, %rcx
+#ifdef USE_AS_STRNCPY
+	cmp	%r10, %r8
+	jbe	LABEL(unaligned_exit)
+#endif
+	jmp	LABEL(ashr_1_use_sse2)
+
+
+	/*
+	 * Exit tail code:
+	 * Up to 32 bytes are copied in the case of strcpy.
+	 */
+	.p2align 4
+LABEL(less32bytes):
+	xor	%ecx, %ecx
+LABEL(unaligned_exit):
+	add	%r9, %rsi		/* r9 holds offset of rsi */
+	mov	%rcx, %r9
+	mov	%r10, %rcx
+	shl	%cl, %edx		/* after shl, calculate the exact number to be filled */
+	mov	%r9, %rcx
+	.p2align 4
+LABEL(aligned_exit):
+	add	%rcx, %rdi		/* locate exact address for rdi */
+LABEL(less16bytes):
+	add	%rcx, %rsi		/* locate exact address for rsi */
+LABEL(aligned_16bytes):
+#ifdef USE_AS_STRNCPY
+	/*
+	 * Null found in 16bytes checked. Set bit in bitmask corresponding to
+	 * the strncpy count argument. We will copy to the null (inclusive)
+	 * or count whichever comes first.
+	 */
+	mov	$1, %r9d
+	lea	-1(%r8), %rcx
+	shl	%cl, %r9d
+	cmp	$32, %r8
+	ja	LABEL(strncpy_tail)
+	or	%r9d, %edx
+LABEL(strncpy_tail):
+#endif
+	/*
+	 * Check to see if BSF is fast on this processor. If not, use a
+	 * different exit tail.
+	 */
+	testb	$USE_BSF, .memops_method(%rip)
+	jz	LABEL(AMD_exit)
+	bsf	%rdx, %rcx		/* Find byte with null char */
+	lea	LABEL(tail_table)(%rip), %r11
+	movslq	(%r11, %rcx, 4), %rcx
+	lea	(%r11, %rcx), %rcx
+	jmp	*%rcx
+
+#ifdef USE_AS_STRNCPY
+	/*
+	 * Count reached before null found.
+	 */
+	.p2align 4
+LABEL(less32bytes_strncpy_truncation):
+	xor	%ecx, %ecx
+LABEL(strncpy_truncation_unaligned):
+	add	%r9, %rsi		/* next src char to copy */
+LABEL(strncpy_truncation_aligned):
+	add	%rcx, %rdi
+	add	%rcx, %rsi
+	add	$16, %r8		/* compensation */
+	lea	-1(%r8), %rcx
+	lea	LABEL(tail_table)(%rip), %r11
+	movslq	(%r11, %rcx, 4), %rcx
+	lea	(%r11, %rcx), %rcx
+	jmp	*%rcx
+
+	.p2align 4
+LABEL(strncpy_exitz):
+	mov	%rdi, %rax
+	ret
 #endif
 
 	.p2align 4
-
-LABEL(alignafter):
-
-LABEL(8try):
-        mov     $0xfefefefefefefeff, %rcx
-
-LABEL(8):                               /* 8-byte */
-        mov     (%rsi, %rdx), %rax
-
-LABEL(8loop):
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-LABEL(8after):
-
-LABEL(64try):
-        mov     _sref_(.amd64cache1half), %r9
-
-LABEL(64):				/* 64-byte */
-
-        .p2align 4
-
-LABEL(64loop):
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
+LABEL(AMD_exit):
+	test	%dl, %dl
+	jz	LABEL(AMD_exit_more_8)
+	test	$0x01, %dl
+	jnz	LABEL(tail_0)
+	test	$0x02, %dl
+	jnz	LABEL(tail_1)
+	test	$0x04, %dl
+	jnz	LABEL(tail_2)
+	test	$0x08, %dl
+	jnz	LABEL(tail_3)
+	test	$0x10, %dl
+	jnz	LABEL(tail_4)
+	test	$0x20, %dl
+	jnz	LABEL(tail_5)
+	test	$0x40, %dl
+	jnz	LABEL(tail_6)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
+	.p2align 4
+LABEL(tail_7):				/* 8 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
 #ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
+	mov	$8, %cl
+	sub	$8, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        cmp     %r9, %rdx
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        lea     8 (%rdx), %rdx
-
-        jbe     LABEL(64loop)
-
-LABEL(64after):
-
-LABEL(pretry):
-        mov     _sref_(.amd64cache2half), %r9
-
-LABEL(pre):                              /* 64-byte prefetch */
-
-        .p2align 4
-
-LABEL(preloop):
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
+	ret
 
 #ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        mov     %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %edx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(tail)
-
-        cmp     %r9, %rdx
+	/*
+	 * Null terminated src string shorter than count. Fill the rest of the
+	 * destination with null chars.
+	 */
+	.p2align 4
+LABEL(strncpy_fill_tail):
+	mov	%rax, %rdx
+	movzx	%cl, %rax
+	mov	%r8, %rcx
+	add	%rax, %rdi
+	xor	%eax, %eax
+	shr	$3, %ecx
+	jz	LABEL(strncpy_fill_less_8)
 
-        mov     %rax, (%rdi, %rdx)
-        prefetchnta 512 + 8 (%rdi, %rdx)	/* 3DNow: use prefetchw */
-        mov     8 (%rsi, %rdx), %rax
-        prefetchnta 512 + 8 (%rsi, %rdx)	/* 3DNow: use prefetch */
-        lea     8 (%rdx), %rdx
-
-        jb	LABEL(preloop)
-
-        .p2align 4
-
-LABEL(preafter):
-
-LABEL(NTtry):
-	mfence
-
-LABEL(NT):				/* 64-byte NT */
-
-        .p2align 4
-
-LABEL(NTloop):
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
-
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
-
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
-
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
-#endif
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
-
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
-
-#ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
+	rep	stosq
+LABEL(strncpy_fill_less_8):
+	mov	%r8, %rcx
+	and	$7, %rcx
+	jz	LABEL(strncpy_fill_return)
+LABEL(strncpy_fill_less_7):
+	sub	$1, %ecx
+	mov	%al, (%rdi, %rcx)
+	jnz	LABEL(strncpy_fill_less_7)
+LABEL(strncpy_fill_return):
+	mov	%rdx, %rax
+	ret
 #endif
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	.p2align 4
+LABEL(tail_0):				/* 1 byte */
+	mov	(%rsi), %cl
+	mov	%cl, (%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$1, %cl
+	sub	$1, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
+	.p2align 4
+LABEL(tail_1):				/* 2 bytes */
+	mov	(%rsi), %cx
+	mov	%cx, (%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$2, %cl
+	sub	$2, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
+	.p2align 4
+LABEL(tail_2):				/* 3 bytes */
+	mov	(%rsi), %cx
+	mov	%cx, (%rdi)
+	mov	1(%rsi), %cx
+	mov	%cx, 1(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$3, %cl
+	sub	$3, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
+	.p2align 4
+LABEL(tail_3):				/* 4 bytes */
+	mov	(%rsi), %ecx
+	mov	%ecx, (%rdi)
 #ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
+	mov	$4, %cl
+	sub	$4, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	.p2align 4
+LABEL(tail_4):				/* 5 bytes */
+	mov	(%rsi), %ecx
+	mov	%ecx, (%rdi)
+	mov	1(%rsi), %edx
+	mov	%edx, 1(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$5, %cl
+	sub	$5, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
+	.p2align 4
+LABEL(tail_5):				/* 6 bytes */
+	mov	(%rsi), %ecx
+	mov	%ecx, (%rdi)
+	mov	2(%rsi), %edx
+	mov	%edx, 2(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$6, %cl
+	sub	$6, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
-
+	.p2align 4
+LABEL(tail_6):				/* 7 bytes */
+	mov	(%rsi), %ecx
+	mov	%ecx, (%rdi)
+	mov	3(%rsi), %edx
+	mov	%edx,3(%rdi)
 #ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
+	mov	$7, %cl
+	sub	$7, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	.p2align 4
+LABEL(tail_8):				/* 9 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	5(%rsi), %edx
+	mov	%edx, 5(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$9, %cl
+	sub	$9, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
+	.p2align 4
+LABEL(AMD_exit_more_8):
+	test	%dh, %dh
+	jz	LABEL(AMD_exit_more_16)
+	test	$0x01, %dh
+	jnz	LABEL(tail_8)
+	test	$0x02, %dh
+	jnz	LABEL(tail_9)
+	test	$0x04, %dh
+	jnz	LABEL(tail_10)
+	test	$0x08, %dh
+	jnz	LABEL(tail_11)
+	test	$0x10, %dh
+	jnz	LABEL(tail_12)
+	test	$0x20, %dh
+	jnz	LABEL(tail_13)
+	test	$0x40, %dh
+	jnz	LABEL(tail_14)
 
-        movnti  %rax, (%rdi, %rdx)
-        mov     8 (%rsi, %rdx), %rax
-        add     $8, %rdx
+	.p2align 4
+LABEL(tail_15):				/* 16 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$16, %cl
+	sub	$16, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
+	.p2align 4
+LABEL(tail_9):				/* 10 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	6(%rsi), %edx
+	mov	%edx, 6(%rdi)
 #ifdef USE_AS_STRNCPY
-	sub	$8, %r11
-	jle	LABEL(tail)
+	mov	$10, %cl
+	sub	$10, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %r10, %r10
+	.p2align 4
+LABEL(tail_10):				/* 11 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	7(%rsi), %edx
+	mov	%edx, 7(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$11, %cl
+	sub	$11, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %r10, %r8
-        jnz     LABEL(NTtail)
+	.p2align 4
+LABEL(tail_11):				/* 12 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %edx
+	mov	%edx, 8(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$12, %cl
+	sub	$12, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        movnti  %rax, (%rdi, %rdx)
-	mov     8 (%rsi, %rdx), %rax
-	prefetchnta 768 + 8 (%rsi, %rdx)
-        add     $8, %rdx
+	.p2align 4
+LABEL(tail_12):				/* 13 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	5(%rsi), %rcx
+	mov	%rcx, 5(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$13, %cl
+	sub	$13, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        jmp     LABEL(NTloop)
-
-        .p2align 4
+	.p2align 4
+LABEL(tail_13):				/* 14 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	6(%rsi), %rcx
+	mov	%rcx, 6(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$14, %cl
+	sub	$14, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-LABEL(NTtail):
-	mfence
-
-        .p2align 4
-
-LABEL(NTafter):
-
-LABEL(tailtry):
-
-LABEL(tail):                             /* 1-byte tail */
+	.p2align 4
+LABEL(tail_14):				/* 15 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	7(%rsi), %rcx
+	mov	%rcx, 7(%rdi)
 #ifdef USE_AS_STRNCPY
-	add	$8, %r11
+	mov	$15, %cl
+	sub	$15, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        .p2align 4
+	.p2align 4
+LABEL(AMD_exit_more_16):
+	shr	$16, %edx
+	test	%dl, %dl
+	jz	LABEL(AMD_exit_more_24)
+	test	$0x01, %dl
+	jnz	LABEL(tail_16)
+	test	$0x02, %dl
+	jnz	LABEL(tail_17)
+	test	$0x04, %dl
+	jnz	LABEL(tail_18)
+	test	$0x08, %dl
+	jnz	LABEL(tail_19)
+	test	$0x10, %dl
+	jnz	LABEL(tail_20)
+	test	$0x20, %dl
+	jnz	LABEL(tail_21)
+	test	$0x40, %dl
+	jnz	LABEL(tail_22)
 
-LABEL(tailloop):
+	.p2align 4
+LABEL(tail_23):				/* 24 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
 #ifdef USE_AS_STRNCPY
-	dec	%r11
-	jl	LABEL(exitn)
+	mov	$24, %cl
+	sub	$24, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        test    %al, %al
-        mov     %al, (%rdi, %rdx)
-        jz      LABEL(exit)
+	.p2align 4
+LABEL(tail_16):				/* 17 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %cl
+	mov	%cl, 16(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$17, %cl
+	sub	$17, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
+
+	.p2align 4
+LABEL(tail_17):				/* 18 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %cx
+	mov	%cx, 16(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$18, %cl
+	sub	$18, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        inc     %rdx
-
+	.p2align 4
+LABEL(tail_18):				/* 19 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	15(%rsi), %ecx
+	mov	%ecx,15(%rdi)
 #ifdef USE_AS_STRNCPY
-	dec	%r11
-	jl	LABEL(exitn)
+	mov	$19, %cl
+	sub	$19, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-	mov	%ah, %al
+	.p2align 4
+LABEL(tail_19):				/* 20 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %ecx
+	mov	%ecx, 16(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$20, %cl
+	sub	$20, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-        test    %ah, %ah
-        mov     %ah, (%rdi, %rdx)
-        jz      LABEL(exit)
-
-        inc     %rdx
+	.p2align 4
+LABEL(tail_20):				/* 21 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	13(%rsi), %rcx
+	mov	%rcx, 13(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$21, %cl
+	sub	$21, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
+	.p2align 4
+LABEL(tail_21):				/* 22 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	14(%rsi), %rcx
+	mov	%rcx, 14(%rdi)
 #ifdef USE_AS_STRNCPY
-	dec	%r11
-	jl	LABEL(exitn)
+	mov	$22, %cl
+	sub	$22, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
-
-        shr     $16, %rax
+	ret
 
-        test    %al, %al
-        mov     %al, (%rdi, %rdx)
-        jz      LABEL(exit)
-
-        inc     %rdx
+	.p2align 4
+LABEL(tail_22):				/* 23 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	15(%rsi), %rcx
+	mov	%rcx, 15(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$23, %cl
+	sub	$23, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-#ifdef USE_AS_STRNCPY
-	dec	%r11
-	jl	LABEL(exitn)
-
-	mov	%ah, %al
-#endif
+	.p2align 4
+LABEL(AMD_exit_more_24):
+	test	$0x01, %dh
+	jnz	LABEL(tail_24)
+	test	$0x02, %dh
+	jnz	LABEL(tail_25)
+	test	$0x04, %dh
+	jnz	LABEL(tail_26)
+	test	$0x08, %dh
+	jnz	LABEL(tail_27)
+	test	$0x10, %dh
+	jnz	LABEL(tail_28)
+	test	$0x20, %dh
+	jnz	LABEL(tail_29)
+	test	$0x40, %dh
+	jnz	LABEL(tail_30)
 
-        test    %ah, %ah
-        mov     %ah, (%rdi, %rdx)
-        jz      LABEL(exit)
+	.p2align 4
+LABEL(tail_31):				/* 32 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	24(%rsi), %rdx
+	mov	%rdx, 24(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$32, %cl
+	sub	$32, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        shr     $16, %rax
-        inc     %rdx
-
-        jmp     LABEL(tailloop)
-
-        .p2align 4
-
-LABEL(tailafter):
+	.p2align 4
+LABEL(tail_24):				/* 25 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	21(%rsi), %edx
+	mov	%edx, 21(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$25, %cl
+	sub	$25, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-LABEL(exit):
+	.p2align 4
+LABEL(tail_25):				/* 26 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	22(%rsi), %edx
+	mov	%edx, 22(%rdi)
 #ifdef USE_AS_STRNCPY
-	test	%r11, %r11
-	mov	%r11, %rcx
+	mov	$26, %cl
+	sub	$26, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-#ifdef USE_AS_STPCPY
-        lea     (%rdi, %rdx), %r8
-#else
-        mov     %rdi, %r8
+	.p2align 4
+LABEL(tail_26):				/* 27 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	23(%rsi), %edx
+	mov	%edx, 23(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$27, %cl
+	sub	$27, %r8
+	jnz	LABEL(strncpy_fill_tail)
 #endif
+	ret
 
-	jz	2f
-
-	xor	%eax, %eax		/* bzero () would do too, but usually there are only a handfull of bytes left */
-	shr	$3, %rcx
-        lea     1 (%rdi, %rdx), %rdi
-	jz	1f
+	.p2align 4
+LABEL(tail_27):				/* 28 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	24(%rsi), %edx
+	mov	%edx, 24(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$28, %cl
+	sub	$28, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-	rep	stosq
-
-1:
-	mov	%r11d, %ecx
-	and	$7, %ecx
-	jz	2f
+	.p2align 4
+LABEL(tail_28):				/* 29 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	21(%rsi), %rdx
+	mov	%rdx, 21(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$29, %cl
+	sub	$29, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-        .p2align 4,, 3
+	.p2align 4
+LABEL(tail_29):				/* 30 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	22(%rsi), %rdx
+	mov	%rdx, 22(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$30, %cl
+	sub	$30, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-3:
-	dec	%ecx
-	mov	%al, (%rdi, %rcx)
-	jnz	3b
-
-        .p2align 4,, 3
-
-2:
-	mov	%r8, %rax
-        ret
+	.p2align 4
+LABEL(tail_30):				/* 31 bytes */
+	mov	(%rsi), %rcx
+	mov	%rcx, (%rdi)
+	mov	8(%rsi), %rdx
+	mov	%rdx, 8(%rdi)
+	mov	16(%rsi), %rcx
+	mov	%rcx, 16(%rdi)
+	mov	23(%rsi), %rdx
+	mov	%rdx, 23(%rdi)
+#ifdef USE_AS_STRNCPY
+	mov	$31, %cl
+	sub	$31, %r8
+	jnz	LABEL(strncpy_fill_tail)
+#endif
+	ret
 
-#endif
-
-        .p2align 4
+	.pushsection .rodata
+	.p2align 4
+LABEL(tail_table):
+	.int	LABEL(tail_0) - LABEL(tail_table)	/* 1 byte */
+	.int	LABEL(tail_1) - LABEL(tail_table)
+	.int	LABEL(tail_2) - LABEL(tail_table)
+	.int	LABEL(tail_3) - LABEL(tail_table)
+	.int	LABEL(tail_4) - LABEL(tail_table)
+	.int	LABEL(tail_5) - LABEL(tail_table)
+	.int	LABEL(tail_6) - LABEL(tail_table)
+	.int	LABEL(tail_7) - LABEL(tail_table)
+	.int	LABEL(tail_8) - LABEL(tail_table)
+	.int	LABEL(tail_9) - LABEL(tail_table)
+	.int	LABEL(tail_10) - LABEL(tail_table)
+	.int	LABEL(tail_11) - LABEL(tail_table)
+	.int	LABEL(tail_12) - LABEL(tail_table)
+	.int	LABEL(tail_13) - LABEL(tail_table)
+	.int	LABEL(tail_14) - LABEL(tail_table)
+	.int	LABEL(tail_15) - LABEL(tail_table)
+	.int	LABEL(tail_16) - LABEL(tail_table)
+	.int	LABEL(tail_17) - LABEL(tail_table)
+	.int	LABEL(tail_18) - LABEL(tail_table)
+	.int	LABEL(tail_19) - LABEL(tail_table)
+	.int	LABEL(tail_20) - LABEL(tail_table)
+	.int	LABEL(tail_21) - LABEL(tail_table)
+	.int	LABEL(tail_22) - LABEL(tail_table)
+	.int	LABEL(tail_23) - LABEL(tail_table)
+	.int	LABEL(tail_24) - LABEL(tail_table)
+	.int	LABEL(tail_25) - LABEL(tail_table)
+	.int	LABEL(tail_26) - LABEL(tail_table)
+	.int	LABEL(tail_27) - LABEL(tail_table)
+	.int	LABEL(tail_28) - LABEL(tail_table)
+	.int	LABEL(tail_29) - LABEL(tail_table)
+	.int	LABEL(tail_30) - LABEL(tail_table)
+	.int	LABEL(tail_31) - LABEL(tail_table)	/* 32 bytes */
 
-LABEL(exitn):
-#ifdef USE_AS_STPCPY
-        lea     (%rdi, %rdx), %rax
-#else
-        mov     %rdi, %rax
-#endif
-
-        ret
+	.p2align 4
+LABEL(unaligned_table):
+	.int	LABEL(ashr_0) - LABEL(unaligned_table)
+	.int	LABEL(ashr_1) - LABEL(unaligned_table)
+	.int	LABEL(ashr_2) - LABEL(unaligned_table)
+	.int	LABEL(ashr_3) - LABEL(unaligned_table)
+	.int	LABEL(ashr_4) - LABEL(unaligned_table)
+	.int	LABEL(ashr_5) - LABEL(unaligned_table)
+	.int	LABEL(ashr_6) - LABEL(unaligned_table)
+	.int	LABEL(ashr_7) - LABEL(unaligned_table)
+	.int	LABEL(ashr_8) - LABEL(unaligned_table)
+	.int	LABEL(ashr_9) - LABEL(unaligned_table)
+	.int	LABEL(ashr_10) - LABEL(unaligned_table)
+	.int	LABEL(ashr_11) - LABEL(unaligned_table)
+	.int	LABEL(ashr_12) - LABEL(unaligned_table)
+	.int	LABEL(ashr_13) - LABEL(unaligned_table)
+	.int	LABEL(ashr_14) - LABEL(unaligned_table)
+	.int	LABEL(ashr_15) - LABEL(unaligned_table)
+	.popsection
 
 #ifdef USE_AS_STRNCPY
 	SET_SIZE(strncpy)
 #else
-	SET_SIZE(strcpy)                        /* (char *, const char *) */
+	SET_SIZE(strcpy)			/* (char *, const char *) */
 #endif
--- a/usr/src/lib/libc/amd64/gen/strlen.s	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/amd64/gen/strlen.s	Mon Sep 21 11:26:40 2009 -0400
@@ -1,430 +1,199 @@
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-	
-/*
- * Copyright (c) 2002 Advanced Micro Devices, 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:
- * 
- * + Redistributions  of source  code  must  retain  the  above
- *   copyright  notice,   this  list  of   conditions  and  the
- *   following disclaimer.
- * 
- * + 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.
- * 
- * + Neither the  name of Advanced Micro Devices,  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  ADVANCED  MICRO  DEVICES,
- * INC.  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.
- * 
- * It is  licensee's responsibility  to comply with  any export
- * regulations applicable in licensee's jurisdiction.
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
  */
 
-	.file	"strlen.s"
+/*
+ * Copyright (c) 2009, Intel Corporation
+ * All rights reserved.
+ */
+
+/*
+ *	strlen - calculate the length of string
+ */
 
 #include "SYS.h"
-#include "cache.h"
+#include "proc64_id.h"
 
 #define LABEL(s) .strlen/**/s
 
-	ENTRY(strlen)                /* (const char *s) */
-
-        mov     %rdi, %rsi
-        neg     %rdi
-
-LABEL(aligntry):
-        mov     %rsi , %r8
-        and     $7, %r8d
-	jz	LABEL(alignafter)
-
-LABEL(align):                            /* 8-byte align */
-        sub     $8, %r8
-
-        .p2align 4
-
-LABEL(alignloop):
-        cmpb    $0, (%rsi)
-        je      LABEL(exit)
+	/*
+	 * This implementation uses SSE instructions to compare up to 16 bytes
+	 * at a time looking for the end of string (null char).
+	 */
+	ENTRY(strlen)			/* (const char *s) */
+	mov	%rdi, %rsi		/* keep original %rdi value */
+	mov	%rsi, %rcx
+	pxor	%xmm0, %xmm0		/* 16 null chars */
+	and	$15, %rcx	
+	jz	LABEL(align16_loop)	/* string is 16 byte aligned */ 		
 
-        inc     %rsi
-        inc     %r8
-        jnz     LABEL(alignloop)
-
-        .p2align 4
-
-LABEL(alignafter):
-
-LABEL(56try):
-
-LABEL(56):                               /* 56-byte */
-        mov     (%rsi), %rax
-        mov     $0xfefefefefefefeff, %rcx
-
-LABEL(56loop):
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
+	/*
+	 * Unaligned case. Round down to 16-byte boundary before comparing
+	 * 16 bytes for a null char. The code then compensates for any extra chars
+	 * preceding the start of the string. 
+	 */
+LABEL(unalign16):
+	and	$0xfffffffffffffff0, %rsi
 
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
+	pcmpeqb	(%rsi), %xmm0
+	lea	16(%rdi), %rsi		
+	pmovmskb %xmm0, %edx
 
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
+	shr	%cl, %edx		/* Compensate for bytes preceding the string */
+	test	%edx, %edx
+	jnz	LABEL(exit)
+	sub	%rcx, %rsi		/* no null, adjust to next 16-byte boundary */
+	pxor	%xmm0, %xmm0		/* clear xmm0, may have been changed... */
+	
+	.p2align 4
+LABEL(align16_loop):			/* 16 byte aligned */
+	pcmpeqb	(%rsi), %xmm0		/* look for null bytes */
+	pmovmskb %xmm0, %edx		/* move each byte mask of %xmm0 to edx */
 
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
+	add	$16, %rsi		/* prepare to search next 16 bytes */
+	test	%edx, %edx		/* if no null byte, %edx must be 0 */
+	jnz	LABEL(exit)		/* found a null */
 
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        jnc     LABEL(tail)
+	pcmpeqb	(%rsi), %xmm0
+	pmovmskb %xmm0, %edx
+	add	$16, %rsi
+	test	%edx, %edx
+	jnz	LABEL(exit)
 
-        xor     %rax, %r8
-        or      %rcx, %r8
-        inc     %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
-
-LABEL(56after):
-
-LABEL(32):                               /* 32-byte */
-        mov     _sref_(.amd64cache1), %r9
+	pcmpeqb	(%rsi), %xmm0
+	pmovmskb %xmm0, %edx
+	add	$16, %rsi
+	test	%edx, %edx
+	jnz	LABEL(exit)
 
-        .p2align 4
-
-LABEL(32loop):
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	pcmpeqb	(%rsi), %xmm0
+	pmovmskb %xmm0, %edx
+	add	$16, %rsi
+	test	%edx, %edx
+	jz	LABEL(align16_loop)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	.p2align 4
+LABEL(exit):
+	neg	%rdi		
+	/*
+	 * Check to see if BSF is fast on this processor. If not, use a different
+	 * exit tail to find first bit set indicating null byte match.
+	 */
+	testl	$USE_BSF, .memops_method(%rip)
+	jz	LABEL(AMD_exit)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	lea	-16(%rdi, %rsi), %rax	/* calculate exact offset */	
+	bsf	%edx, %ecx		/* Least significant 1 bit is index of null */	
+	lea	(%rax, %rcx),%rax
+	ret
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	/*
+	 * This exit tail does not use the bsf instruction.
+	 */
+	.p2align 4
+LABEL(AMD_exit):
+	lea	-16(%rdi, %rsi), %rax
+	test	%dl, %dl	
+	jz	LABEL(exit_high)
+	test	$0x01, %dl
+	jnz	LABEL(exit_tail0)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x02, %dl
+	jnz	LABEL(exit_tail1)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	.p2align 4		
+	test	$0x04, %dl
+	jnz	LABEL(exit_tail2)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x08, %dl
+	jnz	LABEL(exit_tail3)
 
-        sub     $32, %r9
-
-        mov     8 (%rsi), %rax
-        lea     8 (%rsi), %rsi
+	test	$0x10, %dl
+	jnz	LABEL(exit_tail4)
 
-        jbe     LABEL(32loop)
-
-LABEL(32after):
-
-LABEL(pretry):
-
-LABEL(pre):                              /* 64-byte prefetch */
+	test	$0x20, %dl
+	jnz	LABEL(exit_tail5)
 
-        .p2align 4
-
-LABEL(preloop):
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x40, %dl
+	jnz	LABEL(exit_tail6)
+	add	$7, %rax
+	ret
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	.p2align 4
+LABEL(exit_high):
+	add	$8, %rax
+	test	$0x01, %dh
+	jnz	LABEL(exit_tail0)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	test	$0x02, %dh
+	jnz	LABEL(exit_tail1)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x04, %dh
+	jnz	LABEL(exit_tail2)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
+	test	$0x08, %dh
+	jnz	LABEL(exit_tail3)
 
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x10, %dh
+	jnz	LABEL(exit_tail4)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x20, %dh
+	jnz	LABEL(exit_tail5)
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	test	$0x40, %dh
+	jnz	LABEL(exit_tail6)
+	add	$7, %rax
+	ret
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	.p2align 4
+LABEL(exit_tail0):
+	xor	%ecx, %ecx
+	ret
 
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        mov     %rcx, %r8
-        add     %rax, %r8
-        sbb     %rdx, %rdx
-
-        xor     %rax, %r8
-        or      %rcx, %r8
-        sub     %rdx, %r8
-        jnz     LABEL(tail)
+	.p2align 4
+LABEL(exit_tail1):
+	add	$1, %rax
+	ret
 
-        prefetchnta 512 (%rsi)	/* 3DNow: use prefetch */
-
-        mov     8 (%rsi), %rax
-        add     $8, %rsi
-
-        jmp     LABEL(preloop)
-
-        .p2align 4
-
-LABEL(preafter):
+	.p2align 4
+LABEL(exit_tail2):
+	add	$2, %rax
+	ret
 
-LABEL(tailtry):
-
-LABEL(tail):                             /* 4-byte tail */
-
-LABEL(tailloop):
-        test    %al, %al
-        jz      LABEL(exit)
-
-        inc     %rsi
-
-        test    %ah, %ah
-        jz      LABEL(exit)
+	.p2align 4
+LABEL(exit_tail3):
+	add	$3, %rax
+	ret
 
-        inc     %rsi
-
-        test    $0x00ff0000, %eax
-        jz      LABEL(exit)
-
-        inc     %rsi
-
-        test    $0xff000000, %eax
-        jz      LABEL(exit)
-
-        inc     %rsi
+	.p2align 4
+LABEL(exit_tail4):
+	add	$4, %rax
+	ret
 
-        shr     $32, %rax
-        jmp     LABEL(tailloop)
-
-LABEL(tailafter):
+	.p2align 4
+LABEL(exit_tail5):
+	add	$5, %rax
+	ret
 
-        .p2align 4
-
-LABEL(exit):
-        lea     (%rdi, %rsi), %rax
-        ret
-
+	.p2align 4
+LABEL(exit_tail6):
+	add	$6, %rax
+	ret
 	SET_SIZE(strlen)
--- a/usr/src/lib/libc/i386/Makefile.com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/i386/Makefile.com	Mon Sep 21 11:26:40 2009 -0400
@@ -412,6 +412,7 @@
 	csetlen.o		\
 	ctime.o			\
 	ctime_r.o		\
+	daemon.o		\
 	deflt.o			\
 	directio.o		\
 	dirname.o		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libc/port/gen/daemon.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,103 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "lint.h"
+#include "file64.h"
+#include "mtlib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "stdiom.h"
+
+/*
+ * Use fork/setsid/fork to go into background and permanently remove
+ * controlling terminal.
+ */
+int
+daemon(int nochdir, int noclose)
+{
+	int retv, fd;
+
+	/*
+	 * By the first fork+setsid, we disconnect from our current controlling
+	 * terminal and become a session group leader.
+	 */
+	retv = fork();
+	if (retv == -1)
+		return (-1);
+	if (retv != 0)
+		_exit(EXIT_SUCCESS);
+	if (setsid() == -1)
+		return (-1);
+	/*
+	 * By forking again without calling setsid again, we make certain
+	 * that we are not the session group leader and can never reacquire
+	 * a controlling terminal.
+	 */
+	retv = fork();
+	if (retv == -1)
+		return (-1);
+	if (retv != 0)
+		_exit(EXIT_SUCCESS);
+
+	if (nochdir == 0)
+		(void) chdir("/");
+
+	if (noclose == 0) {
+		/*
+		 * Missing the PRIV_FILE_READ privilege may be one of the
+		 * reasons that prevent the opening of /dev/null to succeed.
+		 */
+		if ((fd = open("/dev/null", O_RDWR)) == -1)
+			return (-1);
+
+		/*
+		 * Also, if any of the descriptor redirects fails we should
+		 * return with error to signal to the caller that his request
+		 * cannot be fulfilled properly. It is up to the caller to
+		 * do the cleanup.
+		 */
+		if ((fd != STDIN_FILENO) && (dup2(fd, STDIN_FILENO) < 0)) {
+			(void) close(fd);
+			return (-1);
+		}
+		if ((fd != STDOUT_FILENO) && (dup2(fd, STDOUT_FILENO) < 0)) {
+			(void) close(fd);
+			return (-1);
+		}
+		if ((fd != STDERR_FILENO) && (dup2(fd, STDERR_FILENO) < 0)) {
+			(void) close(fd);
+			return (-1);
+		}
+
+		if (fd > STDERR_FILENO)
+			(void) close(fd);
+	}
+	return (0);
+}
--- a/usr/src/lib/libc/port/llib-lc	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/port/llib-lc	Mon Sep 21 11:26:40 2009 -0400
@@ -345,6 +345,9 @@
 int _tolower(int c);
 int toascii(int c);
 
+/* daemon.c */
+int daemon(int nochdir, int noclose);
+
 /* directio.c */
 int directio(int filedes, int advice);
 
--- a/usr/src/lib/libc/port/mapfile-vers	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/port/mapfile-vers	Mon Sep 21 11:26:40 2009 -0400
@@ -86,6 +86,7 @@
 	clock_gettime;
 	clock_nanosleep;
 	clock_settime;
+	daemon;
 	dirfd;
 	door_bind;
 	door_call;
--- a/usr/src/lib/libc/sparc/Makefile.com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/sparc/Makefile.com	Mon Sep 21 11:26:40 2009 -0400
@@ -429,6 +429,7 @@
 	csetlen.o		\
 	ctime.o			\
 	ctime_r.o		\
+	daemon.o		\
 	deflt.o			\
 	directio.o		\
 	dirname.o		\
--- a/usr/src/lib/libc/sparcv9/Makefile.com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libc/sparcv9/Makefile.com	Mon Sep 21 11:26:40 2009 -0400
@@ -390,6 +390,7 @@
 	csetlen.o		\
 	ctime.o			\
 	ctime_r.o		\
+	daemon.o		\
 	deflt.o			\
 	directio.o		\
 	dirname.o		\
--- a/usr/src/lib/libcryptoutil/common/config_parsing.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libcryptoutil/common/config_parsing.c	Mon Sep 21 11:26:40 2009 -0400
@@ -597,9 +597,10 @@
 	char *token1;
 
 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
-		cryptoerror(LOG_ERR,
+		cryptoerror(LOG_DEBUG,
 		    "failed to open the kcf.conf file for read only.");
-		return (CKR_FUNCTION_FAILED);
+		*mode = CRYPTO_FIPS_MODE_DISABLED;
+		return (CKR_OK);
 	}
 
 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
--- a/usr/src/lib/libgrubmgmt/common/libgrub_cmd.def	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libgrubmgmt/common/libgrub_cmd.def	Mon Sep 21 11:26:40 2009 -0400
@@ -58,6 +58,9 @@
 menu_cmd("args", GRBM_ARGS_CMD, GRUB_LINE_ENTRY, error_line)
 menu_cmd("findroot", GRBM_FINDROOT_CMD, GRUB_LINE_ENTRY, findroot)
 menu_cmd("bootfs", GRBM_BOOTFS_CMD, GRUB_LINE_ENTRY, bootfs)
+menu_cmd("splashimage", GRBM_SPLASHIMAGE_CMD, GRUB_LINE_ENTRY, skip_line)
+menu_cmd("background", GRBM_BACKGROUND_CMD, GRUB_LINE_ENTRY, skip_line)
+menu_cmd("foreground", GRBM_FOREGROUND_CMD, GRUB_LINE_ENTRY, skip_line)
 
 menu_cmd_end(GRBM_CMD_NUM) /* Should be the last one */
 
--- a/usr/src/lib/libscf/common/highlevel.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libscf/common/highlevel.c	Mon Sep 21 11:26:40 2009 -0400
@@ -230,6 +230,8 @@
 		scf_propvec_t ua_boot_config_ovr[] = {
 			{ FASTREBOOT_DEFAULT, NULL, SCF_TYPE_BOOLEAN, NULL,
 			    UA_FASTREBOOT_DEFAULT },
+			{ FASTREBOOT_ONPANIC, NULL, SCF_TYPE_BOOLEAN, NULL,
+			    UA_FASTREBOOT_ONPANIC },
 			{ NULL }
 		};
 		scf_propvec_t	*prop;
@@ -274,6 +276,10 @@
 			}
 		}
 #endif	/* FASTREBOOT_DEBUG */
+
+		if (set)
+			(void) smf_refresh_instance(FMRI_BOOT_CONFIG);
+
 		return (rc);
 
 	}
@@ -283,7 +289,7 @@
 /*
  * Get values of properties in non-persistent "config_ovr" property group.
  */
-static void
+void
 scf_get_boot_config_ovr(uint8_t *boot_config_ovr)
 {
 	(void) scf_getset_boot_config_ovr(B_FALSE, boot_config_ovr);
@@ -295,7 +301,10 @@
 int
 scf_fastreboot_default_set_transient(boolean_t value)
 {
-	uint8_t	boot_config_ovr = (value & UA_FASTREBOOT_DEFAULT);
+	uint8_t	boot_config_ovr = 0;
+
+	if (value == B_TRUE)
+		boot_config_ovr = UA_FASTREBOOT_DEFAULT | UA_FASTREBOOT_ONPANIC;
 
 	return (scf_getset_boot_config_ovr(B_TRUE, &boot_config_ovr));
 }
--- a/usr/src/lib/libscf/common/mapfile-vers	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libscf/common/mapfile-vers	Mon Sep 21 11:26:40 2009 -0400
@@ -315,6 +315,7 @@
 	scf_clean_propvec;
 	scf_instance_delete_prop;
 	scf_get_boot_config;
+	scf_get_boot_config_ovr;
 	scf_is_fastboot_default;
 	scf_fastreboot_default_set_transient;
     local:
--- a/usr/src/lib/libscf/inc/libscf_priv.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libscf/inc/libscf_priv.h	Mon Sep 21 11:26:40 2009 -0400
@@ -530,6 +530,7 @@
  * Functions to extract boot config information from FMRI_BOOT_CONFIG
  */
 void scf_get_boot_config(uint8_t *);
+void scf_get_boot_config_ovr(uint8_t *);
 int scf_is_fastboot_default(void);
 
 /*
--- a/usr/src/lib/libstmf/common/stmf.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/libstmf/common/stmf.c	Mon Sep 21 11:26:40 2009 -0400
@@ -4735,15 +4735,15 @@
 
 	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
 		stmfStateSet.state = STMF_STATE_OFFLINE;
-		stmfStateSet.config_state = STMF_CONFIG_INIT;
+
 		if ((ret = openStmf(OPEN_EXCL_STMF, &fd))
 		    != STMF_STATUS_SUCCESS) {
 			return (ret);
 		}
-		ret = setStmfState(fd, &stmfStateSet, STMF_SERVICE_TYPE);
-		if (ret != STMF_STATUS_SUCCESS) {
-			goto done;
-		}
+		/*
+		 * Configuration not stored persistently; nothing to
+		 * initialize so do not set to STMF_CONFIG_INIT.
+		 */
 		stmfStateSet.config_state = STMF_CONFIG_INIT_DONE;
 		goto done;
 	}
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c	Mon Sep 21 11:26:40 2009 -0400
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  *	dns_common.c
  */
@@ -33,6 +31,7 @@
 
 #pragma weak	dn_expand
 #pragma weak	res_ninit
+#pragma weak	res_ndestroy
 #pragma weak	res_nsearch
 #pragma weak	res_nclose
 #pragma weak	ns_get16
@@ -274,19 +273,6 @@
 }
 
 /*
- * __res_ndestroy is a simplified version of the non-public function
- * res_ndestroy in libresolv.so.2. Before res_ndestroy can be made
- * public, __res_ndestroy will be used to make sure the memory pointed
- * by statp->_u._ext.ext is freed after res_nclose() is called.
- */
-static void
-__res_ndestroy(res_state statp) {
-	res_nclose(statp);
-	if (statp->_u._ext.ext != NULL)
-		free(statp->_u._ext.ext);
-}
-
-/*
  * name_is_alias(aliases_ptr, name_ptr)
  * Verify name matches an alias in the provided aliases list.
  *
@@ -299,7 +285,7 @@
  * INPUT:
  *  aliases_ptr: space separated list of alias names.
  *  name_ptr: name to look for in aliases_ptr list.
- * RETURNS: NSS_SUCCESS or NSS_ERROR
+ * RETURNS: NSS_SUCCESS or NSS_NOTFOUND
  *  NSS_SUCCESS indicates that the name is listed in the collected aliases.
  */
 static nss_status_t
@@ -332,7 +318,7 @@
 		/* Step over separator character. */
 		while (*aliases_ptr == ' ') aliases_ptr++;
 	}
-	return (NSS_ERROR);
+	return (NSS_NOTFOUND);
 }
 
 /*
@@ -397,7 +383,7 @@
 	/* misc variables */
 	int		af;
 	char		*ap, *apc;
-	int		hlen = 0, alen, iplen, len;
+	int		hlen = 0, alen, iplen, len, isans;
 
 	statp = &stat;
 	(void) memset(statp, '\0', sizeof (struct __res_state));
@@ -414,14 +400,14 @@
 	blen = 0;
 	sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg);
 	if (sret != NSS_SUCCESS) {
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 
 	if (ipnode) {
 		/* initially only handle the simple cases */
 		if (arg.key.ipnode.flags != 0) {
-			__res_ndestroy(statp);
+			res_ndestroy(statp);
 			return (NSS_ERROR);
 		}
 		name = arg.key.ipnode.name;
@@ -439,11 +425,11 @@
 			pbuf->p_herrno = HOST_NOT_FOUND;
 			pbuf->p_status = NSS_NOTFOUND;
 			pbuf->data_len = 0;
-			__res_ndestroy(statp);
+			res_ndestroy(statp);
 			return (NSS_NOTFOUND);
 		}
 		/* else lookup error - handle in general code */
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 
@@ -456,23 +442,23 @@
 	qdcount = ntohs(hp->qdcount);
 	cp += HFIXEDSZ;
 	if (qdcount != 1) {
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN);
 	if (n < 0) {
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	} else
 		hlen = strlen(host);
 	/* no host name is an error, return */
 	if (hlen <= 0) {
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	cp += n + QFIXEDSZ;
 	if (cp > eom) {
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	while (ancount-- > 0 && cp < eom && blen < bsize) {
@@ -482,9 +468,10 @@
 			 * Check that the expanded name is either the
 			 * name we asked for or a learned alias.
 			 */
-			if (strncasecmp(host, ans, hlen) != 0 && (alen == 0 ||
-			    name_is_alias(aliases, ans) == NSS_ERROR)) {
-				__res_ndestroy(statp);
+			if ((isans = strncasecmp(host, ans, hlen)) != 0 &&
+			    (alen == 0 || name_is_alias(aliases, ans)
+			    == NSS_NOTFOUND)) {
+				res_ndestroy(statp);
 				return (NSS_ERROR);	/* spoof? */
 			}
 		}
@@ -494,7 +481,7 @@
 		cp += INT16SZ;
 		class = ns_get16(cp);			/* class */
 		cp += INT16SZ;
-		nttl = (nssuint_t)ns_get32(cp);	/* ttl in sec */
+		nttl = (nssuint_t)ns_get32(cp);		/* ttl in sec */
 		if (nttl < ttl)
 			ttl = nttl;
 		cp += INT32SZ;
@@ -507,34 +494,42 @@
 		eor = cp + n;
 		if (type == T_CNAME) {
 			/*
-			 * The name we looked up is really an alias
-			 * and the canonical name should be in the
-			 * RDATA.  A canonical name may have several
-			 * aliases but an alias should only have one
-			 * canonical name. However multiple CNAMEs and
-			 * CNAME chains do exist!  So for caching
-			 * purposes maintain the alias as the host
-			 * name, and the CNAME as an alias.
+			 * The name looked up is really an alias and the
+			 * canonical name should be in the RDATA.
+			 * A canonical name may have several aliases but an
+			 * alias should only have one canonical name.
+			 * However multiple CNAMEs and CNAME chains do exist!
+			 *
+			 * Just error out on attempted buffer overflow exploit,
+			 * generic code will syslog.
+			 *
 			 */
 			n = dn_expand(bom, eor, cp, aname, MAXHOSTNAMELEN);
-			if (n > 0) {
-				len = strlen(aname);
-				if (len > 0) {
+			if (n > 0 && (len = strlen(aname)) > 0) {
+				if (isans == 0) { /* host matched ans. */
 					/*
-					 * Just error out if there is an
-					 * attempted buffer overflow exploit
-					 * generic code will do a syslog
+					 * Append host to alias list.
 					 */
-					if (alen + len + 2 > NS_MAXMSG) {
-						__res_ndestroy(statp);
+					if (alen + hlen + 2 > NS_MAXMSG) {
+						res_ndestroy(statp);
 						return (NSS_ERROR);
 					}
 					*apc++ = ' ';
 					alen++;
-					(void) strlcpy(apc, aname, len + 1);
-					alen += len;
-					apc += len;
+					(void) strlcpy(apc, host,
+					    NS_MAXMSG - alen);
+					alen += hlen;
+					apc += hlen;
 				}
+				/*
+				 * Overwrite host with canonical name.
+				 */
+				if (strlcpy(host, aname, MAXHOSTNAMELEN) >=
+				    MAXHOSTNAMELEN) {
+					res_ndestroy(statp);
+					return (NSS_ERROR);
+				}
+				hlen = len;
 			}
 			cp += n;
 			continue;
@@ -552,7 +547,7 @@
 		af = (type == T_A ? AF_INET : AF_INET6);
 		np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN);
 		if (np == NULL) {
-			__res_ndestroy(statp);
+			res_ndestroy(statp);
 			return (NSS_ERROR);
 		}
 		cp += n;
@@ -563,7 +558,7 @@
 		if (alen > 0)
 			len++;
 		if (blen + len > bsize) {
-			__res_ndestroy(statp);
+			res_ndestroy(statp);
 			return (NSS_ERROR);
 		}
 		(void) strlcpy(bptr, np, bsize - blen);
@@ -589,7 +584,7 @@
 	/* still room? */
 	if (len + sizeof (nssuint_t) > pbuf->data_len) {
 		/* sigh, no, what happened? */
-		__res_ndestroy(statp);
+		res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	pbuf->ext_off = pbuf->data_off + len;
@@ -597,6 +592,6 @@
 	pbuf->data_len = blen;
 	pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off));
 	*pttl = ttl;
-	__res_ndestroy(statp);
+	res_ndestroy(statp);
 	return (NSS_SUCCESS);
 }
--- a/usr/src/lib/pyzfs/common/allow.py	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/lib/pyzfs/common/allow.py	Mon Sep 21 11:26:40 2009 -0400
@@ -322,7 +322,7 @@
 		if sys.argv[2] == "-h":
 			# hack to make "zfs allow -h" work
 			usage()
-		ds = zfs.dataset.Dataset(sys.argv[2])
+		ds = zfs.dataset.Dataset(sys.argv[2], snaps=False)
 
 		p = dict()
 		for (fs, raw) in ds.get_fsacl().items():
--- a/usr/src/pkgdefs/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -118,6 +118,7 @@
 	SUNWatu \
 	SUNWaudiocmi \
 	SUNWaudiohd \
+	SUNWaudiosolo \
 	SUNWaudiovia97 \
 	SUNWbfe	\
 	SUNWcakr.i \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+TMPLFILES += postinstall preremove
+
+.KEEP_STATE:
+
+all: $(FILES) depend
+install: all pkg
+
+include ../Makefile.targ
+include ../Makefile.prtarg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/depend	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,50 @@
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# This package information file defines software dependencies associated
+# with the pkg.  You can define three types of pkg dependencies with this file:
+#	 P indicates a prerequisite for installation
+#	 I indicates an incompatible package
+#	 R indicates a reverse dependency
+# <pkg.abbr> see pkginfo(4), PKG parameter
+# <name> see pkginfo(4), NAME parameter
+# <version> see pkginfo(4), VERSION parameter
+# <arch> see pkginfo(4), ARCH parameter
+# <type> <pkg.abbr> <name>
+# 	(<arch>)<version>
+# 	(<arch>)<version>
+# 	...
+# <type> <pkg.abbr> <name>
+# ...
+#
+
+P SUNWcar	Core Architecture, (Root)
+P SUNWcakr	Core Solaris Kernel Architecture (Root)
+P SUNWkvm	Core Architecture, (Kvm)
+P SUNWcsr	Core Solaris, (Root)
+P SUNWckr	Core Solaris Kernel (Root)
+P SUNWcnetr	Core Solaris Network Infrastructure (Root)
+P SUNWcsu	Core Solaris, (Usr)
+P SUNWcsd	Core Solaris Devices
+P SUNWcsl	Core Solaris Libraries
+P SUNWaudd	Audio Drivers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/pkginfo.tmpl	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,57 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# This required package information file describes characteristics of the
+# package, such as package abbreviation, full package name, package version,
+# and package architecture.
+#
+PKG="SUNWaudiosolo"
+NAME="ESS Solo-1 Audio Driver"
+ARCH="ISA"
+VERSION="ONVERS,REV=0.0.0"
+CATEGORY="system"
+DESC="SunOS audio device driver for ESS Solo-1"
+SUNW_PRODNAME="SunOS"
+SUNW_PRODVERS="RELEASE/VERSION"
+SUNW_PKGTYPE="root"
+MAXINST="1000"
+VENDOR="Sun Microsystems, Inc."
+HOTLINE="Please contact your local service provider"
+EMAIL=""
+CLASSES="none preserve"
+BASEDIR=/
+SUNW_PKGVERS="1.0"
+SUNW_PKG_ALLZONES="true"
+SUNW_PKG_HOLLOW="true"
+SUNW_PKG_THISZONE="false"
+#VSTOCK="<reserved by Release Engineering for package part #>"
+#ISTATES="<developer defined>"
+#RSTATES='<developer defined>'
+#ULIMIT="<developer defined>"
+#ORDER="<developer defined>"
+#PSTAMP="<developer defined>"
+#INTONLY="<developer defined>"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/postinstall.tmpl	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,34 @@
+#! /bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# SUNWaudiols postinstall script
+
+include drv_utils
+
+AUDIOSOLO_ALIASES="\
+	\"pci125d,1969\"	\
+	"
+
+pkg_drvadd -i "${AUDIOSOLO_ALIASES}" audiosolo || exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/preremove.tmpl	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,30 @@
+#! /bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# SUNWaudiosolo preremove script
+
+include drv_utils
+
+pkg_drvrem audiosolo || exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/prototype_com	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...>	# where to find pkg objects
+#!include <filename>			# include another 'prototype' file
+#!default <mode> <owner> <group>	# default used if not specified on entry
+#!<param>=<value>			# puts parameter in pkg environment
+
+# packaging files
+i pkginfo
+i copyright
+i depend
+i postinstall
+i preremove
+#
+# source locations relative to the prototype file
+#
+# SUNWaudiosolo
+#
+d none kernel 755 root sys
+d none kernel/drv 755 root sys
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/pkgdefs/SUNWaudiosolo/prototype_i386	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,48 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# This required package information file contains a list of package contents.
+# The 'pkgmk' command uses this file to identify the contents of a package
+# and their location on the development machine when building the package.
+# Can be created via a text editor or through use of the 'pkgproto' command.
+
+#!search <pathname pathname ...>	# where to find pkg objects
+#!include <filename>			# include another 'prototype' file
+#!default <mode> <owner> <group>	# default used if not specified on entry
+#!<param>=<value>			# puts parameter in pkg environment
+
+#
+# Include ISA independent files (prototype_com)
+#
+!include prototype_com
+#
+# List files which are i386 specific here
+#
+# source locations relative to the prototype file
+#
+# SUNWaudiols
+#
+f none kernel/drv/audiosolo 755 root sys
+d none kernel/drv/amd64 755 root sys
+f none kernel/drv/amd64/audiosolo 755 root sys
--- a/usr/src/pkgdefs/SUNWcakr.i/prototype_com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWcakr.i/prototype_com	Mon Sep 21 11:26:40 2009 -0400
@@ -68,6 +68,7 @@
 f none platform/i86pc/kernel/drv/acpippm 755 root sys
 f none platform/i86pc/kernel/drv/acpippm.conf 644 root sys
 f none platform/i86pc/kernel/drv/amd64/acpinex 755 root sys
+f none platform/i86pc/kernel/drv/amd64/amd_iommu 755 root sys
 f none platform/i86pc/kernel/drv/amd64/ppm 755 root sys
 f none platform/i86pc/kernel/drv/amd64/isa 755 root sys
 f none platform/i86pc/kernel/drv/amd64/npe 755 root sys
@@ -75,6 +76,8 @@
 f none platform/i86pc/kernel/drv/amd64/pit_beep 755 root sys
 f none platform/i86pc/kernel/drv/amd64/rootnex 755 root sys
 f none platform/i86pc/kernel/drv/acpinex 755 root sys
+f none platform/i86pc/kernel/drv/amd_iommu 755 root sys
+f none platform/i86pc/kernel/drv/amd_iommu.conf 644 root sys
 f none platform/i86pc/kernel/drv/cpudrv 755 root sys
 f none platform/i86pc/kernel/drv/isa 755 root sys
 f none platform/i86pc/kernel/drv/npe 755 root sys
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386	Mon Sep 21 11:26:40 2009 -0400
@@ -68,8 +68,6 @@
 f none kernel/drv/acpi_drv 755 root sys
 f none kernel/drv/acpi_drv.conf 644 root sys
 f none kernel/drv/acpi_toshiba 755 root sys
-f none kernel/drv/amd_iommu 755 root sys
-f none kernel/drv/amd_iommu.conf 644 root sys
 f none kernel/drv/bl 755 root sys
 f none kernel/drv/bmc 755 root sys
 f none kernel/drv/bmc.conf 644 root sys
@@ -296,7 +294,6 @@
 f none kernel/drv/amd64/arp 755 root sys
 f none kernel/drv/amd64/acpi_drv 755 root sys
 f none kernel/drv/amd64/acpi_toshiba 755 root sys
-f none kernel/drv/amd64/amd_iommu 755 root sys
 f none kernel/drv/amd64/bl 755 root sys
 f none kernel/drv/amd64/bmc 755 root sys
 f none kernel/drv/amd64/bridge 755 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_i386	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWhea/prototype_i386	Mon Sep 21 11:26:40 2009 -0400
@@ -75,7 +75,6 @@
 f none usr/include/ia32/sys/traptrace.h 644 root bin
 f none usr/include/sys/kdi_regs.h 644 root bin
 f none usr/include/stack_unwind.h 644 root bin
-f none usr/include/sys/amd_iommu.h 644 root bin
 f none usr/include/sys/bootregs.h 644 root bin
 f none usr/include/sys/bootsvcs.h 644 root bin
 f none usr/include/sys/controlregs.h 644 root bin
@@ -121,6 +120,7 @@
 d none usr/platform/i86pc/include/sys 755 root bin
 f none usr/platform/i86pc/include/sys/asm_misc.h 644 root bin
 f none usr/platform/i86pc/include/sys/acpidev.h 644 root bin
+f none usr/platform/i86pc/include/sys/amd_iommu.h 644 root bin
 f none usr/platform/i86pc/include/sys/clock.h 644 root bin
 f none usr/platform/i86pc/include/sys/cram.h 644 root bin
 f none usr/platform/i86pc/include/sys/debug_info.h 644 root bin
--- a/usr/src/pkgdefs/SUNWmdb/prototype_i386	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_i386	Mon Sep 21 11:26:40 2009 -0400
@@ -81,6 +81,7 @@
 f none usr/lib/mdb/kvm/amd64/nfs.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/ptm.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/random.so 555 root sys
+f none usr/lib/mdb/kvm/amd64/rootnex.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/s1394.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/sata.so 555 root sys
 f none usr/lib/mdb/kvm/amd64/scsi_vhci.so 555 root sys
@@ -117,6 +118,7 @@
 f none usr/lib/mdb/kvm/nfs.so 555 root sys
 f none usr/lib/mdb/kvm/ptm.so 555 root sys
 f none usr/lib/mdb/kvm/random.so 555 root sys
+f none usr/lib/mdb/kvm/rootnex.so 555 root sys
 f none usr/lib/mdb/kvm/s1394.so 555 root sys
 f none usr/lib/mdb/kvm/sata.so 555 root sys
 f none usr/lib/mdb/kvm/scsi_vhci.so 555 root sys
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_i386	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_i386	Mon Sep 21 11:26:40 2009 -0400
@@ -50,6 +50,7 @@
 f none kernel/kmdb/amd64/nfs 555 root sys
 f none kernel/kmdb/amd64/ptm 555 root sys
 f none kernel/kmdb/amd64/random 555 root sys
+f none kernel/kmdb/amd64/rootnex 555 root sys
 f none kernel/kmdb/amd64/s1394 555 root sys
 f none kernel/kmdb/amd64/sata 555 root sys
 f none kernel/kmdb/amd64/scsi_vhci 555 root sys
@@ -85,6 +86,7 @@
 f none kernel/kmdb/nfs 555 root sys
 f none kernel/kmdb/ptm 555 root sys
 f none kernel/kmdb/random 555 root sys
+f none kernel/kmdb/rootnex 555 root sys
 f none kernel/kmdb/s1394 555 root sys
 f none kernel/kmdb/sata 555 root sys
 f none kernel/kmdb/scsi_vhci 555 root sys
--- a/usr/src/pkgdefs/SUNWuedg/prototype_com	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/pkgdefs/SUNWuedg/prototype_com	Mon Sep 21 11:26:40 2009 -0400
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -21,12 +20,10 @@
 #
 #
 #
-# Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
-#ident	"%Z%%M%	%I%	%E% SMI"
-
 # This required package information file contains a list of package contents.
 # The 'pkgmk' command uses this file to identify the contents of a package
 # and their location on the development machine when building the package.
@@ -47,3 +44,4 @@
 i preremove
 d none kernel 0755 root sys
 d none kernel/drv 0755 root sys
+e none kernel/drv/usbser_edge.conf 0644 root sys
--- a/usr/src/tools/scripts/bfu.sh	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/tools/scripts/bfu.sh	Mon Sep 21 11:26:40 2009 -0400
@@ -7888,6 +7888,24 @@
 	rm -f $root/dev/rsr[0-9]*
 
 	#
+	# Remove old amd_iommu driver
+	#
+
+	#
+	# old: need to remove going forwards:
+	#
+	rm -f $root/kernel/drv/amd_iommu
+	rm -f $root/kernel/drv/amd_iommu.conf
+	rm -f $root/kernel/drv/amd64/amd_iommu
+
+	#
+	# new: need to remove going backwards:
+	#
+	rm -f $root/platform/i86pc/kernel/drv/amd_iommu.conf
+	rm -f $root/platform/i86pc/kernel/drv/amd_iommu
+	rm -f $root/platform/i86pc/kernel/drv/amd64/amd_iommu
+
+	#
 	# The pkg* commands should not be used after this point and before
 	# archive extraction as libcrypto/libssl may not be available.
 	#
--- a/usr/src/uts/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -177,7 +177,7 @@
 # other directories that should be included and do not yet have the
 # necessary Makefile support.  See 6414855.)
 #
-DYNHDRDIRS = common/rpcsvc common/idmap
+DYNHDRDIRS = common/rpcsvc common/idmap common/sys
 
 sparc_HDRDIRS= sun/sys
 i386_HDRDIRS= i86pc/vm i86xpv/vm
--- a/usr/src/uts/common/Makefile.files	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/Makefile.files	Mon Sep 21 11:26:40 2009 -0400
@@ -452,6 +452,8 @@
 
 AUDIOPCI_OBJS += audiopci.o
 
+AUDIOSOLO_OBJS += audiosolo.o
+
 AUDIOTS_OBJS +=	audiots.o
 
 AC97_OBJS += ac97.o ac97_ad.o ac97_alc.o ac97_cmi.o
--- a/usr/src/uts/common/Makefile.rules	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/Makefile.rules	Mon Sep 21 11:26:40 2009 -0400
@@ -592,6 +592,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/common/io/audio/drv/audiosolo/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/common/io/audio/drv/audiots/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -1862,6 +1866,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/audio/drv/audiop16x/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/audio/drv/audiosolo/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/io/audio/drv/audiots/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- a/usr/src/uts/common/fs/nfs/nfs4_vfsops.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/fs/nfs/nfs4_vfsops.c	Mon Sep 21 11:26:40 2009 -0400
@@ -549,7 +549,7 @@
 		goto errout;
 	}
 
-	nargs->addr = kmem_alloc(sizeof (struct netbuf), KM_SLEEP);
+	nargs->addr = kmem_zalloc(sizeof (struct netbuf), KM_SLEEP);
 	userbufptr = STRUCT_FGETP(addr_tmp, buf);
 	addr.len = STRUCT_FGET(addr_tmp, len);
 	addr.buf = kmem_alloc(addr.len, KM_SLEEP);
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2017,6 +2017,10 @@
 	    ds->ds_reserved);
 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_GUID,
 	    ds->ds_phys->ds_guid);
+	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_UNIQUE,
+	    dsl_dataset_unique(ds));
+	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_OBJSETID,
+	    ds->ds_object);
 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USERREFS, ds->ds_userrefs);
 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
 	    DS_IS_DEFER_DESTROY(ds) ? 1 : 0);
--- a/usr/src/uts/common/fs/zfs/spa.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/spa.c	Mon Sep 21 11:26:40 2009 -0400
@@ -3683,7 +3683,17 @@
 	if (vd->vdev_remove_wanted) {
 		vd->vdev_remove_wanted = 0;
 		vdev_set_state(vd, B_FALSE, VDEV_STATE_REMOVED, VDEV_AUX_NONE);
-		vdev_clear(spa, vd);
+
+		/*
+		 * We want to clear the stats, but we don't want to do a full
+		 * vdev_clear() as that will cause us to throw away
+		 * degraded/faulted state as well as attempt to reopen the
+		 * device, all of which is a waste.
+		 */
+		vd->vdev_stat.vs_read_errors = 0;
+		vd->vdev_stat.vs_write_errors = 0;
+		vd->vdev_stat.vs_checksum_errors = 0;
+
 		vdev_state_dirty(vd->vdev_top);
 	}
 
--- a/usr/src/uts/common/fs/zfs/vdev_disk.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/vdev_disk.c	Mon Sep 21 11:26:40 2009 -0400
@@ -430,12 +430,19 @@
 	 * asynchronous removal of the device. Otherwise, probe the device and
 	 * make sure it's still accessible.
 	 */
-	if (zio->io_error == EIO) {
+	if (zio->io_error == EIO && !vd->vdev_remove_wanted) {
 		vdev_disk_t *dvd = vd->vdev_tsd;
 		int state = DKIO_NONE;
 
 		if (ldi_ioctl(dvd->vd_lh, DKIOCSTATE, (intptr_t)&state,
 		    FKIOCTL, kcred, NULL) == 0 && state != DKIO_INSERTED) {
+			/*
+			 * We post the resource as soon as possible, instead of
+			 * when the async removal actually happens, because the
+			 * DE is using this information to discard previous I/O
+			 * errors.
+			 */
+			zfs_post_remove(zio->io_spa, vd);
 			vd->vdev_remove_wanted = B_TRUE;
 			spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE);
 		}
--- a/usr/src/uts/common/fs/zfs/zfs_fm.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/fs/zfs/zfs_fm.c	Mon Sep 21 11:26:40 2009 -0400
@@ -147,9 +147,7 @@
 			 * not yet been asynchronously placed into the REMOVED
 			 * state.
 			 */
-			if (zio->io_vd == vd &&
-			    !vdev_accessible(vd, zio) &&
-			    strcmp(subclass, FM_EREPORT_ZFS_PROBE_FAILURE) != 0)
+			if (zio->io_vd == vd && !vdev_accessible(vd, zio))
 				return;
 
 			/*
@@ -164,6 +162,15 @@
 		}
 	}
 
+	/*
+	 * For probe failure, we want to avoid posting ereports if we've
+	 * already removed the device in the meantime.
+	 */
+	if (vd != NULL &&
+	    strcmp(subclass, FM_EREPORT_ZFS_PROBE_FAILURE) == 0 &&
+	    (vd->vdev_remove_wanted || vd->vdev_state == VDEV_STATE_REMOVED))
+		return;
+
 	if ((ereport = fm_nvlist_create(NULL)) == NULL)
 		return;
 
@@ -338,6 +345,9 @@
 	nvlist_t *resource;
 	char class[64];
 
+	if (spa->spa_load_state == SPA_LOAD_TRYIMPORT)
+		return;
+
 	if ((resource = fm_nvlist_create(NULL)) == NULL)
 		return;
 
--- a/usr/src/uts/common/inet/ip/ip.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/ip/ip.c	Mon Sep 21 11:26:40 2009 -0400
@@ -13947,8 +13947,8 @@
 		 * ire_cache_lookup() can return ire of IRE_LOCAL in
 		 * transient cases. In such case, just drop the packet
 		 */
-		if (ire->ire_type != IRE_CACHE)
-			goto drop;
+		if (ire != NULL && ire->ire_type != IRE_CACHE)
+			goto indiscard;
 	}
 
 	/*
--- a/usr/src/uts/common/inet/ipf/fil.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/ipf/fil.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2151,6 +2151,7 @@
 u_32_t *passp;
 {
 	frentry_t *fr;
+	fr_info_t *fc;
 	u_32_t pass;
 	int out;
 	ipf_stack_t *ifs = fin->fin_ifs;
@@ -2164,13 +2165,51 @@
 	else
 #endif
 		fin->fin_fr = ifs->ifs_ipfilter[out][ifs->ifs_fr_active];
-	if (fin->fin_fr != NULL)
+
+	/*
+	 * If there are no rules loaded skip all checks and return.
+	 */
+	if (fin->fin_fr == NULL) {
+
+		if ((pass & FR_NOMATCH)) {
+			IPF_BUMP(ifs->ifs_frstats[out].fr_nom);
+		}
+
+		return (NULL);
+	}
+
+	fc = &ifs->ifs_frcache[out][CACHE_HASH(fin)];
+	READ_ENTER(&ifs->ifs_ipf_frcache);
+	if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) {
+		/*
+		 * copy cached data so we can unlock the mutexes earlier.
+		 */
+		bcopy((char *)fc, (char *)fin, FI_COPYSIZE);
+		RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+		IPF_BUMP(ifs->ifs_frstats[out].fr_chit);
+
+		if ((fr = fin->fin_fr) != NULL) {
+			IPF_BUMP(fr->fr_hits);
+			pass = fr->fr_flags;
+		}
+	} else {
+		RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+
 		pass = fr_scanlist(fin, ifs->ifs_fr_pass);
 
+		if (((pass & FR_KEEPSTATE) == 0) &&
+		    ((fin->fin_flx & FI_DONTCACHE) == 0)) {
+			WRITE_ENTER(&ifs->ifs_ipf_frcache);
+			bcopy((char *)fin, (char *)fc, FI_COPYSIZE);
+			RWLOCK_EXIT(&ifs->ifs_ipf_frcache);
+		}
+
+		fr = fin->fin_fr;
+	}
+
 	if ((pass & FR_NOMATCH)) {
 		IPF_BUMP(ifs->ifs_frstats[out].fr_nom);
 	}
-	fr = fin->fin_fr;
 
 	/*
 	 * Apply packets per second rate-limiting to a rule as required.
@@ -3520,6 +3559,7 @@
 	int flushed = 0, set;
 
 	WRITE_ENTER(&ifs->ifs_ipf_mutex);
+	bzero((char *)ifs->ifs_frcache, sizeof (ifs->ifs_frcache));
 
 	set = ifs->ifs_fr_active;
 	if ((flags & FR_INACTIVE) == FR_INACTIVE)
@@ -4504,6 +4544,7 @@
 		fp->fr_cksum += *p;
 
 	WRITE_ENTER(&ifs->ifs_ipf_mutex);
+	bzero((char *)ifs->ifs_frcache, sizeof (ifs->ifs_frcache));
 
 	for (; (f = *ftail) != NULL; ftail = &f->fr_next) {
 		if ((fp->fr_cksum != f->fr_cksum) ||
--- a/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/ipf/ip_fil_solaris.c	Mon Sep 21 11:26:40 2009 -0400
@@ -260,6 +260,7 @@
 	ifs->ifs_fr_pass = (IPF_DEFAULT_PASS)|FR_NOMATCH;
 #endif
 
+	bzero((char *)ifs->ifs_frcache, sizeof(ifs->ifs_frcache));
 	MUTEX_INIT(&ifs->ifs_ipf_rw, "ipf rw mutex");
 	MUTEX_INIT(&ifs->ifs_ipf_timeoutlock, "ipf timeout lock mutex");
 	RWLOCK_INIT(&ifs->ifs_ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
@@ -643,6 +644,8 @@
 			error = EPERM;
 		else {
 			WRITE_ENTER(&ifs->ifs_ipf_mutex);
+			bzero((char *)ifs->ifs_frcache,
+			    sizeof (ifs->ifs_frcache));
 			error = COPYOUT((caddr_t)&ifs->ifs_fr_active,
 					(caddr_t)data,
 					sizeof(ifs->ifs_fr_active));
--- a/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/ipf/netinet/ipf_stack.h	Mon Sep 21 11:26:40 2009 -0400
@@ -45,6 +45,7 @@
 	zoneid_t		ifs_zone;
 
 	/* ipf module */
+	fr_info_t		ifs_frcache[2][8];
 
 	filterstats_t		ifs_frstats[2];
 	frentry_t		*ifs_ipfilter[2][2];
@@ -91,6 +92,7 @@
 	ipfmutex_t	ifs_ipf_timeoutlock;
 	ipfrwlock_t	ifs_ipf_mutex;
 	ipfrwlock_t	ifs_ipf_global;
+	ipfrwlock_t	ifs_ipf_frcache;
 	ipfrwlock_t	ifs_ip_poolrw;
 	ipfrwlock_t	ifs_ipf_frag;
 	ipfrwlock_t	ifs_ipf_state;
--- a/usr/src/uts/common/inet/ipf/solaris.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/ipf/solaris.c	Mon Sep 21 11:26:40 2009 -0400
@@ -3,7 +3,7 @@
  *
  * See the IPFILTER.LICENCE file for details on licencing.
  *
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -396,7 +396,7 @@
 	 */
 	RWLOCK_INIT(&ifs->ifs_ipf_global, "ipf filter load/unload mutex");
 	RWLOCK_INIT(&ifs->ifs_ipf_mutex, "ipf filter rwlock");
-
+	RWLOCK_INIT(&ifs->ifs_ipf_frcache, "ipf cache rwlock");
 	ifs->ifs_netid = id;
 	ifs->ifs_zone = net_getzoneidbynetid(id);
 	ipf_kstat_init(ifs);
@@ -553,6 +553,7 @@
 
 	RWLOCK_EXIT(&ifs->ifs_ipf_global);
 	RW_DESTROY(&ifs->ifs_ipf_mutex);
+	RW_DESTROY(&ifs->ifs_ipf_frcache);
 	RW_DESTROY(&ifs->ifs_ipf_global);
 
 	KFREE(ifs);
--- a/usr/src/uts/common/inet/tcp/tcp.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Mon Sep 21 11:26:40 2009 -0400
@@ -7834,12 +7834,11 @@
 
 	PRESERVE(tcp->tcp_family);
 	if (tcp->tcp_family == AF_INET6) {
-		tcp->tcp_ipversion = IPV6_VERSION;
 		tcp->tcp_mss = tcps->tcps_mss_def_ipv6;
 	} else {
-		tcp->tcp_ipversion = IPV4_VERSION;
 		tcp->tcp_mss = tcps->tcps_mss_def_ipv4;
 	}
+	PRESERVE(tcp->tcp_ipversion);		/* Init in tcp_init_values */
 
 	tcp->tcp_bound_if = 0;
 	tcp->tcp_ipv6_recvancillary = 0;
@@ -7983,7 +7982,7 @@
 	tcp->tcp_loopback_peer = NULL;
 
 	/* Initialize the header template */
-	if (tcp->tcp_ipversion == IPV4_VERSION) {
+	if (tcp->tcp_family == AF_INET) {
 		err = tcp_header_init_ipv4(tcp);
 	} else {
 		err = tcp_header_init_ipv6(tcp);
@@ -8048,9 +8047,19 @@
 	connp->conn_mlp_type = mlptSingle;
 	connp->conn_ulp_labeled = !is_system_labeled();
 	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
+
+	/*
+	 * tcp_do_get{sock,peer}name constructs the sockaddr from the
+	 * ip header, and decides which header to use based on ip version.
+	 * That operation happens outside the squeue, so we hold the lock
+	 * here to ensure that the ip version and header remain consistent.
+	 */
+	mutex_enter(&connp->conn_lock);
+	tcp->tcp_ipversion = IPV4_VERSION;
 	tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
 	tcp->tcp_ip6h = NULL;
-	tcp->tcp_ipversion = IPV4_VERSION;
+	mutex_exit(&connp->conn_lock);
+
 	tcp->tcp_hdr_len = sizeof (ipha_t) + sizeof (tcph_t);
 	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
 	tcp->tcp_ip_hdr_len = sizeof (ipha_t);
@@ -8120,12 +8129,21 @@
 	connp->conn_ulp_labeled = !is_system_labeled();
 
 	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
-	tcp->tcp_ipversion = IPV6_VERSION;
 	tcp->tcp_hdr_len = IPV6_HDR_LEN + sizeof (tcph_t);
 	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
 	tcp->tcp_ip_hdr_len = IPV6_HDR_LEN;
+
+	/*
+	 * tcp_do_get{sock,peer}name constructs the sockaddr from the
+	 * ip header, and decides which header to use based on ip version.
+	 * That operation happens outside the squeue, so we hold the lock
+	 * here to ensure that the ip version and header remain consistent.
+	 */
+	mutex_enter(&connp->conn_lock);
+	tcp->tcp_ipversion = IPV6_VERSION;
 	tcp->tcp_ip6h = (ip6_t *)tcp->tcp_iphc;
 	tcp->tcp_ipha = NULL;
+	mutex_exit(&connp->conn_lock);
 
 	/* Initialize the header template */
 
@@ -17884,12 +17902,14 @@
 		sin6->sin6_family = AF_INET6;
 		if (tcp->tcp_state >= TCPS_BOUND) {
 			sin6->sin6_port = tcp->tcp_lport;
+			mutex_enter(&tcp->tcp_connp->conn_lock);
 			if (tcp->tcp_ipversion == IPV4_VERSION) {
 				IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
 				    &sin6->sin6_addr);
 			} else {
 				sin6->sin6_addr = tcp->tcp_ip6h->ip6_src;
 			}
+			mutex_exit(&tcp->tcp_connp->conn_lock);
 		}
 		*salenp = sizeof (sin6_t);
 		break;
@@ -17930,10 +17950,12 @@
 		sin6->sin6_family = AF_INET6;
 		sin6->sin6_port = tcp->tcp_fport;
 		sin6->sin6_addr = tcp->tcp_remote_v6;
+		mutex_enter(&tcp->tcp_connp->conn_lock);
 		if (tcp->tcp_ipversion == IPV6_VERSION) {
 			sin6->sin6_flowinfo = tcp->tcp_ip6h->ip6_vcf &
 			    ~IPV6_VERS_AND_FLOW_MASK;
 		}
+		mutex_exit(&tcp->tcp_connp->conn_lock);
 		*salenp = sizeof (sin6_t);
 		break;
 	}
@@ -26090,7 +26112,7 @@
 	in_port_t requested_port;
 	ipaddr_t	v4addr;
 	in6_addr_t	v6addr;
-	uint_t	origipversion;
+	uint_t	ipversion;
 	int	error = 0;
 
 	ASSERT((uintptr_t)len <= (uintptr_t)INT_MAX);
@@ -26104,7 +26126,6 @@
 		}
 		return (-TOUTSTATE);
 	}
-	origipversion = tcp->tcp_ipversion;
 
 	ASSERT(sa != NULL && len != 0);
 
@@ -26132,7 +26153,7 @@
 			return (EAFNOSUPPORT);
 		}
 		requested_port = ntohs(sin->sin_port);
-		tcp->tcp_ipversion = IPV4_VERSION;
+		ipversion = IPV4_VERSION;
 		v4addr = sin->sin_addr.s_addr;
 		IN6_IPADDR_TO_V4MAPPED(v4addr, &v6addr);
 		break;
@@ -26144,7 +26165,7 @@
 			return (EAFNOSUPPORT);
 		}
 		requested_port = ntohs(sin6->sin6_port);
-		tcp->tcp_ipversion = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ?
+		ipversion = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ?
 		    IPV4_VERSION : IPV6_VERSION;
 		v6addr = sin6->sin6_addr;
 		break;
@@ -26161,9 +26182,9 @@
 	tcp->tcp_bound_source_v6 = v6addr;
 
 	/* Check for change in ipversion */
-	if (origipversion != tcp->tcp_ipversion) {
+	if (tcp->tcp_ipversion != ipversion) {
 		ASSERT(tcp->tcp_family == AF_INET6);
-		error = tcp->tcp_ipversion == IPV6_VERSION ?
+		error = (ipversion == IPV6_VERSION) ?
 		    tcp_header_init_ipv6(tcp) : tcp_header_init_ipv4(tcp);
 		if (error) {
 			return (ENOMEM);
@@ -27075,14 +27096,12 @@
 				sin = (sin_t *)&addr;
 				*sin = sin_null;
 				sin->sin_family = AF_INET;
-				tcp->tcp_ipversion = IPV4_VERSION;
 			} else {
 				ASSERT(tcp->tcp_family == AF_INET6);
 				len = sizeof (sin6_t);
 				sin6 = (sin6_t *)&addr;
 				*sin6 = sin6_null;
 				sin6->sin6_family = AF_INET6;
-				tcp->tcp_ipversion = IPV6_VERSION;
 			}
 			sa = (struct sockaddr *)&addr;
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/io/audio/drv/audiosolo/audiosolo.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (C) 4Front Technologies 1996-2008.
+ */
+
+#include <sys/audio/audio_driver.h>
+#include <sys/note.h>
+#include <sys/pci.h>
+#include <sys/stdbool.h>
+
+
+/*
+ * NB: The Solo-1 is a bit schizophrenic compared to most devices.
+ * It has two separate DMA engines for PCM data.  The first can do
+ * either capture or playback, and supports various Sound Blaster
+ * compatibility features.  The second is dedicated to playback.  The
+ * two engines have very little in common when it comes to programming
+ * them.
+ *
+ * We configure engine 1 for record, and engine 2 for playback.  Both
+ * are configured for 48 kHz stereo 16-bit signed PCM.
+ */
+
+/*
+ * ESS Solo-1 only implements the low 24-bits on Audio1, and requires
+ * 64KB alignment.  For Audio2, it implements the full 32-bit address
+ * space, but requires a 1MB address boundary.  Audio1 is used for
+ * recording, and Audio2 is used for playback.
+ */
+static struct ddi_dma_attr dma_attr_audio1 = {
+	DMA_ATTR_VERSION,	/* dma_attr_version */
+	0x0,			/* dma_attr_addr_lo */
+	0x00ffffffU,		/* dma_attr_addr_hi */
+	0xffff,			/* dma_attr_count_max */
+	0x10000,		/* dma_attr_align */
+	0x7f,			/* dma_attr_burstsizes */
+	0x4,			/* dma_attr_minxfer */
+	0xffff,			/* dma_attr_maxxfer */
+	0xffff,			/* dma_attr_seg */
+	0x1,			/* dma_attr_sgllen */
+	0x1,			/* dma_attr_granular */
+	0			/* dma_attr_flags */
+};
+
+static struct ddi_dma_attr dma_attr_audio2 = {
+	DMA_ATTR_VERSION,	/* dma_attr_version */
+	0x0,			/* dma_attr_addr_lo */
+	0xffffffffU,		/* dma_attr_addr_hi */
+	0xfff0,			/* dma_attr_count_max */
+	0x100000,		/* dma_attr_align */
+	0x7f,			/* dma_attr_burstsizes */
+	0x4,			/* dma_attr_minxfer */
+	0xfff0,			/* dma_attr_maxxfer */
+	0xffff,			/* dma_attr_seg */
+	0x1,			/* dma_attr_sgllen */
+	0x1,			/* dma_attr_granular */
+	0			/* dma_attr_flags */
+};
+
+static ddi_device_acc_attr_t acc_attr = {
+	DDI_DEVICE_ATTR_V0,
+	DDI_STRUCTURE_LE_ACC,
+	DDI_STRICTORDER_ACC
+};
+
+static ddi_device_acc_attr_t buf_attr = {
+	DDI_DEVICE_ATTR_V0,
+	DDI_NEVERSWAP_ACC,
+	DDI_STRICTORDER_ACC
+};
+
+
+/*
+ * For the sake of simplicity, this driver fixes a few parameters with
+ * constants.  If you want these values to be tunable, upgrade to a
+ * nicer and newer device.  This is all tuned for 100 Hz (10
+ * millisecs) latency.
+ */
+#define	SOLO_RATE	48000
+#define	SOLO_INTRS	100
+#define	SOLO_FRAGFR	(SOLO_RATE / SOLO_INTRS)
+#define	SOLO_NFRAGS	8
+#define	SOLO_NCHAN	2
+#define	SOLO_SAMPSZ	2
+#define	SOLO_FRAGSZ	(SOLO_FRAGFR * (SOLO_NCHAN * SOLO_SAMPSZ))
+#define	SOLO_BUFFR	(SOLO_NFRAGS * SOLO_FRAGFR)
+#define	SOLO_BUFSZ	(SOLO_NFRAGS * SOLO_FRAGSZ)
+
+#define	INPUT_MIC	0
+#define	INPUT_LINE	1
+#define	INPUT_CD	2
+#define	INPUT_AUX	3
+#define	INPUT_MONO	4
+#define	INSRCS		0x1f		/* bits 0-4 */
+
+#define	DRVNAME		"audiosolo"
+
+static const char *solo_insrcs[] = {
+	AUDIO_PORT_MIC,
+	AUDIO_PORT_LINEIN,
+	AUDIO_PORT_CD,
+	AUDIO_PORT_AUX1IN,
+	AUDIO_PORT_AUX2IN,	/* this is really mono-in */
+	NULL
+};
+
+typedef struct solo_regs {
+	ddi_acc_handle_t	acch;
+	caddr_t			base;
+} solo_regs_t;
+
+typedef struct solo_engine {
+	struct solo_dev		*dev;
+	audio_engine_t		*engine;
+	ddi_dma_handle_t	dmah;
+	ddi_acc_handle_t	acch;
+	caddr_t			kaddr;
+	uint32_t		paddr;
+
+	bool			started;
+	uint64_t		count;
+	uint16_t		offset;
+	int			syncdir;
+	int			format;
+	bool			swapped;
+
+	void			(*start)(struct solo_engine *);
+	void			(*stop)(struct solo_engine *);
+	void			(*update)(struct solo_engine *);
+} solo_engine_t;
+
+typedef enum {
+	CTL_FRONT = 0,
+	CTL_VOLUME,
+	CTL_MIC,
+	CTL_LINE,
+	CTL_CD,
+	CTL_AUX,
+	CTL_MONO,
+	CTL_MICBOOST,
+	CTL_RECGAIN,
+	CTL_RECSRC,
+	CTL_MONSRC,
+	CTL_SPEAKER,
+	CTL_LOOPBACK,
+	CTL_NUM,			/* must be last */
+} solo_ctrl_num_t;
+
+typedef struct solo_ctrl {
+	struct solo_dev		*dev;
+	audio_ctrl_t		*ctrl;
+	solo_ctrl_num_t		num;
+	uint64_t		val;
+} solo_ctrl_t;
+
+typedef struct solo_dev {
+	dev_info_t		*dip;
+	audio_dev_t		*adev;
+	kmutex_t		mutex;
+	ddi_intr_handle_t	ihandle;
+
+	bool			suspended;
+
+	/*
+	 * Audio engines
+	 */
+	solo_engine_t		rec;
+	solo_engine_t		play;
+	uint32_t		last_capture;
+
+	/*
+	 * Controls.
+	 */
+	solo_ctrl_t		ctrls[CTL_NUM];
+
+	/*
+	 * Mapped registers
+	 */
+	ddi_acc_handle_t	pcih;
+	solo_regs_t		io;
+	solo_regs_t		sb;
+	solo_regs_t		vc;
+
+} solo_dev_t;
+
+/*
+ * Common code for the pcm function
+ *
+ * solo_cmd write a single byte to the CMD port.
+ * solo_cmd1 write a CMD + 1 byte arg
+ * ess_get_byte returns a single byte from the DSP data port
+ *
+ * solo_write is actually solo_cmd1
+ * solo_read access ext. regs via solo_cmd(0xc0, reg) followed by solo_get_byte
+ */
+
+#define	PORT_RD8(port, regno)		\
+	ddi_get8(port.acch, (void *)(port.base + (regno)))
+#define	PORT_RD16(port, regno)		\
+	ddi_get16(port.acch, (void *)(port.base + (regno)))
+#define	PORT_RD32(port, regno)		\
+	ddi_get32(port.acch, (void *)(port.base + (regno)))
+#define	PORT_WR8(port, regno, data)	\
+	ddi_put8(port.acch, (void *)(port.base + (regno)), data)
+#define	PORT_WR16(port, regno, data)	\
+	ddi_put16(port.acch, (void *)(port.base + (regno)), data)
+#define	PORT_WR32(port, regno, data)	\
+	ddi_put32(port.acch, (void *)(port.base + (regno)), data)
+
+static bool
+solo_dspready(solo_dev_t *dev)
+{
+	return ((PORT_RD8(dev->sb, 0xc) & 0x80) == 0 ? true : false);
+}
+
+static bool
+solo_dspwr(solo_dev_t *dev, uint8_t val)
+{
+	int  i;
+
+	for (i = 0; i < 1000; i++) {
+		if (solo_dspready(dev)) {
+			PORT_WR8(dev->sb, 0xc, val);
+			return (true);
+		}
+		if (i > 10)
+			drv_usecwait((i > 100)? 1000 : 10);
+	}
+	audio_dev_warn(dev->adev, "solo_dspwr(0x%02x) timed out", val);
+	return (false);
+}
+
+static bool
+solo_cmd(solo_dev_t *dev, uint8_t val)
+{
+	return (solo_dspwr(dev, val));
+}
+
+static void
+solo_cmd1(solo_dev_t *dev, uint8_t cmd, uint8_t val)
+{
+	if (solo_dspwr(dev, cmd)) {
+		(void) solo_dspwr(dev, val);
+	}
+}
+
+static void
+solo_setmixer(solo_dev_t *dev, uint8_t port, uint8_t value)
+{
+	PORT_WR8(dev->sb, 0x4, port); /* Select register */
+	drv_usecwait(10);
+	PORT_WR8(dev->sb, 0x5, value);
+	drv_usecwait(10);
+}
+
+static uint8_t
+solo_getmixer(solo_dev_t *dev, uint8_t port)
+{
+	uint8_t val;
+
+	PORT_WR8(dev->sb, 0x4, port); /* Select register */
+	drv_usecwait(10);
+	val = PORT_RD8(dev->sb, 0x5);
+	drv_usecwait(10);
+
+	return (val);
+}
+
+static uint8_t
+solo_get_byte(solo_dev_t *dev)
+{
+	for (int i = 1000; i > 0; i--) {
+		if (PORT_RD8(dev->sb, 0xc) & 0x40)
+			return (PORT_RD8(dev->sb, 0xa));
+		else
+			drv_usecwait(20);
+	}
+	audio_dev_warn(dev->adev, "timeout waiting to read DSP port");
+	return (0xff);
+}
+
+static void
+solo_write(solo_dev_t *dev, uint8_t reg, uint8_t val)
+{
+	solo_cmd1(dev, reg, val);
+}
+
+static uint8_t
+solo_read(solo_dev_t *dev, uint8_t reg)
+{
+	if (solo_cmd(dev, 0xc0) && solo_cmd(dev, reg)) {
+		return (solo_get_byte(dev));
+	}
+	return (0xff);
+}
+
+static bool
+solo_reset_dsp(solo_dev_t *dev)
+{
+	PORT_WR8(dev->sb, 0x6, 3);
+	drv_usecwait(100);
+	PORT_WR8(dev->sb, 0x6, 0);
+	if (solo_get_byte(dev) != 0xAA) {
+		audio_dev_warn(dev->adev, "solo_reset_dsp failed");
+		return (false);	/* Sorry */
+	}
+	return (true);
+}
+
+static uint_t
+solo_intr(caddr_t arg1, caddr_t arg2)
+{
+	solo_dev_t	*dev = (void *)arg1;
+	audio_engine_t	*prod = NULL;
+	audio_engine_t	*cons = NULL;
+	uint8_t		status;
+	uint_t		rv = DDI_INTR_UNCLAIMED;
+
+	_NOTE(ARGUNUSED(arg2));
+
+	mutex_enter(&dev->mutex);
+
+	if (dev->suspended) {
+		mutex_exit(&dev->mutex);
+		return (rv);
+	}
+
+	status = PORT_RD8(dev->io, 0x7);
+	if (status & 0x20) {
+		rv = DDI_INTR_CLAIMED;
+		cons = dev->play.engine;
+		/* ack the interrupt */
+		solo_setmixer(dev, 0x7a, solo_getmixer(dev, 0x7a) & ~0x80);
+	}
+
+	if (status & 0x10) {
+		rv = DDI_INTR_CLAIMED;
+		prod = dev->rec.engine;
+		/* ack the interrupt */
+		(void) PORT_RD8(dev->sb, 0xe);
+	}
+	mutex_exit(&dev->mutex);
+
+	if (cons) {
+		audio_engine_consume(cons);
+	}
+
+	if (prod) {
+		audio_engine_produce(prod);
+	}
+
+	return (rv);
+}
+
+static uint8_t
+solo_mixer_scale(solo_dev_t *dev, solo_ctrl_num_t num)
+{
+	uint32_t	l, r;
+	uint64_t	value = dev->ctrls[num].val;
+
+	l = (value >> 8) & 0xff;
+	r = value & 0xff;
+
+	l = (l * 15) / 100;
+	r = (r * 15) / 100;
+	return ((uint8_t)((l << 4) | (r)));
+}
+
+static void
+solo_configure_mixer(solo_dev_t *dev)
+{
+	uint32_t v;
+	uint32_t mon, rec;
+
+	/*
+	 * We disable hardware volume control (i.e. async updates to volume).
+	 * We could in theory support this, but making it work right can be
+	 * tricky, and we doubt it is widely used.
+	 */
+	solo_setmixer(dev, 0x64, solo_getmixer(dev, 0x64) | 0xc);
+	solo_setmixer(dev, 0x66, 0);
+
+	/* master volume has 6 bits per channel, bit 6 indicates mute  */
+	/* left */
+	v = (dev->ctrls[CTL_FRONT].val >> 8) & 0xff;
+	v = v ? (v * 63) / 100 : 64;
+	solo_setmixer(dev, 0x60, v & 0xff);
+
+	/* right */
+	v = dev->ctrls[CTL_FRONT].val & 0xff;
+	v = v ? (v * 63) / 100 : 64;
+	solo_setmixer(dev, 0x62, v & 0xff);
+
+	v = solo_mixer_scale(dev, CTL_VOLUME);
+	v = v | (v << 4);
+	solo_setmixer(dev, 0x7c, v & 0xff);
+	solo_setmixer(dev, 0x14, v & 0xff);
+
+	mon = dev->ctrls[CTL_MONSRC].val;
+	rec = dev->ctrls[CTL_RECSRC].val;
+
+	/*
+	 * The Solo-1 has dual stereo mixers (one for input and one for output),
+	 * with separate volume controls for each.
+	 */
+	v = solo_mixer_scale(dev, CTL_MIC);
+	solo_setmixer(dev, 0x68, rec & (1 << INPUT_MIC) ? v : 0);
+	solo_setmixer(dev, 0x1a, mon & (1 << INPUT_MIC) ? v : 0);
+
+	v = solo_mixer_scale(dev, CTL_LINE);
+	solo_setmixer(dev, 0x6e, rec & (1 << INPUT_LINE) ? v : 0);
+	solo_setmixer(dev, 0x3e, mon & (1 << INPUT_LINE) ? v : 0);
+
+	v = solo_mixer_scale(dev, CTL_CD);
+	solo_setmixer(dev, 0x6a, rec & (1 << INPUT_CD) ? v : 0);
+	solo_setmixer(dev, 0x38, mon & (1 << INPUT_CD) ? v : 0);
+
+	v = solo_mixer_scale(dev, CTL_AUX);
+	solo_setmixer(dev, 0x6c, rec & (1 << INPUT_AUX) ? v : 0);
+	solo_setmixer(dev, 0x3a, mon & (1 << INPUT_AUX) ? v : 0);
+
+	v = solo_mixer_scale(dev, CTL_MONO);
+	v = v | (v << 4);
+	solo_setmixer(dev, 0x6f, rec & (1 << INPUT_MONO) ? v : 0);
+	solo_setmixer(dev, 0x6d, mon & (1 << INPUT_MONO) ? v : 0);
+
+	if (dev->ctrls[CTL_MICBOOST].val) {
+		solo_setmixer(dev, 0x7d, solo_getmixer(dev, 0x7d) | 0x8);
+	} else {
+		solo_setmixer(dev, 0x7d, solo_getmixer(dev, 0x7d) & ~(0x8));
+	}
+
+	v = solo_mixer_scale(dev, CTL_RECGAIN);
+	v = v | (v << 4);
+	solo_write(dev, 0xb4, v & 0xff);
+
+	v = dev->ctrls[CTL_SPEAKER].val & 0xff;
+	v = (v * 7) / 100;
+	solo_setmixer(dev, 0x3c, v & 0xff);
+
+	if (dev->ctrls[CTL_LOOPBACK].val) {
+		/* record-what-you-hear mode */
+		solo_setmixer(dev, 0x1c, 0x3);
+	} else {
+		/* use record mixer */
+		solo_setmixer(dev, 0x1c, 0x5);
+	}
+
+}
+
+static int
+solo_set_mixsrc(void *arg, uint64_t val)
+{
+	solo_ctrl_t	*pc = arg;
+	solo_dev_t	*dev = pc->dev;
+
+	if ((val & ~INSRCS) != 0)
+		return (EINVAL);
+
+	mutex_enter(&dev->mutex);
+	pc->val = val;
+	if (!dev->suspended)
+		solo_configure_mixer(dev);
+	mutex_exit(&dev->mutex);
+	return (0);
+}
+
+static int
+solo_set_mono(void *arg, uint64_t val)
+{
+	solo_ctrl_t	*pc = arg;
+	solo_dev_t	*dev = pc->dev;
+
+	val &= 0xff;
+	if (val > 100)
+		return (EINVAL);
+
+	val = (val & 0xff) | ((val & 0xff) << 8);
+
+	mutex_enter(&dev->mutex);
+	pc->val = val;
+	if (!dev->suspended)
+		solo_configure_mixer(dev);
+	mutex_exit(&dev->mutex);
+	return (0);
+}
+
+static int
+solo_set_stereo(void *arg, uint64_t val)
+{
+	solo_ctrl_t	*pc = arg;
+	solo_dev_t	*dev = pc->dev;
+	uint8_t		l;
+	uint8_t		r;
+
+	l = (val & 0xff00) >> 8;
+	r = val & 0xff;
+
+	if ((l > 100) || (r > 100))
+		return (EINVAL);
+
+	mutex_enter(&dev->mutex);
+	pc->val = val;
+	if (!dev->suspended)
+		solo_configure_mixer(dev);
+	mutex_exit(&dev->mutex);
+	return (0);
+}
+
+static int
+solo_set_bool(void *arg, uint64_t val)
+{
+	solo_ctrl_t	*pc = arg;
+	solo_dev_t	*dev = pc->dev;
+
+	mutex_enter(&dev->mutex);
+	pc->val = val;
+	if (!dev->suspended)
+		solo_configure_mixer(dev);
+	mutex_exit(&dev->mutex);
+	return (0);
+}
+
+static int
+solo_get_value(void *arg, uint64_t *val)
+{
+	solo_ctrl_t	*pc = arg;
+	solo_dev_t	*dev = pc->dev;
+
+	mutex_enter(&dev->mutex);
+	*val = pc->val;
+	mutex_exit(&dev->mutex);
+	return (0);
+}
+
+#define	PLAYCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
+#define	RECCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
+#define	MONCTL	(AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
+#define	PCMVOL	(PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
+#define	MAINVOL	(PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
+#define	RECVOL	(RECCTL | AUDIO_CTRL_FLAG_RECVOL)
+
+static void
+solo_alloc_ctrl(solo_dev_t *dev, uint32_t num, uint64_t val)
+{
+	audio_ctrl_desc_t	desc;
+	audio_ctrl_wr_t		fn;
+	solo_ctrl_t		*pc;
+
+	bzero(&desc, sizeof (desc));
+
+	pc = &dev->ctrls[num];
+	pc->num = num;
+	pc->dev = dev;
+
+	switch (num) {
+	case CTL_VOLUME:
+		desc.acd_name = AUDIO_CTRL_ID_VOLUME;
+		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = PCMVOL;
+		fn = solo_set_mono;
+		break;
+
+	case CTL_FRONT:
+		desc.acd_name = AUDIO_CTRL_ID_LINEOUT;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = MAINVOL;
+		fn = solo_set_stereo;
+		break;
+
+	case CTL_SPEAKER:
+		desc.acd_name = AUDIO_CTRL_ID_SPEAKER;
+		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = MAINVOL;
+		fn = solo_set_mono;
+		break;
+
+	case CTL_MIC:
+		desc.acd_name = AUDIO_CTRL_ID_MIC;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECVOL;
+		fn = solo_set_stereo;
+		break;
+
+	case CTL_LINE:
+		desc.acd_name = AUDIO_CTRL_ID_LINEIN;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECVOL;
+		fn = solo_set_stereo;
+		break;
+
+	case CTL_CD:
+		desc.acd_name = AUDIO_CTRL_ID_CD;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECVOL;
+		fn = solo_set_stereo;
+		break;
+
+	case CTL_AUX:
+		desc.acd_name = AUDIO_CTRL_ID_AUX1IN;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECVOL;
+		fn = solo_set_stereo;
+		break;
+
+	case CTL_MONO:
+		desc.acd_name = AUDIO_CTRL_ID_AUX2IN;
+		desc.acd_type = AUDIO_CTRL_TYPE_MONO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECVOL;
+		fn = solo_set_mono;
+		break;
+
+	case CTL_RECSRC:
+		desc.acd_name = AUDIO_CTRL_ID_RECSRC;
+		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
+		desc.acd_minvalue = INSRCS;
+		desc.acd_maxvalue = INSRCS;
+		desc.acd_flags = RECCTL | AUDIO_CTRL_FLAG_MULTI;
+		for (int i = 0; solo_insrcs[i]; i++) {
+			desc.acd_enum[i] = solo_insrcs[i];
+		}
+		fn = solo_set_mixsrc;
+		break;
+
+	case CTL_MONSRC:
+		desc.acd_name = AUDIO_CTRL_ID_MONSRC;
+		desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
+		desc.acd_minvalue = INSRCS;
+		desc.acd_maxvalue = INSRCS;
+		desc.acd_flags = MONCTL | AUDIO_CTRL_FLAG_MULTI;
+		for (int i = 0; solo_insrcs[i]; i++) {
+			desc.acd_enum[i] = solo_insrcs[i];
+		}
+		fn = solo_set_mixsrc;
+		break;
+
+	case CTL_MICBOOST:
+		desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
+		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 1;
+		desc.acd_flags = RECCTL;
+		fn = solo_set_bool;
+		break;
+
+	case CTL_LOOPBACK:
+		desc.acd_name = AUDIO_CTRL_ID_LOOPBACK;
+		desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 1;
+		desc.acd_flags = RECCTL;
+		fn = solo_set_bool;
+		break;
+
+	case CTL_RECGAIN:
+		desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
+		desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
+		desc.acd_minvalue = 0;
+		desc.acd_maxvalue = 100;
+		desc.acd_flags = RECCTL;
+		fn = solo_set_stereo;
+		break;
+	}
+
+	pc->val = val;
+	pc->ctrl = audio_dev_add_control(dev->adev, &desc,
+	    solo_get_value, fn, pc);
+}
+
+static bool
+solo_add_controls(solo_dev_t *dev)
+{
+	solo_alloc_ctrl(dev, CTL_VOLUME, 0x4b);
+	solo_alloc_ctrl(dev, CTL_FRONT, 0x5a5a);
+	solo_alloc_ctrl(dev, CTL_SPEAKER, 0x4b);
+	solo_alloc_ctrl(dev, CTL_MIC, 0x3232);
+	solo_alloc_ctrl(dev, CTL_LINE, 0x4b4b);
+	solo_alloc_ctrl(dev, CTL_CD, 0x4b4b);
+	solo_alloc_ctrl(dev, CTL_AUX, 0);
+	solo_alloc_ctrl(dev, CTL_MONO, 0);
+	solo_alloc_ctrl(dev, CTL_RECSRC, (1U << INPUT_MIC));
+	solo_alloc_ctrl(dev, CTL_MONSRC, 0);
+	solo_alloc_ctrl(dev, CTL_RECGAIN, 0x4b4b);
+	solo_alloc_ctrl(dev, CTL_MICBOOST, 1);
+	solo_alloc_ctrl(dev, CTL_LOOPBACK, 0);
+
+	return (true);
+}
+
+
+/* utility functions for ESS */
+static uint8_t
+solo_calcfilter(int spd)
+{
+	int cutoff;
+
+	cutoff = (spd * 9 * 82) / 20;
+	return (256 - (7160000 / cutoff));
+}
+
+static void
+solo_aud1_update(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+	uint16_t	offset, n;
+	uint32_t	ptr;
+	uint32_t	count;
+	uint32_t	diff;
+
+	ASSERT(mutex_owned(&dev->mutex));
+
+	/*
+	 * During recording, this register is known to give back
+	 * garbage if it's not quiescent while being read.  This hack
+	 * attempts to work around it.
+	 */
+	ptr = PORT_RD32(dev->vc, 0);
+	count = PORT_RD16(dev->vc, 4);
+	diff = e->paddr + SOLO_BUFSZ - ptr - count;
+	if ((diff > 3) || (ptr < e->paddr) ||
+	    (ptr >= (e->paddr + SOLO_BUFSZ))) {
+		ptr = dev->last_capture;
+	} else {
+		dev->last_capture = ptr;
+	}
+	offset = ptr - e->paddr;
+	offset /= (SOLO_NCHAN * SOLO_SAMPSZ);
+
+	n = offset >= e->offset ?
+	    offset - e->offset :
+	    offset + SOLO_BUFSZ - e->offset;
+
+	e->offset = offset;
+	e->count += n / (SOLO_NCHAN * SOLO_SAMPSZ);
+}
+
+static void
+solo_aud1_start(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+	int		len;
+	uint32_t	v;
+
+	ASSERT(mutex_owned(&dev->mutex));
+
+	len = SOLO_FRAGSZ / 2;
+	len = -len;
+
+	/* sample rate - 48 kHz */
+	solo_write(dev, 0xa1, 0xf0);
+	/* filter cutoff */
+	solo_write(dev, 0xa2, solo_calcfilter(SOLO_RATE));
+
+
+	/* mono/stereo - bit 0 set, bit 1 clear */
+	solo_write(dev, 0xa8, (solo_read(dev, 0xa8) & ~0x03) | 1);
+
+	(void) solo_cmd(dev, 0xd3);	/* turn off DAC1 output */
+
+	/* setup fifo for signed 16-bit stereo */
+	solo_write(dev, 0xb7, 0x71);
+	solo_write(dev, 0xb7, 0xbc);
+
+	v = solo_mixer_scale(dev, CTL_RECGAIN);
+	v = v | (v << 4);
+	solo_write(dev, 0xb4, v & 0xff);
+
+	PORT_WR8(dev->vc, 0x8, 0xc4); /* command */
+	PORT_WR8(dev->vc, 0xd, 0xff); /* clear DMA */
+	PORT_WR8(dev->vc, 0xf, 0x01); /* stop DMA  */
+
+	PORT_WR8(dev->vc, 0xd, 0xff); /* reset */
+	PORT_WR8(dev->vc, 0xf, 0x01); /* mask */
+	PORT_WR8(dev->vc, 0xb, 0x14); /* mode */
+
+	PORT_WR32(dev->vc, 0x0, e->paddr);
+	PORT_WR16(dev->vc, 0x4, SOLO_BUFSZ - 1);
+
+	/* transfer length low, high */
+	solo_write(dev, 0xa4, len & 0x00ff);
+	solo_write(dev, 0xa5, (len & 0xff00) >> 8);
+
+	/* autoinit, dma dir, go for it */
+	solo_write(dev, 0xb8, 0x0f);
+	PORT_WR8(dev->vc, 0xf, 0);	/* start DMA */
+
+	dev->last_capture = e->paddr;
+}
+
+static void
+solo_aud1_stop(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+
+	/* NB: We might be in quiesce, without a lock held */
+	solo_write(dev, 0xb8, solo_read(dev, 0xb8) & ~0x01);
+}
+
+static void
+solo_aud2_update(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+	uint16_t	offset = 0, n;
+
+	ASSERT(mutex_owned(&dev->mutex));
+
+	offset = SOLO_BUFSZ - PORT_RD16(dev->io, 0x4);
+	offset /= (SOLO_NCHAN * SOLO_SAMPSZ);
+
+	n = offset >= e->offset ?
+	    offset - e->offset :
+	    offset + SOLO_BUFFR - e->offset;
+
+	e->offset = offset;
+	e->count += n;
+}
+
+static void
+solo_aud2_start(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+	int		len;
+	uint32_t	v;
+
+	ASSERT(mutex_owned(&dev->mutex));
+
+	len = SOLO_FRAGSZ / 2;
+	len = -len;
+
+	/* program transfer type */
+	solo_setmixer(dev, 0x78, 0x10);
+	/* sample rate - 48 kHz */
+	solo_setmixer(dev, 0x70, 0xf0);
+	solo_setmixer(dev, 0x72, solo_calcfilter(SOLO_RATE));
+	/* transfer length low & high */
+	solo_setmixer(dev, 0x74, len & 0x00ff);
+	solo_setmixer(dev, 0x76, (len & 0xff00) >> 8);
+	/* enable irq, set signed 16-bit stereo format */
+	solo_setmixer(dev, 0x7a, 0x47);
+
+	PORT_WR8(dev->io, 0x6, 0);
+	PORT_WR32(dev->io, 0x0, e->paddr);
+	PORT_WR16(dev->io, 0x4, SOLO_BUFSZ);
+
+	/* this crazy initialization appears to help with fifo weirdness */
+	/* start the engine running */
+	solo_setmixer(dev, 0x78, 0x92);
+	drv_usecwait(10);
+	solo_setmixer(dev, 0x78, 0x93);
+
+	PORT_WR8(dev->io, 0x6, 0x0a); /* autoinit, enable */
+
+	v = solo_mixer_scale(dev, CTL_VOLUME);
+	v = v | (v << 4);
+	solo_setmixer(dev, 0x7c, v & 0xff);
+}
+
+static void
+solo_aud2_stop(solo_engine_t *e)
+{
+	solo_dev_t	*dev = e->dev;
+
+	/* NB: We might be in quiesce, without a lock held */
+	PORT_WR8(dev->io, 0x6, 0);
+	solo_setmixer(dev, 0x78, solo_getmixer(dev, 0x78) & ~0x03);
+}
+
+/*
+ * Audio entry points.
+ */
+static int
+solo_format(void *arg)
+{
+	solo_engine_t	*e = arg;
+	return (e->format);
+}
+
+static int
+solo_channels(void *arg)
+{
+	_NOTE(ARGUNUSED(arg));
+	return (SOLO_NCHAN);
+}
+
+static int
+solo_rate(void *arg)
+{
+	_NOTE(ARGUNUSED(arg));
+	return (SOLO_RATE);
+}
+
+static size_t
+solo_qlen(void *arg)
+{
+	_NOTE(ARGUNUSED(arg));
+	return (0);
+}
+
+static void
+solo_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
+{
+	solo_engine_t *e = arg;
+
+	if (e->swapped) {
+		*offset = !chan;
+	} else {
+		*offset = chan;
+	}
+	*incr = 2;
+}
+
+static void
+solo_sync(void *arg, unsigned nframes)
+{
+	solo_engine_t *e = arg;
+
+	_NOTE(ARGUNUSED(nframes));
+
+	(void) ddi_dma_sync(e->dmah, 0, 0, e->syncdir);
+}
+
+
+static uint64_t
+solo_count(void *arg)
+{
+	solo_engine_t	*e = arg;
+	solo_dev_t	*dev = e->dev;
+	uint64_t	count;
+
+	mutex_enter(&dev->mutex);
+	if (!dev->suspended)
+		e->update(e);
+	count = e->count;
+	mutex_exit(&dev->mutex);
+
+	return (count);
+}
+
+static int
+solo_open(void *arg, int f, unsigned *ffr, unsigned *nfr, caddr_t *buf)
+{
+	solo_engine_t	*e = arg;
+	solo_dev_t	*dev = e->dev;
+
+	_NOTE(ARGUNUSED(f));
+
+	/* NB: For simplicity, we just fix the interrupt rate at 100 Hz */
+	*ffr = SOLO_FRAGFR;
+	*nfr = SOLO_NFRAGS;
+	*buf = e->kaddr;
+
+	mutex_enter(&dev->mutex);
+	e->started = false;
+	e->count = 0;
+	mutex_exit(&dev->mutex);
+
+	return (0);
+}
+
+void
+solo_close(void *arg)
+{
+	solo_engine_t	*e = arg;
+	solo_dev_t	*dev = e->dev;
+
+	mutex_enter(&dev->mutex);
+	if (!dev->suspended)
+		e->stop(e);
+	e->started = false;
+	mutex_exit(&dev->mutex);
+}
+
+
+static int
+solo_start(void *arg)
+{
+	solo_engine_t	*e = arg;
+	solo_dev_t	*dev = e->dev;
+
+	mutex_enter(&dev->mutex);
+	if (!e->started) {
+		if (!dev->suspended)
+			e->start(e);
+		e->started = true;
+	}
+	mutex_exit(&dev->mutex);
+
+	return (0);
+}
+
+static void
+solo_stop(void *arg)
+{
+	solo_engine_t	*e = arg;
+	solo_dev_t	*dev = e->dev;
+
+	mutex_enter(&dev->mutex);
+	if (e->started) {
+		if (!dev->suspended)
+			e->stop(e);
+		e->started = false;
+	}
+	mutex_exit(&dev->mutex);
+
+}
+
+static audio_engine_ops_t solo_engine_ops = {
+	AUDIO_ENGINE_VERSION,
+	solo_open,
+	solo_close,
+	solo_start,
+	solo_stop,
+	solo_count,
+	solo_format,
+	solo_channels,
+	solo_rate,
+	solo_sync,
+	solo_qlen,
+	solo_chinfo,
+};
+
+static void
+solo_release_resources(solo_dev_t *dev)
+{
+	if (dev->ihandle != NULL) {
+		(void) ddi_intr_disable(dev->ihandle);
+		(void) ddi_intr_remove_handler(dev->ihandle);
+		(void) ddi_intr_free(dev->ihandle);
+		mutex_destroy(&dev->mutex);
+	}
+
+	if (dev->io.acch != NULL) {
+		ddi_regs_map_free(&dev->io.acch);
+	}
+
+	if (dev->sb.acch != NULL) {
+		ddi_regs_map_free(&dev->sb.acch);
+	}
+
+	if (dev->vc.acch != NULL) {
+		ddi_regs_map_free(&dev->vc.acch);
+	}
+
+	if (dev->pcih != NULL) {
+		pci_config_teardown(&dev->pcih);
+	}
+
+	/* release play resources */
+	if (dev->play.paddr != 0)
+		(void) ddi_dma_unbind_handle(dev->play.dmah);
+	if (dev->play.acch != NULL)
+		ddi_dma_mem_free(&dev->play.acch);
+	if (dev->play.dmah != NULL)
+		ddi_dma_free_handle(&dev->play.dmah);
+
+	if (dev->play.engine != NULL) {
+		audio_dev_remove_engine(dev->adev, dev->play.engine);
+		audio_engine_free(dev->play.engine);
+	}
+
+	/* release record resources */
+	if (dev->rec.paddr != 0)
+		(void) ddi_dma_unbind_handle(dev->rec.dmah);
+	if (dev->rec.acch != NULL)
+		ddi_dma_mem_free(&dev->rec.acch);
+	if (dev->rec.dmah != NULL)
+		ddi_dma_free_handle(&dev->rec.dmah);
+
+	if (dev->rec.engine != NULL) {
+		audio_dev_remove_engine(dev->adev, dev->rec.engine);
+		audio_engine_free(dev->rec.engine);
+	}
+
+	if (dev->adev != NULL) {
+		audio_dev_free(dev->adev);
+	}
+
+	kmem_free(dev, sizeof (*dev));
+}
+
+static bool
+solo_setup_interrupts(solo_dev_t *dev)
+{
+	int actual;
+	uint_t ipri;
+
+	if ((ddi_intr_alloc(dev->dip, &dev->ihandle, DDI_INTR_TYPE_FIXED,
+	    0, 1, &actual, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) ||
+	    (actual != 1)) {
+		audio_dev_warn(dev->adev, "can't alloc intr handle");
+		return (false);
+	}
+
+	if (ddi_intr_get_pri(dev->ihandle, &ipri) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev,  "can't determine intr priority");
+		(void) ddi_intr_free(dev->ihandle);
+		dev->ihandle = NULL;
+		return (false);
+	}
+
+	if (ddi_intr_add_handler(dev->ihandle, solo_intr, dev,
+	    NULL) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "can't add intr handler");
+		(void) ddi_intr_free(dev->ihandle);
+		dev->ihandle = NULL;
+		return (false);
+	}
+
+	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
+
+	return (true);
+}
+
+static bool
+solo_map_registers(solo_dev_t *dev)
+{
+	dev_info_t	*dip = dev->dip;
+
+	/* map registers */
+	if (ddi_regs_map_setup(dip, 1, &dev->io.base, 0, 0, &acc_attr,
+	    &dev->io.acch) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "can't map IO registers");
+		return (false);
+	}
+	if (ddi_regs_map_setup(dip, 2, &dev->sb.base, 0, 0, &acc_attr,
+	    &dev->sb.acch) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "can't map SB registers");
+		return (false);
+	}
+	if (ddi_regs_map_setup(dip, 3, &dev->vc.base, 0, 0, &acc_attr,
+	    &dev->vc.acch) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "can't map VC registers");
+		return (false);
+	}
+
+	return (true);
+}
+
+#define	ESS_PCI_LEGACYCONTROL		0x40
+#define	ESS_PCI_CONFIG			0x50
+#define	ESS_PCI_DDMACONTROL		0x60
+
+static bool
+solo_init_hw(solo_dev_t *dev)
+{
+	uint32_t	data;
+
+	/*
+	 * Legacy audio register -- disable legacy audio.  We also
+	 * arrange for 16-bit I/O address decoding.
+	 */
+	/* this version disables the MPU, FM synthesis (Adlib), and Game Port */
+	pci_config_put16(dev->pcih, ESS_PCI_LEGACYCONTROL, 0x8041);
+
+	/*
+	 * Note that Solo-1 uses I/O space for all BARs, and hardwires
+	 * the upper 32-bits to zero.
+	 */
+	data = pci_config_get32(dev->pcih, PCI_CONF_BASE2);
+	data |= 1;
+	pci_config_put16(dev->pcih, ESS_PCI_DDMACONTROL, data & 0xffff);
+
+	/*
+	 * Make sure that legacy IRQ and DRQ are disbled.  We disable most
+	 * other legacy features too.
+	 */
+	pci_config_put16(dev->pcih, ESS_PCI_CONFIG, 0);
+
+	if (!solo_reset_dsp(dev))
+		return (false);
+
+	/* enable extended mode */
+	(void) solo_cmd(dev, 0xc6);
+
+
+	PORT_WR8(dev->io, 0x7, 0x30); /* enable audio irqs */
+
+	/* demand mode, 4 bytes/xfer */
+	solo_write(dev, 0xb9, 0x01);
+
+	/*
+	 * This sets Audio 2 (playback) to use its own independent
+	 * rate control, and gives us 48 kHz compatible divisors.  It
+	 * also bypasses the switched capacitor filter.
+	 */
+	solo_setmixer(dev, 0x71, 0x2a);
+
+	/* irq control */
+	solo_write(dev, 0xb1, (solo_read(dev, 0xb1) & 0x0f) | 0x50);
+	/* drq control */
+	solo_write(dev, 0xb2, (solo_read(dev, 0xb2) & 0x0f) | 0x50);
+
+	solo_setmixer(dev, 0, 0); /* reset mixer settings */
+
+	solo_configure_mixer(dev);
+	return (true);
+}
+
+static bool
+solo_alloc_engine(solo_dev_t *dev, int engno)
+{
+	size_t			rlen;
+	ddi_dma_attr_t		*dattr;
+	ddi_dma_cookie_t	c;
+	unsigned		ccnt;
+	unsigned		caps;
+	unsigned		dflags;
+	const char		*desc;
+	solo_engine_t		*e;
+
+	ASSERT((engno == 1) || (engno = 2));
+
+	switch (engno) {
+	case 1:	/* record */
+		e = &dev->rec;
+		desc = "record";
+		dattr = &dma_attr_audio1;
+		caps = ENGINE_INPUT_CAP;
+		dflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
+		e->syncdir = DDI_DMA_SYNC_FORKERNEL;
+		e->update = solo_aud1_update;
+		e->start = solo_aud1_start;
+		e->stop = solo_aud1_stop;
+		e->format = AUDIO_FORMAT_S16_BE;
+		e->swapped = true;
+		break;
+
+	case 2:	/* playback */
+		e = &dev->play;
+		desc = "playback";
+		dattr = &dma_attr_audio2;
+		caps = ENGINE_OUTPUT_CAP;
+		dflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
+		e->syncdir = DDI_DMA_SYNC_FORDEV;
+		e->update = solo_aud2_update;
+		e->start = solo_aud2_start;
+		e->stop = solo_aud2_stop;
+		e->format = AUDIO_FORMAT_S16_LE;
+		e->swapped = false;
+		break;
+
+	default:
+		audio_dev_warn(dev->adev, "bad engine number!");
+		return (false);
+	}
+
+	printf("%s %sswapped!", desc, e->swapped ? "" : "not ");
+	e->dev = dev;
+
+	if (ddi_dma_alloc_handle(dev->dip, dattr, DDI_DMA_SLEEP, NULL,
+	    &e->dmah) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "%s dma handle alloc failed", desc);
+		return (false);
+	}
+	if (ddi_dma_mem_alloc(e->dmah, SOLO_BUFSZ, &buf_attr,
+	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &e->kaddr,
+	    &rlen, &e->acch) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev, "%s dma memory alloc failed", desc);
+		return (false);
+	}
+	/* ensure that the buffer is zeroed out properly */
+	bzero(e->kaddr, rlen);
+	if (ddi_dma_addr_bind_handle(e->dmah, NULL, e->kaddr, SOLO_BUFSZ,
+	    dflags, DDI_DMA_SLEEP, NULL, &c, &ccnt) != DDI_DMA_MAPPED) {
+		audio_dev_warn(dev->adev, "%s dma binding failed", desc);
+		return (false);
+	}
+	e->paddr = c.dmac_address;
+
+	/*
+	 * Allocate and configure audio engine.
+	 */
+	e->engine = audio_engine_alloc(&solo_engine_ops, caps);
+	if (e->engine == NULL) {
+		audio_dev_warn(dev->adev, "record audio_engine_alloc failed");
+		return (false);
+	}
+
+	audio_engine_set_private(e->engine, e);
+	audio_dev_add_engine(dev->adev, e->engine);
+
+	return (true);
+}
+
+
+static int
+solo_suspend(solo_dev_t *dev)
+{
+	mutex_enter(&dev->mutex);
+	/* play */
+	solo_aud2_stop(&dev->play);
+	solo_aud2_update(&dev->play);
+	/* record */
+	solo_aud1_stop(&dev->rec);
+	solo_aud1_update(&dev->rec);
+
+	dev->suspended = true;
+	mutex_exit(&dev->mutex);
+
+	return (DDI_SUCCESS);
+}
+
+static int
+solo_resume(solo_dev_t *dev)
+{
+	solo_engine_t	*e;
+	audio_engine_t	*prod = NULL;
+	audio_engine_t	*cons = NULL;
+
+	audio_engine_reset(dev->rec.engine);
+	audio_engine_reset(dev->play.engine);
+
+	mutex_enter(&dev->mutex);
+	if (!solo_init_hw(dev)) {
+		/* yikes! */
+		audio_dev_warn(dev->adev, "unable to resume audio!");
+		audio_dev_warn(dev->adev, "reboot or reload driver to reset");
+		mutex_exit(&dev->mutex);
+		return (DDI_SUCCESS);
+	}
+	dev->suspended = false;
+
+	/* record - audio 1 */
+	e = &dev->rec;
+	if (e->started) {
+		e->start(e);
+		prod = e->engine;
+	}
+
+	/* play - audio 2 */
+	e = &dev->play;
+	if (e->started) {
+		e->start(e);
+		cons = e->engine;
+	}
+
+	mutex_exit(&dev->mutex);
+
+	if (cons)
+		audio_engine_consume(cons);
+	if (prod)
+		audio_engine_produce(prod);
+
+	return (DDI_SUCCESS);
+}
+
+static int
+solo_attach(dev_info_t *dip)
+{
+	solo_dev_t	*dev;
+	uint32_t	data;
+
+	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
+	dev->dip = dip;
+	ddi_set_driver_private(dip, dev);
+
+	dev->adev = audio_dev_alloc(dip, 0);
+	if (dev->adev == NULL)
+		goto no;
+
+	audio_dev_set_description(dev->adev, "ESS Solo-1 PCI AudioDrive");
+	audio_dev_set_version(dev->adev, "ES1938");
+
+	if (pci_config_setup(dip, &dev->pcih) != DDI_SUCCESS) {
+		audio_dev_warn(NULL, "pci_config_setup failed");
+		goto no;
+	}
+
+	data = pci_config_get16(dev->pcih, PCI_CONF_COMM);
+	data |= PCI_COMM_ME | PCI_COMM_IO;
+	pci_config_put16(dev->pcih, PCI_CONF_COMM, data);
+
+	if ((!solo_map_registers(dev)) ||
+	    (!solo_setup_interrupts(dev)) ||
+	    (!solo_alloc_engine(dev, 1)) ||
+	    (!solo_alloc_engine(dev, 2)) ||
+	    (!solo_add_controls(dev)) ||
+	    (!solo_init_hw(dev))) {
+		goto no;
+	}
+
+	if (audio_dev_register(dev->adev) != DDI_SUCCESS) {
+		audio_dev_warn(dev->adev,
+		    "unable to register with audio framework");
+		goto no;
+	}
+
+	(void) ddi_intr_enable(dev->ihandle);
+	ddi_report_dev(dip);
+
+	return (DDI_SUCCESS);
+
+no:
+	solo_release_resources(dev);
+	return (DDI_FAILURE);
+}
+
+static int
+solo_detach(solo_dev_t *dev)
+{
+	if (audio_dev_unregister(dev->adev) != DDI_SUCCESS) {
+		return (DDI_FAILURE);
+	}
+
+	solo_release_resources(dev);
+	return (DDI_SUCCESS);
+}
+
+static int
+solo_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
+{
+	solo_dev_t *dev;
+
+	switch (cmd) {
+	case DDI_ATTACH:
+		return (solo_attach(dip));
+
+	case DDI_RESUME:
+		if ((dev = ddi_get_driver_private(dip)) == NULL) {
+			return (DDI_FAILURE);
+		}
+		return (solo_resume(dev));
+
+	default:
+		return (DDI_FAILURE);
+	}
+}
+
+static int
+solo_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+	solo_dev_t *dev;
+
+	if ((dev = ddi_get_driver_private(dip)) == NULL) {
+		return (DDI_FAILURE);
+	}
+
+	switch (cmd) {
+	case DDI_DETACH:
+		return (solo_detach(dev));
+
+	case DDI_SUSPEND:
+		return (solo_suspend(dev));
+	default:
+		return (DDI_FAILURE);
+	}
+}
+
+static int
+solo_quiesce(dev_info_t *dip)
+{
+	solo_dev_t *dev;
+
+	dev = ddi_get_driver_private(dip);
+
+	solo_aud1_stop(&dev->rec);
+	solo_aud2_stop(&dev->play);
+
+	solo_setmixer(dev, 0, 0);
+	PORT_WR8(dev->io, 0x7, 0); /* disable all irqs */
+	return (0);
+}
+
+struct dev_ops solo_dev_ops = {
+	DEVO_REV,		/* rev */
+	0,			/* refcnt */
+	NULL,			/* getinfo */
+	nulldev,		/* identify */
+	nulldev,		/* probe */
+	solo_ddi_attach,	/* attach */
+	solo_ddi_detach,	/* detach */
+	nodev,			/* reset */
+	NULL,			/* cb_ops */
+	NULL,			/* bus_ops */
+	NULL,			/* power */
+	solo_quiesce,		/* quiesce */
+};
+
+static struct modldrv solo_modldrv = {
+	&mod_driverops,			/* drv_modops */
+	"ESS Solo-1 Audio",		/* linkinfo */
+	&solo_dev_ops,			/* dev_ops */
+};
+
+static struct modlinkage modlinkage = {
+	MODREV_1,
+	{ &solo_modldrv, NULL }
+};
+
+int
+_init(void)
+{
+	int	rv;
+
+	audio_init_ops(&solo_dev_ops, DRVNAME);
+	if ((rv = mod_install(&modlinkage)) != 0) {
+		audio_fini_ops(&solo_dev_ops);
+	}
+	return (rv);
+}
+
+int
+_fini(void)
+{
+	int	rv;
+
+	if ((rv = mod_remove(&modlinkage)) == 0) {
+		audio_fini_ops(&solo_dev_ops);
+	}
+	return (rv);
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+	return (mod_info(&modlinkage, modinfop));
+}
--- a/usr/src/uts/common/io/audio/impl/audio_client.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_client.c	Mon Sep 21 11:26:40 2009 -0400
@@ -58,7 +58,7 @@
  *
  */
 
-const uint16_t auimpl_db_table[AUDIO_DB_SIZE + 1] = {
+static const uint16_t auimpl_db_table[AUDIO_DB_SIZE + 1] = {
 	0,   0,   1,   1,   1,   1,   1,   1,   2,   2,
 	2,   2,   3,   3,   4,   4,   5,   5,   6,   7,
 	8,   9,   10,  11,  12,  14,  16,  18,  20,  22,
@@ -67,6 +67,10 @@
 	256
 };
 
+static list_t			auimpl_clients;
+static krwlock_t		auimpl_client_lock;
+static audio_client_ops_t	*audio_client_ops[AUDIO_MN_TYPE_MASK + 1];
+
 void *
 auclnt_get_private(audio_client_t *c)
 {
@@ -641,7 +645,8 @@
 	return (sp->s_user_parms->p_nchan);
 }
 
-void
+
+static void
 auimpl_set_gain_master(audio_stream_t *sp, uint8_t gain)
 {
 	uint32_t	scaled;
@@ -675,6 +680,38 @@
 	 */
 }
 
+int
+auimpl_set_pcmvol(void *arg, uint64_t val)
+{
+	audio_dev_t	*d = arg;
+	list_t		*l = &d->d_clients;
+	audio_client_t	*c;
+
+	if (val > 100) {
+		return (EINVAL);
+	}
+	rw_enter(&auimpl_client_lock, RW_WRITER);
+	d->d_pcmvol = val & 0xff;
+	rw_downgrade(&auimpl_client_lock);
+
+	for (c = list_head(l); c; c = list_next(l, c)) {
+		/* don't need to check is_active here, its safe */
+		auimpl_set_gain_master(&c->c_ostream, (uint8_t)val);
+	}
+	rw_exit(&auimpl_client_lock);
+
+	return (0);
+}
+
+int
+auimpl_get_pcmvol(void *arg, uint64_t *val)
+{
+	audio_dev_t	*d = arg;
+
+	*val = d->d_pcmvol;
+	return (0);
+}
+
 void
 auclnt_set_gain(audio_stream_t *sp, uint8_t gain)
 {
@@ -842,10 +879,6 @@
  * implementations, but are for private framework use only.
  */
 
-static list_t			auimpl_clients;
-static krwlock_t		auimpl_client_lock;
-static audio_client_ops_t	*audio_client_ops[AUDIO_MN_TYPE_MASK + 1];
-
 void
 auimpl_client_init(void)
 {
@@ -1157,6 +1190,22 @@
 }
 
 void
+auimpl_client_activate(audio_client_t *c)
+{
+	rw_enter(&auimpl_client_lock, RW_WRITER);
+	c->c_is_active = B_TRUE;
+	rw_exit(&auimpl_client_lock);
+}
+
+void
+auimpl_client_deactivate(audio_client_t *c)
+{
+	rw_enter(&auimpl_client_lock, RW_WRITER);
+	c->c_is_active = B_FALSE;
+	rw_exit(&auimpl_client_lock);
+}
+
+void
 auclnt_close(audio_client_t *c)
 {
 	audio_dev_t	*d = c->c_dev;
@@ -1165,9 +1214,9 @@
 	auclnt_stop(&c->c_istream);
 	auclnt_stop(&c->c_ostream);
 
-	rw_enter(&d->d_clnt_lock, RW_WRITER);
+	rw_enter(&auimpl_client_lock, RW_WRITER);
 	list_remove(&d->d_clients, c);
-	rw_exit(&d->d_clnt_lock);
+	rw_exit(&auimpl_client_lock);
 
 	mutex_enter(&c->c_lock);
 	/* if in transition need to wait for other thread to release */
@@ -1212,7 +1261,7 @@
 	for (c = list_head(list); c != NULL; c = list_next(list, c)) {
 		if ((c->c_major == mj) && (c->c_minor == mn)) {
 			mutex_enter(&c->c_lock);
-			if (c->c_is_open) {
+			if (c->c_is_active) {
 				c->c_refcnt++;
 				mutex_exit(&c->c_lock);
 			} else {
@@ -1246,9 +1295,11 @@
 	audio_client_t	*c;
 	int		rv;
 
-	rw_enter(&d->d_clnt_lock, RW_READER);
+	rw_enter(&auimpl_client_lock, RW_READER);
 restart:
 	for (c = list_head(l); c != NULL; c = list_next(l, c)) {
+		if (!c->c_is_active)
+			continue;
 		rv = (walker(c, arg));
 		if (rv == AUDIO_WALK_STOP) {
 			break;
@@ -1256,7 +1307,7 @@
 			goto restart;
 		}
 	}
-	rw_exit(&d->d_clnt_lock);
+	rw_exit(&auimpl_client_lock);
 }
 
 
@@ -1317,11 +1368,11 @@
 		auimpl_engine_close(&c->c_ostream);
 		auimpl_engine_close(&c->c_istream);
 	} else {
-		rw_enter(&d->d_clnt_lock, RW_WRITER);
+		rw_enter(&auimpl_client_lock, RW_WRITER);
 		list_insert_tail(&d->d_clients, c);
 		c->c_ostream.s_gain_master = d->d_pcmvol;
 		c->c_istream.s_gain_master = 100;
-		rw_exit(&d->d_clnt_lock);
+		rw_exit(&auimpl_client_lock);
 		auclnt_set_gain(&c->c_ostream, 100);
 		auclnt_set_gain(&c->c_istream, 100);
 	}
@@ -1465,14 +1516,16 @@
 	list_t *l = &dev->d_clients;
 	audio_client_t *c;
 
-	rw_enter(&dev->d_clnt_lock, RW_READER);
+	rw_enter(&auimpl_client_lock, RW_READER);
 	for (c = list_head(l); c != NULL; c = list_next(l, c)) {
+		if (!c->c_is_active)
+			continue;
 		mutex_enter(&c->c_lock);
 		c->c_do_notify = B_TRUE;
 		cv_broadcast(&c->c_cv);
 		mutex_exit(&c->c_lock);
 	}
-	rw_exit(&dev->d_clnt_lock);
+	rw_exit(&auimpl_client_lock);
 }
 
 uint64_t
--- a/usr/src/uts/common/io/audio/impl/audio_ctrl.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_ctrl.c	Mon Sep 21 11:26:40 2009 -0400
@@ -239,34 +239,6 @@
 	kmem_free(ctrl, sizeof (*ctrl));
 }
 
-static int
-auimpl_set_pcmvol(void *arg, uint64_t val)
-{
-	audio_dev_t	*d = arg;
-	list_t		*l = &d->d_clients;
-	audio_client_t	*c;
-
-	if (val > 100) {
-		return (EINVAL);
-	}
-	rw_enter(&d->d_clnt_lock, RW_WRITER);
-	d->d_pcmvol = val & 0xff;
-	for (c = list_head(l); c; c = list_next(l, c)) {
-		auimpl_set_gain_master(&c->c_ostream, (uint8_t)val);
-	}
-	rw_exit(&d->d_clnt_lock);
-	return (0);
-}
-
-static int
-auimpl_get_pcmvol(void *arg, uint64_t *val)
-{
-	audio_dev_t	*d = arg;
-
-	*val = d->d_pcmvol;
-	return (0);
-}
-
 int
 audio_dev_add_soft_volume(audio_dev_t *d)
 {
--- a/usr/src/uts/common/io/audio/impl/audio_ddi.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_ddi.c	Mon Sep 21 11:26:40 2009 -0400
@@ -180,9 +180,8 @@
 	/* we do device cloning! */
 	*devp = makedevice(c->c_major, c->c_minor);
 
-	mutex_enter(&c->c_lock);
-	c->c_is_open = B_TRUE;
-	mutex_exit(&c->c_lock);
+	/* now we can receive upcalls */
+	auimpl_client_activate(c);
 
 	auclnt_notify_dev(c->c_dev);
 
@@ -240,14 +239,13 @@
 	/* we do device cloning! */
 	*devp = makedevice(c->c_major, c->c_minor);
 
-	mutex_enter(&c->c_lock);
-	c->c_is_open = B_TRUE;
-	mutex_exit(&c->c_lock);
+	qprocson(rq);
+
+	/* now we can receive upcalls */
+	auimpl_client_activate(c);
 
 	auclnt_notify_dev(c->c_dev);
 
-	qprocson(rq);
-
 	return (0);
 }
 
@@ -268,9 +266,8 @@
 		rv = auclnt_drain(c);
 	}
 
-	mutex_enter(&c->c_lock);
-	c->c_is_open = B_FALSE;
-	mutex_exit(&c->c_lock);
+	/* make sure we won't get any upcalls */
+	auimpl_client_deactivate(c);
 
 	/*
 	 * Pick up any data sitting around in input buffers.  This
@@ -316,9 +313,8 @@
 		return (ENXIO);
 	}
 
-	mutex_enter(&c->c_lock);
-	c->c_is_open = B_FALSE;
-	mutex_exit(&c->c_lock);
+	/* we don't want any upcalls anymore */
+	auimpl_client_deactivate(c);
 
 	/*
 	 * Pick up any data sitting around in input buffers.  This
--- a/usr/src/uts/common/io/audio/impl/audio_engine.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_engine.c	Mon Sep 21 11:26:40 2009 -0400
@@ -75,7 +75,6 @@
 	mutex_init(&d->d_lock, NULL, MUTEX_DRIVER, NULL);
 	cv_init(&d->d_cv, NULL, CV_DRIVER, NULL);
 	rw_init(&d->d_ctrl_lock, NULL, RW_DRIVER, NULL);
-	rw_init(&d->d_clnt_lock, NULL, RW_DRIVER, NULL);
 	list_create(&d->d_clients, sizeof (struct audio_client),
 	    offsetof(struct audio_client, c_dev_linkage));
 	list_create(&d->d_engines, sizeof (struct audio_engine),
@@ -107,7 +106,6 @@
 	rw_destroy(&d->d_ctrl_lock);
 	mutex_destroy(&d->d_lock);
 	cv_destroy(&d->d_cv);
-	rw_destroy(&d->d_clnt_lock);
 	kmem_free(d, sizeof (*d));
 }
 
--- a/usr/src/uts/common/io/audio/impl/audio_impl.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_impl.h	Mon Sep 21 11:26:40 2009 -0400
@@ -189,7 +189,7 @@
 	boolean_t		c_do_notify;
 	boolean_t		c_do_drain;
 	boolean_t		c_closing;
-	boolean_t		c_is_open;
+	boolean_t		c_is_active;
 
 	/*
 	 * Client wide settings... e.g. ops vector, etc.
@@ -442,9 +442,12 @@
 void auimpl_client_fini(void);
 audio_client_t *auimpl_client_create(dev_t);
 void auimpl_client_destroy(audio_client_t *);
+void auimpl_client_activate(audio_client_t *);
+void auimpl_client_deactivate(audio_client_t *);
 int auimpl_create_minors(audio_dev_t *);
 void auimpl_remove_minors(audio_dev_t *);
-void auimpl_set_gain_master(audio_stream_t *, uint8_t);
+int auimpl_set_pcmvol(void *, uint64_t);
+int auimpl_get_pcmvol(void *, uint64_t *);
 
 /* audio_engine.c */
 void auimpl_dev_init(void);
--- a/usr/src/uts/common/io/audio/impl/audio_input.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/audio/impl/audio_input.c	Mon Sep 21 11:26:40 2009 -0400
@@ -40,29 +40,25 @@
 void									\
 auimpl_import_##NAME(audio_engine_t *eng, audio_stream_t *sp)		\
 {									\
-	int	nch = eng->e_nchan;					\
-	int32_t *out;							\
-	TYPE	*in;							\
-	int	ch;							\
-	void	*data;							\
-	int	vol;							\
-									\
-	data = sp->s_cnv_src;						\
-	ch = 0;								\
-	in = (void *)(eng->e_data + (eng->e_tidx * eng->e_framesz));	\
-	out = data;							\
-	vol = sp->s_gain_eff;						\
+	int		fragfr = eng->e_fragfr;				\
+	int		nch = eng->e_nchan;				\
+	unsigned	tidx = eng->e_tidx;				\
+	int32_t 	*out = (void *)sp->s_cnv_src;			\
+	TYPE		*in = (void *)eng->e_data;			\
+	int		ch = 0;						\
+	int		vol = sp->s_gain_eff;				\
 									\
 	do {	/* for each channel */					\
-		TYPE *ip;						\
+		TYPE 	*ip;						\
 		int32_t *op;						\
-		int i;							\
+		int 	i;						\
+		int 	incr = eng->e_chincr[ch];			\
 									\
 		/* get value and adjust next channel offset */		\
 		op = out++;						\
-		ip = in++;						\
+		ip = in + eng->e_choffs[ch] + (tidx * incr);		\
 									\
-		i = eng->e_fragfr;					\
+		i = fragfr;						\
 									\
 		do {	/* for each frame */				\
 			int32_t	sample = (TYPE)SWAP(*ip);		\
@@ -72,7 +68,7 @@
 			scaled /= AUDIO_VOL_SCALE;			\
 									\
 			*op = scaled;					\
-			ip += nch;					\
+			ip += incr;					\
 			op += nch;					\
 									\
 		} while (--i);						\
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Mon Sep 21 11:26:40 2009 -0400
@@ -2962,6 +2962,8 @@
 		cmn_err(CE_NOTE, "ioctl failed %d", rc);
 	}
 	kmem_free(zc, sizeof (zfs_cmd_t));
+	if (packed)
+		kmem_free(packed, len);
 out:
 	nvlist_free(nv);
 	(void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
--- a/usr/src/uts/common/io/comstar/stmf/stmf.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/comstar/stmf/stmf.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1387,7 +1387,7 @@
 
 	stmf_state.stmf_inventory_locked = 1;
 	stmf_state.stmf_service_running = 0;
-	stmf_delete_all_ppds();
+
 	mutex_exit(&stmf_state.stmf_lock);
 	for (ilport = stmf_state.stmf_ilportlist; ilport != NULL;
 	    ilport = ilport->ilport_next) {
--- a/usr/src/uts/common/io/lvm/md/md_subr.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/lvm/md/md_subr.c	Mon Sep 21 11:26:40 2009 -0400
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -112,6 +112,7 @@
 extern void		*lookup_entry(struct nm_next_hdr *, set_t,
 				side_t, mdkey_t, md_dev64_t, int);
 extern struct nm_next_hdr	*get_first_record(set_t, int, int);
+extern dev_t		getrootdev(void);
 
 struct mdq_anchor	md_done_daemon; /* done request queue */
 struct mdq_anchor	md_mstr_daemon; /* mirror error, WOW requests */
@@ -3380,6 +3381,7 @@
 	mdi_unit_t		*ui;
 	md_probedev_impl_t	*p;
 	int			err = 0;
+	set_t			setno;
 
 	p = (md_probedev_impl_t *)reqp->private_handle;
 	/*
@@ -3389,20 +3391,41 @@
 	 * locks this will prevent a metaclear operation being performed
 	 * on the metadevice because metaclear takes the readerlock (via
 	 * openclose lock).
+	 * To avoid a potential deadlock with the probe_fcn() causing i/o to
+	 * be issued to the writerlock'd metadevice we only grab the writerlock
+	 * if the unit is not an SVM root device.
 	 */
 	while (md_ioctl_lock_enter() == EINTR)
 		;
+	setno = MD_MIN2SET(reqp->mnum);
 	ui = MDI_UNIT(reqp->mnum);
 	if (ui != NULL) {
-		(void) md_unit_writerlock_common(ui, 0);
+		int	writer_grabbed;
+		dev_t	svm_root;
+
+		if ((setno == MD_LOCAL_SET) && root_is_svm) {
+			svm_root = getrootdev();
+
+			if (getminor(svm_root) == reqp->mnum) {
+				writer_grabbed = 0;
+			} else {
+				writer_grabbed = 1;
+				(void) md_unit_writerlock_common(ui, 0);
+			}
+		} else {
+			writer_grabbed = 1;
+			(void) md_unit_writerlock_common(ui, 0);
+		}
 		(void) md_ioctl_lock_exit(0, 0, 0, FALSE);
 		err = (*reqp->probe_fcn)(ui, reqp->mnum);
-		md_unit_writerexit(ui);
+		if (writer_grabbed) {
+			md_unit_writerexit(ui);
+		}
 	} else {
 		(void) md_ioctl_lock_exit(0, 0, 0, FALSE);
 	}
 
-	/* update the info info in the probe structure */
+	/* update the info in the probe structure */
 
 	mutex_enter(PROBE_MX(p));
 	if (err != 0) {
--- a/usr/src/uts/common/io/nxge/nxge_espc.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_espc.c	Mon Sep 21 11:26:40 2009 -0400
@@ -254,6 +254,8 @@
 	} else if (strncmp(nxgep->vpd_info.bd_model,
 	    NXGE_RFEM_BM_STR, strlen(NXGE_RFEM_BM_STR)) == 0) {
 		nxgep->hot_swappable_phy = B_TRUE;
+		nxgep->platform_type = P_NEPTUNE_GENERIC;
+		nxgep->niu_type = NEPTUNE_2_10GF;
 	}
 
 	/* If Alonso platform, replace "mif" for the last 2 ports phy-type */
--- a/usr/src/uts/common/io/nxge/nxge_hio.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_hio.c	Mon Sep 21 11:26:40 2009 -0400
@@ -132,9 +132,10 @@
 	int i;
 
 	nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
-	if (nhd == 0) {
+	if (nhd == NULL) {
 		nhd = KMEM_ZALLOC(sizeof (*nhd), KM_SLEEP);
 		MUTEX_INIT(&nhd->lock, NULL, MUTEX_DRIVER, NULL);
+		nhd->type = NXGE_HIO_TYPE_SERVICE;
 		nxge->nxge_hw_p->hio = (uintptr_t)nhd;
 	}
 
@@ -966,8 +967,7 @@
  *	Any domain
  */
 int
-nxge_hio_init(
-	nxge_t *nxge)
+nxge_hio_init(nxge_t *nxge)
 {
 	nxge_hio_data_t *nhd;
 	int i, region;
@@ -976,6 +976,10 @@
 	if (nhd == 0) {
 		nhd = KMEM_ZALLOC(sizeof (*nhd), KM_SLEEP);
 		MUTEX_INIT(&nhd->lock, NULL, MUTEX_DRIVER, NULL);
+		if (isLDOMguest(nxge))
+			nhd->type = NXGE_HIO_TYPE_GUEST;
+		else
+			nhd->type = NXGE_HIO_TYPE_SERVICE;
 		nxge->nxge_hw_p->hio = (uintptr_t)nhd;
 	}
 
@@ -1917,15 +1921,12 @@
 }
 
 int
-nxge_hio_addres(
-	nxge_hio_vr_t *vr,
-	mac_ring_type_t type,
-	uint64_t *map)
+nxge_hio_addres(nxge_hio_vr_t *vr, mac_ring_type_t type, uint64_t *map)
 {
 	nxge_t		*nxge = (nxge_t *)vr->nxge;
 	nxge_grp_t	*group;
 	int		groupid;
-	int		i;
+	int		i, rv = 0;
 	int		max_dcs;
 
 	NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_addres"));
@@ -1958,8 +1959,6 @@
 
 	for (i = 0; i < max_dcs; i++) {
 		if (group->map & (1 << i)) {
-			int rv;
-
 			if ((rv = nxge_hio_dc_share(nxge, vr, type, i)) < 0) {
 				if (*map == 0) /* Couldn't get even one DC. */
 					return (-rv);
@@ -1970,8 +1969,13 @@
 		}
 	}
 
+	if ((*map == 0) || (rv != 0)) {
+		NXGE_DEBUG_MSG((nxge, HIO_CTL,
+		    "<== nxge_hio_addres: rv(%x)", rv));
+		return (EIO);
+	}
+
 	NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_addres"));
-
 	return (0);
 }
 
--- a/usr/src/uts/common/io/nxge/nxge_hio_guest.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_hio_guest.c	Mon Sep 21 11:26:40 2009 -0400
@@ -192,13 +192,21 @@
 
 	NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_vr_add"));
 
+	if (nhd->type == NXGE_HIO_TYPE_SERVICE) {
+		/*
+		 * Can't add VR to the service domain from which we came.
+		 */
+		ASSERT(nhd->type == NXGE_HIO_TYPE_GUEST);
+		return (DDI_FAILURE);
+	}
+
 	/*
 	 * Get our HV cookie.
 	 */
 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxge->dip,
 	    0, "reg", &reg_val, &reg_len) != DDI_PROP_SUCCESS) {
 		NXGE_DEBUG_MSG((nxge, VPD_CTL, "`reg' property not found"));
-		return (NXGE_ERROR);
+		return (DDI_FAILURE);
 	}
 
 	cookie = (uint32_t)(reg_val[0]);
@@ -209,7 +217,7 @@
 	if (hv_rv != 0) {
 		NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 		    "vr->getinfo() failed"));
-		return (NXGE_ERROR);
+		return (DDI_FAILURE);
 	}
 
 	/*
@@ -239,7 +247,7 @@
 		NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 		    "nxge_hio_vr_add(%d): cookie(0x%x)\n",
 		    nxge->instance, cookie));
-		return (NXGE_ERROR);
+		return (DDI_FAILURE);
 	}
 
 	vr = &nhd->vr[vr_index];
@@ -265,7 +273,7 @@
 	if (nxge_hio_intr_init(nxge) != NXGE_OK) {
 		NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 		    "nxge_hio_intr_init() failed"));
-		return (NXGE_ERROR);
+		return (DDI_FAILURE);
 	}
 
 	/*
@@ -282,7 +290,7 @@
 		if (hv_rv != 0) {
 			NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 			    "tx->get_map() failed"));
-			return (NXGE_ERROR);
+			return (DDI_FAILURE);
 		}
 		res_map_parse(nxge, NXGE_TRANSMIT_GROUP, tx_map);
 
@@ -297,7 +305,7 @@
 				if (dc == 0) {
 					NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 					    "DC add failed"));
-					return (NXGE_ERROR);
+					return (DDI_FAILURE);
 				}
 				dc->channel = (nxge_channel_t)i;
 			}
@@ -315,7 +323,7 @@
 		if (hv_rv != 0) {
 			NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 			    "rx->get_map() failed"));
-			return (NXGE_ERROR);
+			return (DDI_FAILURE);
 		}
 		res_map_parse(nxge, NXGE_RECEIVE_GROUP, rx_map);
 
@@ -330,7 +338,7 @@
 				if (dc == 0) {
 					NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
 					    "DC add failed"));
-					return (NXGE_ERROR);
+					return (DDI_FAILURE);
 				}
 				dc->channel = (nxge_channel_t)i;
 			}
@@ -341,14 +349,14 @@
 	if (status != NXGE_OK) {
 		cmn_err(CE_WARN, "nxge(%d): nxge_mac_register failed\n",
 		    nxge->instance);
-		return (status);
+		return (DDI_FAILURE);
 	}
 
 	nxge->hio_vr = vr;	/* For faster lookups. */
 
 	NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_vr_add"));
 
-	return (NXGE_OK);
+	return (DDI_SUCCESS);
 }
 
 /*
--- a/usr/src/uts/common/io/nxge/nxge_mac.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_mac.c	Mon Sep 21 11:26:40 2009 -0400
@@ -312,6 +312,10 @@
 	 */
 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
 		nxgep->hot_swappable_phy = B_TRUE;
+		if (portn > 1) {
+			return (NXGE_ERROR);
+		}
+
 		/*
 		 * If this is the 2nd NIU port, then check 2 addresses
 		 * to take care of the Goa NEM card. Port 1 can have addr 17
--- a/usr/src/uts/common/io/nxge/nxge_main.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_main.c	Mon Sep 21 11:26:40 2009 -0400
@@ -128,10 +128,12 @@
 nxge_rxbuf_threshold_t nxge_rx_threshold_lo = NXGE_RX_COPY_3;
 
 /* Use kmem_alloc() to allocate data buffers. */
-#if defined(_BIG_ENDIAN)
+#if defined(__sparc)
 uint32_t	nxge_use_kmem_alloc = 1;
+#elif defined(__i386)
+uint32_t	nxge_use_kmem_alloc = 0;
 #else
-uint32_t	nxge_use_kmem_alloc = 0;
+uint32_t	nxge_use_kmem_alloc = 1;
 #endif
 
 rtrace_t npi_rtracebuf;
@@ -822,11 +824,12 @@
 	if (isLDOMguest(nxgep)) {
 		/* Find our VR & channel sets. */
 		status = nxge_hio_vr_add(nxgep);
-		if (status != NXGE_OK) {
-			NXGE_DEBUG_MSG((nxgep, DDI_CTL,
+		if (status != DDI_SUCCESS) {
+			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 			    "nxge_hio_vr_add failed"));
 			(void) hsvc_unregister(&nxgep->niu_hsvc);
 			nxgep->niu_hsvc_available = B_FALSE;
+			goto nxge_attach_fail;
 		}
 		goto nxge_attach_exit;
 	}
@@ -6530,6 +6533,8 @@
 	p_nxge_hw_list_t	hw_p;
 	dev_info_t 		*p_dip;
 
+	ASSERT(nxgep != NULL);
+
 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_init_common_device"));
 
 	p_dip = nxgep->p_dip;
@@ -6644,6 +6649,8 @@
 	p_nxge_hw_pt_cfg_t	p_cfgp;
 	dev_info_t 		*p_dip;
 
+	ASSERT(nxgep != NULL);
+
 	NXGE_DEBUG_MSG((nxgep, MOD_CTL, "==> nxge_uninit_common_device"));
 	if (nxgep->nxge_hw_p == NULL) {
 		NXGE_DEBUG_MSG((nxgep, MOD_CTL,
--- a/usr/src/uts/common/io/nxge/nxge_rxdma.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_rxdma.c	Mon Sep 21 11:26:40 2009 -0400
@@ -18,6 +18,7 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
@@ -4268,12 +4269,13 @@
 
 	if (isLDOMguest(nxgep)) {
 		/* Add interrupt handler for this channel. */
-		if (nxge_hio_intr_add(nxgep, VP_BOUND_RX, channel)
-		    != NXGE_OK) {
+		status = nxge_hio_intr_add(nxgep, VP_BOUND_RX, channel);
+		if (status != NXGE_OK) {
 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 			    " nxge_rxdma_start_channel: "
 			    " nxge_hio_intr_add failed (0x%08x channel %d)",
-		    status, channel));
+			    status, channel));
+			return (status);
 		}
 	}
 
@@ -4556,7 +4558,6 @@
 	rbrp = (p_rx_rbr_ring_t)nxgep->rx_rbr_rings->rbr_rings[channel];
 	rcrp = (p_rx_rcr_ring_t)nxgep->rx_rcr_rings->rcr_rings[channel];
 
-	MUTEX_ENTER(&rcrp->lock);
 	MUTEX_ENTER(&rbrp->lock);
 	MUTEX_ENTER(&rbrp->post_lock);
 
@@ -4651,20 +4652,17 @@
 
 	MUTEX_EXIT(&rbrp->post_lock);
 	MUTEX_EXIT(&rbrp->lock);
-	MUTEX_EXIT(&rcrp->lock);
 
 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 	    "Recovery Successful, RxDMAChannel#%d Restored",
 	    channel));
 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_rxdma_fatal_err_recover"));
-
 	return (NXGE_OK);
+
 fail:
 	MUTEX_EXIT(&rbrp->post_lock);
 	MUTEX_EXIT(&rbrp->lock);
-	MUTEX_EXIT(&rcrp->lock);
 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
-
 	return (NXGE_ERROR | rs);
 }
 
@@ -4673,6 +4671,7 @@
 {
 	nxge_grp_set_t *set = &nxgep->rx_set;
 	nxge_status_t status = NXGE_OK;
+	p_rx_rcr_ring_t rcrp;
 	int rdc;
 
 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_rx_port_fatal_err_recover"));
@@ -4689,10 +4688,16 @@
 
 	for (rdc = 0; rdc < NXGE_MAX_RDCS; rdc++) {
 		if ((1 << rdc) & set->owned.map) {
-			if (nxge_rxdma_fatal_err_recover(nxgep, rdc)
-			    != NXGE_OK) {
-				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
-				    "Could not recover channel %d", rdc));
+			rcrp = nxgep->rx_rcr_rings->rcr_rings[rdc];
+			if (rcrp != NULL) {
+				MUTEX_ENTER(&rcrp->lock);
+				if (nxge_rxdma_fatal_err_recover(nxgep,
+				    rdc) != NXGE_OK) {
+					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
+					    "Could not recover "
+					    "channel %d", rdc));
+				}
+				MUTEX_EXIT(&rcrp->lock);
 			}
 		}
 	}
--- a/usr/src/uts/common/io/nxge/nxge_txdma.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/nxge/nxge_txdma.c	Mon Sep 21 11:26:40 2009 -0400
@@ -209,11 +209,13 @@
 		nxgep->statsp->tdc_ksp[channel] = 0;
 	}
 
-	(void) nxge_txdma_stop_channel(nxgep, channel);
+	if (nxge_txdma_stop_channel(nxgep, channel) != NXGE_OK)
+		goto nxge_uninit_txdma_channel_exit;
+
 	nxge_unmap_txdma_channel(nxgep, channel);
 
-	NXGE_DEBUG_MSG((nxgep, MEM3_CTL,
-	    "<== nxge_uninit_txdma_channel"));
+nxge_uninit_txdma_channel_exit:
+	NXGE_DEBUG_MSG((nxgep, MEM3_CTL, "<== nxge_uninit_txdma_channel"));
 }
 
 void
@@ -684,6 +686,8 @@
 				    (mblk_len < stuff_len)) {
 					stuff_len -= mblk_len;
 					nmp = nmp->b_cont;
+					if (nmp)
+						mblk_len = MBLKL(nmp);
 				}
 				ASSERT(nmp);
 				up = (uint16_t *)(nmp->b_rptr + stuff_len);
@@ -2946,7 +2950,16 @@
 	 */
 	(void) nxge_txdma_stop_inj_err(nxgep, channel);
 
+	if (nxgep->tx_rings == NULL) {
+		status = NXGE_ERROR;
+		goto nxge_txdma_stop_channel_exit;
+	}
+
 	tx_ring_p = nxgep->tx_rings->rings[channel];
+	if (tx_ring_p == NULL) {
+		status = NXGE_ERROR;
+		goto nxge_txdma_stop_channel_exit;
+	}
 
 	/*
 	 * Reset TXDMA channel
--- a/usr/src/uts/common/io/scsi/targets/st.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/scsi/targets/st.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1331,8 +1331,8 @@
 		    (un->un_pos.blkno != 0)) ||	/* Or within first file */
 		    ((un->un_pos.pmode == logical) &&
 		    (un->un_pos.lgclblkno > 0))) &&
-		    ((un->un_state != ST_STATE_CLOSED) &&
-		    (un->un_laststate != ST_STATE_CLOSING)))) {
+		    ((un->un_state == ST_STATE_CLOSED) &&
+		    (un->un_laststate == ST_STATE_CLOSING)))) {
 
 			ST_DEBUG(ST_DEVINFO, st_label, SCSI_DEBUG,
 			    "cannot detach: pmode=%d fileno=0x%x, blkno=0x%x"
@@ -17033,6 +17033,12 @@
 	case CMD_TRAN_ERR:
 		action = QUE_COMMAND;
 		break;
+	case CMD_DEV_GONE:
+		if (un->un_multipath)
+			action = PATH_FAILED;
+		else
+			action = COMMAND_DONE_ERROR;
+		break;
 	default:
 		ST_DEBUG(ST_DEVINFO, st_label, CE_PANIC,
 		    "pkt_reason not handled yet %s",
--- a/usr/src/uts/common/io/tpm/tpm.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/io/tpm/tpm.c	Mon Sep 21 11:26:40 2009 -0400
@@ -421,7 +421,9 @@
 
 	ret = itpm_command(tpm, buf, sizeof (buf));
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: itpm_command failed", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: itpm_command failed", myname);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -433,9 +435,11 @@
 	 */
 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
 	if (len != 4 * sizeof (uint32_t)) {
-		cmn_err(CE_WARN, "%s: capability response size should be %d"
-		    "instead it's %d",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: capability response size should be %d"
+		    "instead len = %d",
 		    myname, (int)(4 * sizeof (uint32_t)), (int)len);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -503,8 +507,10 @@
 
 	ret = itpm_command(tpm, buf, sizeof (buf));
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: itpm_command failed with ret code: 0x%x",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x",
 			myname, ret);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -516,9 +522,11 @@
 	 */
 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
 	if (len != 3 * sizeof (uint32_t)) {
-		cmn_err(CE_WARN, "%s: capability response should be %d, "
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: capability response should be %d, "
 		    "instead, it's %d",
 		    myname, (int)(3 * sizeof (uint32_t)), (int)len);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -576,8 +584,10 @@
 
 	ret = itpm_command(tpm, buf, sizeof (buf));
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: itpm_command failed with ret code: 0x%x",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x",
 			myname, ret);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -586,11 +596,11 @@
 	 */
 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
 	if (len < TPM_CAP_VERSION_INFO_SIZE) {
-		cmn_err(CE_WARN, "%s: capability response should be greater"
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: capability response should be greater"
 		    " than %d, instead, it's %d",
-		    myname,
-		    TPM_CAP_VERSION_INFO_SIZE,
-		    len);
+		    myname, TPM_CAP_VERSION_INFO_SIZE, len);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -616,7 +626,7 @@
 	 */
 	if (tpm->vers_info.version.major != 1 &&
 	    tpm->vers_info.version.minor != 2) {
-		cmn_err(CE_WARN, "%s: Unsupported TPM version (%d.%d)",
+		cmn_err(CE_WARN, "!%s: Unsupported TPM version (%d.%d)",
 		    myname,
 		    tpm->vers_info.version.major,		/* Version */
 		    tpm->vers_info.version.minor);
@@ -644,7 +654,9 @@
 	/* Need a longer timeout */
 	ret = itpm_command(tpm, buf, sizeof (buf));
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: itpm_command failed", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: itpm_command failed", myname);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -669,25 +681,31 @@
 	/* Is it a TSC_ORDINAL? */
 	if (ordinal & TSC_ORDINAL_MASK) {
 		if (ordinal > TSC_ORDINAL_MAX) {
+#ifdef DEBUG
 			cmn_err(CE_WARN,
-			    "%s: tsc ordinal: %d exceeds MAX: %d",
+			    "!%s: tsc ordinal: %d exceeds MAX: %d",
 			    myname, ordinal, TSC_ORDINAL_MAX);
+#endif
 			return (0);
 		}
 		index = tsc_ords_duration[ordinal];
 	} else {
 		if (ordinal > TPM_ORDINAL_MAX) {
+#ifdef DEBUG
 			cmn_err(CE_WARN,
-			    "%s: ordinal %d exceeds MAX: %d",
+			    "!%s: ordinal %d exceeds MAX: %d",
 			    myname, ordinal, TPM_ORDINAL_MAX);
+#endif
 			return (0);
 		}
 		index = tpm_ords_duration[ordinal];
 	}
 
 	if (index > TPM_DURATION_MAX_IDX) {
-		cmn_err(CE_WARN, "%s: FATAL:index '%d' is out of bound",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: duration index '%d' is out of bounds",
 		    myname, index);
+#endif
 		return (0);
 	}
 	return (tpm->duration[index]);
@@ -710,22 +728,21 @@
 	/* The byte order is network byte order so convert it */
 	count = load32(buf, TPM_PARAMSIZE_OFFSET);
 
-	if (count == 0) {
-		cmn_err(CE_WARN, "%s: count=0, no data? %d", myname,
-		    (int)bufsiz);
-		return (DDI_FAILURE);
-	}
-	if (count > bufsiz) {
-		cmn_err(CE_WARN, "%s: invalid count value:count:%d > bufsiz %d",
-		    myname, (int)count, (int)bufsiz);
+	if (count == 0 || (count > bufsiz)) {
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: invalid byte count value "
+		    "(%d > bufsiz %d)", myname, (int)count, (int)bufsiz);
+#endif
 		return (DDI_FAILURE);
 	}
 
 	/* Send the command */
 	ret = tis_send_data(tpm, buf, count);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tis_send_data failed with error %x",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_send_data failed with error %x",
 		    myname, ret);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -735,7 +752,9 @@
 	 */
 	ret = tis_recv_data(tpm, buf, bufsiz);
 	if (ret < TPM_HEADER_SIZE) {
-		cmn_err(CE_WARN, "%s: tis_recv_data failed", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_recv_data failed", myname);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -743,11 +762,11 @@
 	ret = load32(buf, TPM_RETURN_OFFSET);
 	if (ret != TPM_SUCCESS) {
 		if (ret == TPM_E_DEACTIVATED)
-			cmn_err(CE_WARN, "%s: TPM is deactivated", myname);
+			cmn_err(CE_WARN, "!%s: TPM is deactivated", myname);
 		else if (ret == TPM_E_DISABLED)
-			cmn_err(CE_WARN, "%s: TPM is disabled", myname);
+			cmn_err(CE_WARN, "!%s: TPM is disabled", myname);
 		else
-			cmn_err(CE_WARN, "%s: TPM error code 0x%0x",
+			cmn_err(CE_WARN, "!%s: TPM error code 0x%0x",
 			    myname, ret);
 		return (DDI_FAILURE);
 	}
@@ -853,18 +872,22 @@
 	ASSERT(tpm != NULL && buf != NULL);
 
 	if (bufsiz < TPM_HEADER_SIZE) {
-		/* There should be at least tag,paramsize,return code */
-		cmn_err(CE_WARN, "%s: received data should contain at least "
+		/* There should be at least tag, paramsize, return code */
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: received data should contain at least "
 		    "the header which is %d bytes long",
 		    myname, TPM_HEADER_SIZE);
+#endif
 		goto OUT;
 	}
 
 	/* Read tag(2 bytes), paramsize(4), and result(4) */
 	size = receive_data(tpm, buf, TPM_HEADER_SIZE);
 	if (size < TPM_HEADER_SIZE) {
-		cmn_err(CE_WARN, "%s: getting the TPM_HEADER failed: size=%d",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: recv TPM_HEADER failed, size = %d",
 		    myname, size);
+#endif
 		goto OUT;
 	}
 
@@ -873,9 +896,11 @@
 	/* Get 'paramsize'(4 bytes)--it includes tag and paramsize */
 	expected = load32(buf, TPM_PARAMSIZE_OFFSET);
 	if (expected > bufsiz) {
-		cmn_err(CE_WARN, "%s: paramSize is bigger "
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: paramSize is bigger "
 		    "than the requested size: paramSize=%d bufsiz=%d result=%d",
 		    myname, (int)expected, (int)bufsiz, cmdresult);
+#endif
 		goto OUT;
 	}
 
@@ -883,8 +908,10 @@
 	size += receive_data(tpm, (uint8_t *)&buf[TPM_HEADER_SIZE],
 	    expected - TPM_HEADER_SIZE);
 	if (size < expected) {
-		cmn_err(CE_WARN, "%s: received data length=%d "
-		    "is less than expected = %d", myname, size, expected);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: received data length (%d) "
+		    "is less than expected (%d)", myname, size, expected);
+#endif
 		goto OUT;
 	}
 
@@ -893,15 +920,19 @@
 
 	status = tis_get_status(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: TPM didn't set stsValid after its I/O: "
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: TPM didn't set stsValid after its I/O: "
 		    "status = 0x%08X", myname, status);
+#endif
 		goto OUT;
 	}
 
 	/* There is still more data? */
 	if (status & TPM_STS_DATA_AVAIL) {
-		cmn_err(CE_WARN, "%s: Status TPM_STS_DATA_AVAIL set:0x%08X",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: TPM_STS_DATA_AVAIL is set:0x%08X",
 		    myname, status);
+#endif
 		goto OUT;
 	}
 
@@ -932,8 +963,9 @@
 	ASSERT(tpm != NULL && buf != NULL);
 
 	if (bufsiz == 0) {
-		cmn_err(CE_WARN, "%s: passed in argument bufsize is zero",
-		    myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: bufsiz arg is zero", myname);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -944,10 +976,12 @@
 		tpm_set_ready(tpm);
 		ret = tpm_wait_for_stat(tpm, TPM_STS_CMD_READY, tpm->timeout_b);
 		if (ret != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: could not put the TPM "
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: could not put the TPM "
 			    "in the command ready state:"
 			    "tpm_wait_for_stat returned error",
 			    myname);
+#endif
 			goto FAIL;
 		}
 	}
@@ -961,8 +995,10 @@
 	while (count < bufsiz - 1) {
 		burstcnt = tpm_get_burstcount(tpm);
 		if (burstcnt == 0) {
-			cmn_err(CE_WARN, "%s: tpm_get_burstcnt returned error",
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: tpm_get_burstcnt returned error",
 			    myname);
+#endif
 			ret = DDI_FAILURE;
 			goto FAIL;
 		}
@@ -975,8 +1011,10 @@
 		ret = tpm_wait_for_stat(tpm,
 		    (TPM_STS_VALID | TPM_STS_DATA_EXPECT), tpm->timeout_c);
 		if (ret != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: TPM didn't enter stsvalid "
-			    "state after sending the data:", myname);
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: TPM didn't enter STS_VALID "
+			    "state", myname);
+#endif
 			goto FAIL;
 		}
 	}
@@ -989,15 +1027,20 @@
 	/* Wait for the TPM to enter Valid State */
 	ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c);
 	if (ret == DDI_FAILURE) {
-		cmn_err(CE_WARN, "%s: tpm didn't enter Valid state", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tpm didn't enter STS_VALID state",
+		    myname);
+#endif
 		goto FAIL;
 	}
 
 	status = tis_get_status(tpm);
 	/* The TPM should NOT be expecing more data at this point */
 	if ((status & TPM_STS_DATA_EXPECT) != 0) {
-		cmn_err(CE_WARN, "%s: DATA_EXPECT is set (shouldn't be) after "
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: DATA_EXPECT should not be set after "
 		    "writing the last byte: status=0x%08X", myname, status);
+#endif
 		ret = DDI_FAILURE;
 		goto FAIL;
 	}
@@ -1014,18 +1057,21 @@
 	ret = tpm_wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 	    tpm_get_ordinal_duration(tpm, ordinal));
 	if (ret == DDI_FAILURE) {
+#ifdef DEBUG
 		status = tis_get_status(tpm);
 		if (!(status & TPM_STS_DATA_AVAIL) ||
 		    !(status & TPM_STS_VALID)) {
-			cmn_err(CE_WARN, "%s: TPM not ready or valid "
-			    "(ordinal = %d timeout = %ld)",
+			cmn_err(CE_WARN, "!%s: TPM not ready or valid "
+			    "(ordinal = %d timeout = %ld status = 0x%0x)",
 			    myname, ordinal,
-			    tpm_get_ordinal_duration(tpm, ordinal));
+			    tpm_get_ordinal_duration(tpm, ordinal),
+			    status);
 		} else {
-			cmn_err(CE_WARN, "%s: tpm_wait_for_stat "
-			    "(DATA_AVAIL | VALID) failed: STS = 0x%0X",
+			cmn_err(CE_WARN, "!%s: tpm_wait_for_stat "
+			    "(DATA_AVAIL | VALID) failed status = 0x%0X",
 			    myname, status);
 		}
+#endif
 		goto FAIL;
 	}
 	return (DDI_SUCCESS);
@@ -1107,9 +1153,11 @@
 	while (tis_check_active_locality(tpm, locality)
 		!= DDI_SUCCESS) {
 		if (ddi_get_lbolt() >= timeout) {
-			cmn_err(CE_WARN, "%s (interrupt-disabled) "
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: (interrupt-disabled) "
 			    "tis_request_locality timed out (timeout_a = %ld)",
 			    myname, tpm->timeout_a);
+#endif
 			return (DDI_FAILURE);
 		}
 		delay(tpm->timeout_poll);
@@ -1134,9 +1182,11 @@
 	while ((tis_get_status(tpm) & mask) != mask) {
 		if (ddi_get_lbolt() >= absolute_timeout) {
 			/* Timeout reached */
-			cmn_err(CE_WARN, "%s: using "
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: using "
 			    "polling - reached timeout (%ld usecs)",
 			    myname, drv_hztousec(timeout));
+#endif
 			return (DDI_FAILURE);
 		}
 		delay(tpm->timeout_poll);
@@ -1182,22 +1232,21 @@
 
 	/* Upper 3 bytes should always return 0 */
 	if (intf_caps & 0x7FFFFF00) {
-#ifdef DEBUG
-		cmn_err(CE_WARN, "%s: bad intf_caps value 0x%0X",
+		cmn_err(CE_WARN, "!%s: bad intf_caps value 0x%0X",
 		    myname, intf_caps);
-#endif
 		return (DDI_FAILURE);
 	}
 
 	/* These two interrupts are mandatory */
 	if (!(intf_caps & TPM_INTF_INT_LOCALITY_CHANGE_INT)) {
-		cmn_err(CE_WARN, "%s: Mandatory capability Locality Change Int "
+		cmn_err(CE_WARN,
+		    "!%s: Mandatory capability Locality Change Int "
 		    "not supported", myname);
 		return (DDI_FAILURE);
 	}
 	if (!(intf_caps & TPM_INTF_INT_DATA_AVAIL_INT)) {
-		cmn_err(CE_WARN, "%s: Mandatory capability Data Available Int "
-		    "not supported", myname);
+		cmn_err(CE_WARN, "!%s: Mandatory capability Data Available Int "
+		    "not supported.", myname);
 		return (DDI_FAILURE);
 	}
 
@@ -1207,7 +1256,7 @@
 	 */
 	ret = tis_request_locality(tpm, DEFAULT_LOCALITY);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: Unable to request locality %d", myname,
+		cmn_err(CE_WARN, "!%s: Unable to request locality %d", myname,
 		    DEFAULT_LOCALITY);
 		return (DDI_FAILURE);
 	} /* Now we can refer to the locality as tpm->locality */
@@ -1218,20 +1267,20 @@
 	/* Get the real timeouts from the TPM */
 	ret = tpm_get_timeouts(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tpm_get_timeouts error", myname);
+		cmn_err(CE_WARN, "!%s: tpm_get_timeouts error", myname);
 		return (DDI_FAILURE);
 	}
 
 	ret = tpm_get_duration(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tpm_get_duration error", myname);
+		cmn_err(CE_WARN, "!%s: tpm_get_duration error", myname);
 		return (DDI_FAILURE);
 	}
 
 	/* This gets the TPM version information */
 	ret = tpm_get_version(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tpm_get_version error", myname);
+		cmn_err(CE_WARN, "!%s: tpm_get_version error", myname);
 		return (DDI_FAILURE);
 	}
 
@@ -1241,7 +1290,7 @@
 	 */
 	ret = tpm_continue_selftest(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tpm_continue_selftest error", myname);
+		cmn_err(CE_WARN, "!%s: tpm_continue_selftest error", myname);
 		return (DDI_FAILURE);
 	}
 	return (DDI_SUCCESS);
@@ -1256,14 +1305,17 @@
 	int ret;
 
 	ret = ddi_soft_state_init(&statep, sizeof (tpm_state_t), 1);
-	if (ret)
-{
-		cmn_err(CE_WARN, "ddi_soft_state_init failed: %d", ret);
+	if (ret) {
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!ddi_soft_state_init failed: %d", ret);
+#endif
 		return (ret);
-}
+	}
 	ret = mod_install(&tpm_ml);
 	if (ret != 0) {
-		cmn_err(CE_WARN, "_init: mod_install returned non-zero");
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!_init: mod_install returned non-zero");
+#endif
 		ddi_soft_state_fini(&statep);
 		return (ret);
 	}
@@ -1276,8 +1328,10 @@
 {
 	int ret;
 	ret = mod_info(&tpm_ml, modinfop);
+#ifdef DEBUG
 	if (ret == 0)
-		cmn_err(CE_WARN, "mod_info failed: %d", ret);
+		cmn_err(CE_WARN, "!mod_info failed: %d", ret);
+#endif
 
 	return (ret);
 }
@@ -1345,16 +1399,18 @@
 		if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) {
 			tpm = ddi_get_soft_state(statep, instance);
 			if (tpm == NULL) {
+#ifdef DEBUG
 				cmn_err(CE_WARN,
-				    "%s: cannot get state information.",
+				    "!%s: cannot get state information.",
 				    myname);
+#endif
 				return (DDI_FAILURE);
 			}
 			tpm->dip = dip;
 		} else {
 #ifdef DEBUG
 			cmn_err(CE_WARN,
-			    "%s: cannot allocate state information.",
+			    "!%s: cannot allocate state information.",
 			    myname);
 #endif
 			return (DDI_FAILURE);
@@ -1363,13 +1419,17 @@
 	case DDI_RESUME:
 		tpm = ddi_get_soft_state(statep, instance);
 		if (tpm == NULL) {
-			cmn_err(CE_WARN, "%s: cannot get state information.",
+#ifdef DEBUG
+			cmn_err(CE_WARN, "!%s: cannot get state information.",
 			    myname);
+#endif
 			return (DDI_FAILURE);
 		}
 		return (tpm_resume(tpm));
 	default:
-		cmn_err(CE_WARN, "%s: cmd %d is not implemented", myname, cmd);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: cmd %d is not implemented", myname, cmd);
+#endif
 		ret = DDI_FAILURE;
 		goto FAIL;
 	}
@@ -1380,7 +1440,7 @@
 #ifdef sun4v
 	ret = hsvc_register(&hsvc_tpm, &hsvc_tpm_minor);
 	if (ret != 0) {
-		cmn_err(CE_WARN, "%s: failed to register with "
+		cmn_err(CE_WARN, "!%s: failed to register with "
 		    "hypervisor: 0x%0x", myname, ret);
 		goto FAIL;
 	}
@@ -1429,8 +1489,10 @@
 	/* Enable TPM device according to the TIS specification */
 	ret = tis_init(tpm);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tis_init() failed with error %d",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_init() failed with error %d",
 		    myname, ret);
+#endif
 
 		/* We need to clean up the ddi_regs_map_setup call */
 		if (tpm->flags & TPM_DIDREGSMAP) {
@@ -1471,7 +1533,9 @@
 	ret = ddi_create_minor_node(dip, "tpm", S_IFCHR, ddi_get_instance(dip),
 	    DDI_PSEUDO, 0);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: ddi_create_minor_node failed", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: ddi_create_minor_node failed", myname);
+#endif
 		goto FAIL;
 	}
 	tpm->flags |= TPM_DIDMINOR;
@@ -1479,7 +1543,7 @@
 #ifdef KCF_TPM_RNG_PROVIDER
 	/* register RNG with kcf */
 	if (tpmrng_register(tpm) != DDI_SUCCESS)
-		cmn_err(CE_WARN, "%s: tpm RNG failed to register with kcf",
+		cmn_err(CE_WARN, "!%s: tpm RNG failed to register with kcf",
 		    myname);
 #endif
 
@@ -1576,8 +1640,10 @@
 		return (DDI_FAILURE);
 
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (ENXIO);
 	}
 
@@ -1588,7 +1654,9 @@
 	case DDI_SUSPEND:
 		return (tpm_suspend(tpm));
 	default:
-		cmn_err(CE_WARN, "%s: case %d not implemented", myname, cmd);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: case %d not implemented", myname, cmd);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -1612,8 +1680,10 @@
 
 	instance = ddi_get_instance(dip);
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (DDI_FAILURE);
 	}
 
@@ -1625,7 +1695,9 @@
 		*resultp = 0;
 		break;
 	default:
-		cmn_err(CE_WARN, "%s: cmd %d is not implemented", myname, cmd);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: cmd %d is not implemented", myname, cmd);
+#endif
 		return (DDI_FAILURE);
 	}
 	return (DDI_SUCCESS);
@@ -1647,21 +1719,27 @@
 
 	instance = getminor(*devp);
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (ENXIO);
 	}
 	if (otyp != OTYP_CHR) {
-		cmn_err(CE_WARN, "%s: otyp(%d) != OTYP_CHR(%d)",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)",
 		    myname, otyp, OTYP_CHR);
+#endif
 		return (EINVAL);
 	}
 	TPM_EXCLUSIVE_LOCK(tpm);
 
 	mutex_enter(&tpm->dev_lock);
 	if (tpm->dev_held) {
-		cmn_err(CE_WARN, "%s: the device is already being used",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: the device is already being used",
 		    myname);
+#endif
 		mutex_exit(&tpm->dev_lock);
 		return (EBUSY);
 	}
@@ -1683,13 +1761,17 @@
 
 	instance = getminor(dev);
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (ENXIO);
 	}
 	if (otyp != OTYP_CHR) {
-		cmn_err(CE_WARN, "%s: otyp(%d) != OTYP_CHR(%d)",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)",
 		    myname, otyp, OTYP_CHR);
+#endif
 		return (EINVAL);
 	}
 	TPM_EXCLUSIVE_LOCK(tpm);
@@ -1716,12 +1798,16 @@
 
 	instance = getminor(dev);
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (ENXIO);
 	}
 	if (uiop == NULL) {
-		cmn_err(CE_WARN, "%s: passed in uiop is NULL", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: passed in uiop is NULL", myname);
+#endif
 		return (EFAULT);
 	}
 
@@ -1735,25 +1821,31 @@
 		return (ret);
 
 	if (uiop->uio_resid > tpm->bufsize) {
-		cmn_err(CE_WARN, "%s: read_in data is bigger "
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: read_in data is bigger "
 		    "than tpm->bufsize:read in:%d, bufsiz:%d",
 		    myname, (int)uiop->uio_resid, (int)tpm->bufsize);
+#endif
 		ret = EIO;
 		goto OUT;
 	}
 
 	ret = tis_recv_data(tpm, tpm->iobuf, tpm->bufsize);
 	if (ret < TPM_HEADER_SIZE) {
-		cmn_err(CE_WARN, "%s: tis_recv_data returned error", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_recv_data returned error", myname);
+#endif
 		ret = EIO;
 		goto OUT;
 	}
 
 	size = load32(tpm->iobuf, 2);
 	if (ret != size) {
-		cmn_err(CE_WARN, "%s: tis_recv_data:"
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_recv_data:"
 		    "expected size=%d, actually read=%d",
 		    myname, size, ret);
+#endif
 		ret = EIO;
 		goto OUT;
 	}
@@ -1761,7 +1853,9 @@
 	/* Send the buffer from the kernel to the userspace */
 	ret = uiomove(tpm->iobuf, size, UIO_READ, uiop);
 	if (ret) {
-		cmn_err(CE_WARN, "%s: uiomove returned error", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: uiomove returned error", myname);
+#endif
 		goto OUT;
 	}
 
@@ -1788,13 +1882,17 @@
 
 	instance = getminor(dev);
 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
-		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
 		    myname);
+#endif
 		return (ENXIO);
 	}
 
 	if (uiop == NULL) {
-		cmn_err(CE_WARN, "%s: passed in uiop is NULL", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: passed in uiop is NULL", myname);
+#endif
 		return (EFAULT);
 	}
 
@@ -1802,7 +1900,9 @@
 
 	len = uiop->uio_resid;
 	if (len == 0) {
-		cmn_err(CE_WARN, "%s: requested read of len 0", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: requested read of len 0", myname);
+#endif
 		return (0);
 	}
 
@@ -1815,9 +1915,11 @@
 	/* Copy the header and parse the structure to find out the size... */
 	ret = uiomove(tpm->iobuf, TPM_HEADER_SIZE, UIO_WRITE, uiop);
 	if (ret) {
-		cmn_err(CE_WARN, "%s: uiomove returned error"
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: uiomove returned error"
 		    "while getting the the header",
 		    myname);
+#endif
 		goto OUT;
 	}
 
@@ -1826,9 +1928,11 @@
 
 	/* Copy the command to the contiguous buffer */
 	if (size > tpm->bufsize) {
-		cmn_err(CE_WARN, "%s: size %d is greater than "
-		    "the tpm's input buffer size %d",
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: size %d is greater than "
+		    "the tpm input buffer size %d",
 		    myname, (int)size, (int)tpm->bufsize);
+#endif
 		ret = ENXIO;
 		goto OUT;
 	}
@@ -1838,15 +1942,19 @@
 	    UIO_WRITE, uiop);
 
 	if (ret) {
-		cmn_err(CE_WARN, "%s: uiomove returned error"
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: uiomove returned error"
 		    "while getting the rest of the command", myname);
+#endif
 		goto OUT;
 	}
 
 	/* Send the command */
 	ret = tis_send_data(tpm, tpm->iobuf, size);
 	if (ret != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: tis_send_data returned error", myname);
+#ifdef DEBUG
+		cmn_err(CE_WARN, "!%s: tis_send_data returned error", myname);
+#endif
 		ret = EFAULT;
 		goto OUT;
 	}
@@ -1880,7 +1988,7 @@
 			/* Timeout reached */
 			mutex_exit(&tpm->iobuf_lock);
 #ifdef DEBUG
-			cmn_err(CE_WARN, "tpm_io_lock:iorequest timed out");
+			cmn_err(CE_WARN, "!tpm_io_lock:iorequest timed out");
 #endif
 			return (ETIME);
 		}
@@ -1991,9 +2099,10 @@
 	(void) memcpy(rngmech, "random", 6);
 	ret = crypto_load_dev_disabled("tpm", ddi_get_instance(tpm->dip),
 	    1, rngmech);
-	if (ret != CRYPTO_SUCCESS) {
-		cmn_err(CE_WARN, "crypto_load_dev_disabled failed (%d)", ret);
-	}
+#ifdef DEBUG
+	if (ret != CRYPTO_SUCCESS)
+		cmn_err(CE_WARN, "!crypto_load_dev_disabled failed (%d)", ret);
+#endif
 	return (DDI_SUCCESS);
 }
 
@@ -2076,7 +2185,7 @@
 
 	if (ret != DDI_SUCCESS) {
 #ifdef DEBUG
-		cmn_err(CE_WARN, "tpmrng_seed_random failed");
+		cmn_err(CE_WARN, "!tpmrng_seed_random failed");
 #endif
 		return (CRYPTO_FAILED);
 	}
@@ -2125,7 +2234,7 @@
 	ret = itpm_command(tpm, cmdbuf, buflen);
 	if (ret != DDI_SUCCESS) {
 #ifdef DEBUG
-		cmn_err(CE_WARN, "tpmrng_generate_random failed");
+		cmn_err(CE_WARN, "!tpmrng_generate_random failed");
 #endif
 		kmem_free(cmdbuf, buflen);
 		tpm_unlock(tpm);
--- a/usr/src/uts/common/sys/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/sys/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -1306,6 +1306,11 @@
 LVMDERIVED_H:
 	cd $(SRC)/uts/common/sys/lvm; pwd; $(MAKE)
 
+clean:
+	$(RM) $(GENHDRS)
+
+clobber:	clean
+
 check:	$(CHECKHDRS)
 
 FRC:
--- a/usr/src/uts/common/sys/fs/zfs.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/sys/fs/zfs.h	Mon Sep 21 11:26:40 2009 -0400
@@ -117,6 +117,8 @@
 	ZFS_PROP_DEFER_DESTROY,
 	ZFS_PROP_USERREFS,
 	ZFS_PROP_LOGBIAS,
+	ZFS_PROP_UNIQUE,		/* not exposed to the user */
+	ZFS_PROP_OBJSETID,		/* not exposed to the user */
 	ZFS_NUM_PROPS
 } zfs_prop_t;
 
--- a/usr/src/uts/common/sys/nxge/nxge_hio.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/sys/nxge/nxge_hio.h	Mon Sep 21 11:26:40 2009 -0400
@@ -99,8 +99,8 @@
 #define	NXGE_VR_SR_MAX		8 /* There are 8 subregions (SR). */
 
 typedef enum {
-	NXGE_HIO_TYPE_SERVICE,	/* We are a service domain driver. */
-	NXGE_HIO_TYPE_GUEST	/* We are a guest domain driver. */
+	NXGE_HIO_TYPE_SERVICE = 0x80,	/* We are a service domain driver. */
+	NXGE_HIO_TYPE_GUEST		/* We are a guest domain driver. */
 } nxge_hio_type_t;
 
 typedef enum {
--- a/usr/src/uts/common/syscall/uadmin.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/syscall/uadmin.c	Mon Sep 21 11:26:40 2009 -0400
@@ -305,7 +305,7 @@
 	case A_CONFIG:
 		switch (fcn) {
 		case AD_UPDATE_BOOT_CONFIG:
-#ifndef	__sparc
+#if !defined(__sparc) && !defined(__s390)
 		{
 			extern void fastboot_update_config(const char *);
 
@@ -376,7 +376,7 @@
 		} else
 			panic_bootstr = mdep;
 
-#ifndef	__sparc
+#if !defined(__sparc) && !defined(__s390)
 		extern void fastboot_update_and_load(int, char *);
 
 		fastboot_update_and_load(fcn, mdep);
--- a/usr/src/uts/common/xen/io/blk_common.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/common/xen/io/blk_common.c	Mon Sep 21 11:26:40 2009 -0400
@@ -558,6 +558,17 @@
 		goto startconnectfail_transaction_start;
 	}
 
+	/* xentop requires the instance in xenstore */
+	e = xenbus_printf(xbt, xsnode, "instance", "%d",
+	    ddi_get_instance(ring->ri_dip));
+	if (e != 0) {
+		cmn_err(CE_WARN, "xdb@%s: failed to write 'instance'",
+		    ddi_get_name_addr(dip));
+		xvdi_fatal_error(dip, e, "writing 'instance'");
+		(void) xenbus_transaction_end(xbt, 1);
+		goto startconnectfail_xenbus_printf;
+	}
+
 	/* If feature-barrier isn't present in xenstore, add it */
 	e = xenbus_read(xbt, xsnode, "feature-barrier", (void **)&barrier,
 	    &len);
--- a/usr/src/uts/i86pc/Makefile.files	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/Makefile.files	Mon Sep 21 11:26:40 2009 -0400
@@ -206,6 +206,8 @@
 TZMON_OBJS	+= tzmon.o
 UPPC_OBJS += uppc.o psm_common.o
 XSVC_OBJS += xsvc.o
+AMD_IOMMU_OBJS +=	amd_iommu.o amd_iommu_impl.o amd_iommu_acpi.o \
+			amd_iommu_cmd.o amd_iommu_log.o amd_iommu_page_tables.o
 
 #
 #	Build up defines and paths.
--- a/usr/src/uts/i86pc/Makefile.i86pc.shared	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/Makefile.i86pc.shared	Mon Sep 21 11:26:40 2009 -0400
@@ -255,11 +255,13 @@
 DRV_KMODS	+= tzmon
 DRV_KMODS	+= acpi_drv 
 DRV_KMODS	+= acpinex
+DRV_KMODS	+= amd_iommu
 DRV_KMODS	+= ioat
 DRV_KMODS	+= fipe
 
 DRV_KMODS	+= cpudrv
 
+
 #
 # Platform Power Modules
 # 
--- a/usr/src/uts/i86pc/Makefile.rules	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/Makefile.rules	Mon Sep 21 11:26:40 2009 -0400
@@ -79,6 +79,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(UTSBASE)/i86pc/io/amd_iommu/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/i86pc/io/ioat/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -295,6 +299,9 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/i86pc/io/acpi/acpinex/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:              $(UTSBASE)/i86pc/io/amd_iommu/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/i86pc/io/ioat/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/amd_iommu/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,83 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#	This Makefile drives production of the amd_iommu driver kernel module.
+#
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE	= ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= amd_iommu
+OBJECTS		= $(AMD_IOMMU_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(AMD_IOMMU_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_PSM_DRV_DIR)/$(MODULE)
+CONF_SRCDIR     = $(UTSBASE)/i86pc/io/amd_iommu
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/i86pc/Makefile.i86pc
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY) $(SRC_CONFILE)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
+
+#
+# depends on misc/iommulib and misc/acpica
+#
+LDFLAGS         += -dy -Nmisc/iommulib -Nmisc/acpica
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS) $(CONF_INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/i86pc/Makefile.targ
--- a/usr/src/uts/i86pc/boot/boot_console.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/boot/boot_console.c	Mon Sep 21 11:26:40 2009 -0400
@@ -510,6 +510,10 @@
 	console_value_t *consolep;
 	size_t len, cons_len;
 	char *cons_str;
+#if !defined(_BOOT)
+	static char console_text[] = "text";
+	extern int post_fastreboot;
+#endif
 
 	boot_line = bootstr;
 	console = CONS_INVALID;
@@ -522,6 +526,11 @@
 	if (cons_str == NULL)
 		cons_str = find_boot_line_prop("output-device");
 
+#if !defined(_BOOT)
+	if (post_fastreboot && strcmp(cons_str, "graphics") == 0)
+		cons_str = console_text;
+#endif
+
 	/*
 	 * Go through the console_devices array trying to match the string
 	 * we were given.  The string on the command line must end with
@@ -646,6 +655,10 @@
 	char *devnames[] = { consoledev, outputdev, inputdev, NULL };
 	console_value_t *consolep;
 	int i;
+	extern int post_fastreboot;
+
+	if (post_fastreboot && console == CONS_SCREEN_GRAPHICS)
+		console = CONS_SCREEN_TEXT;
 
 	if (console != CONS_USBSER && console != CONS_SCREEN_GRAPHICS) {
 		if (console_set) {
--- a/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/cpu/genuineintel/gintel_main.c	Mon Sep 21 11:26:40 2009 -0400
@@ -131,6 +131,23 @@
 	case INTEL_QP_U2:
 	case INTEL_QP_U3:
 	case INTEL_QP_U4:
+	case INTEL_QP_JF:
+	case INTEL_QP_JF0:
+	case INTEL_QP_JF1:
+	case INTEL_QP_JF2:
+	case INTEL_QP_JF3:
+	case INTEL_QP_JF4:
+	case INTEL_QP_JF5:
+	case INTEL_QP_JF6:
+	case INTEL_QP_JF7:
+	case INTEL_QP_JF8:
+	case INTEL_QP_JF9:
+	case INTEL_QP_JFa:
+	case INTEL_QP_JFb:
+	case INTEL_QP_JFc:
+	case INTEL_QP_JFd:
+	case INTEL_QP_JFe:
+	case INTEL_QP_JFf:
 		quickpath = 1;
 		break;
 	default:
--- a/usr/src/uts/i86pc/io/amd_iommu/amd_iommu.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu.c	Mon Sep 21 11:26:40 2009 -0400
@@ -54,6 +54,7 @@
 static int amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp);
 static int amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
     cred_t *credp, int *rvalp);
+static int amd_iommu_quiesce(dev_info_t *dip);
 
 static struct cb_ops amd_iommu_cb_ops = {
 	amd_iommu_open,		/* cb_open */
@@ -87,7 +88,8 @@
 	nodev,			/* devo_reset */
 	&amd_iommu_cb_ops,	/* devo_cb_ops */
 	NULL,			/* devo_bus_ops */
-	nulldev			/* devo_power */
+	nulldev,		/* devo_power */
+	amd_iommu_quiesce,	/* devo_quiesce */
 };
 
 static struct modldrv modldrv = {
@@ -442,3 +444,26 @@
 
 	return (ENOTTY);
 }
+
+static int
+amd_iommu_quiesce(dev_info_t *dip)
+{
+	int instance = ddi_get_instance(dip);
+	struct amd_iommu_state *statep;
+	const char *f = "amd_iommu_quiesce";
+
+	statep = ddi_get_soft_state(amd_iommu_statep, instance);
+	if (statep == NULL) {
+		cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
+		    f, instance);
+		return (DDI_FAILURE);
+	}
+
+	if (amd_iommu_teardown(dip, statep, AMD_IOMMU_QUIESCE) != DDI_SUCCESS) {
+		cmn_err(CE_WARN, "%s: Unable to quiesce AMD IOMMU "
+		    "%s%d", f, ddi_driver_name(dip), instance);
+		return (DDI_FAILURE);
+	}
+
+	return (DDI_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu.conf	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,27 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#
+# To enable IOMMU set this to "yes" and rebuild boot archive
+amd-iommu="yes";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_acpi.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,951 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "amd_iommu_acpi.h"
+#include "amd_iommu_impl.h"
+
+static int create_acpi_hash(amd_iommu_acpi_t *acpi);
+static void amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp);
+
+static void dump_acpi_aliases(void);
+
+
+/*
+ * Globals
+ */
+static amd_iommu_acpi_global_t *amd_iommu_acpi_global;
+static amd_iommu_acpi_ivhd_t **amd_iommu_acpi_ivhd_hash;
+static amd_iommu_acpi_ivmd_t **amd_iommu_acpi_ivmd_hash;
+
+static int
+type_byte_size(char *cp)
+{
+	uint8_t type8 = *((uint8_t *)cp);
+	uint8_t len_bits;
+
+	len_bits = AMD_IOMMU_REG_GET8(&type8, AMD_IOMMU_ACPI_DEVENTRY_LEN);
+
+	switch (len_bits) {
+	case 0:
+			return (4);
+	case 1:
+			return (8);
+	case 2:
+			return (16);
+	case 3:
+			return (32);
+	default:
+			cmn_err(CE_WARN, "%s: Invalid deventry len: %d",
+			    amd_iommu_modname, len_bits);
+			return (len_bits);
+	}
+	/*NOTREACHED*/
+}
+
+static void
+process_4byte_deventry(ivhd_container_t *c, char *cp)
+{
+	int entry_type = *((uint8_t *)cp);
+	ivhd_deventry_t deventry = {0};
+	ivhd_deventry_t *devp;
+	uint8_t datsetting8;
+	align_16_t al = {0};
+	int i;
+
+	/* 4 byte entry */
+	deventry.idev_len = 4;
+	deventry.idev_deviceid = -1;
+	deventry.idev_src_deviceid = -1;
+
+	for (i = 0; i < 2; i++) {
+		al.ent8[i] = *((uint8_t *)&cp[i + 1]);
+	}
+
+	switch (entry_type) {
+	case 1:
+		deventry.idev_type = DEVENTRY_ALL;
+		break;
+	case 2:
+		deventry.idev_type = DEVENTRY_SELECT;
+		deventry.idev_deviceid = al.ent16;
+		break;
+	case 3:
+		deventry.idev_type = DEVENTRY_RANGE;
+		deventry.idev_deviceid = al.ent16;
+		break;
+	case 4:
+		deventry.idev_type = DEVENTRY_RANGE_END;
+		deventry.idev_deviceid = al.ent16;
+		ASSERT(cp[3] == 0);
+		break;
+	case 0:
+		ASSERT(al.ent16 == 0);
+		ASSERT(cp[3] == 0);
+	default:
+		return;
+	}
+
+
+	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
+	*devp = deventry;
+
+	if (c->ivhdc_first_deventry == NULL)
+		c->ivhdc_first_deventry =  devp;
+	else
+		c->ivhdc_last_deventry->idev_next = devp;
+
+	c->ivhdc_last_deventry = devp;
+
+	if (entry_type == 4)
+		return;
+
+	datsetting8 = (*((uint8_t *)&cp[3]));
+
+	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_LINT1PASS);
+
+	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_LINT0PASS);
+
+	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_SYSMGT);
+
+	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_DATRSV) == 0);
+
+	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_NMIPASS);
+
+	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_EXTINTPASS);
+
+	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_INITPASS);
+}
+
+static void
+process_8byte_deventry(ivhd_container_t *c, char *cp)
+{
+	uint8_t datsetting8;
+	int entry_type = (uint8_t)*cp;
+	ivhd_deventry_t deventry = {0};
+	ivhd_deventry_t *devp;
+	align_16_t al1 = {0};
+	align_16_t al2 = {0};
+	align_32_t al3 = {0};
+	int i;
+
+	/* Length is 8 bytes */
+	deventry.idev_len = 8;
+	deventry.idev_deviceid = -1;
+	deventry.idev_src_deviceid = -1;
+
+	for (i = 0; i < 2; i++) {
+		al1.ent8[i] = *((uint8_t *)&cp[i+1]);
+		al2.ent8[i] = *((uint8_t *)&cp[i+5]);
+	}
+
+	datsetting8 = *((uint8_t *)&cp[3]);
+
+	switch (entry_type) {
+	case 66:
+		deventry.idev_type = DEVENTRY_ALIAS_SELECT;
+		deventry.idev_deviceid = al1.ent16;
+		deventry.idev_src_deviceid = al2.ent16;
+		ASSERT(cp[4] == 0);
+		ASSERT(cp[7] == 0);
+		break;
+	case 67:
+		deventry.idev_type = DEVENTRY_ALIAS_RANGE;
+		deventry.idev_deviceid = al1.ent16;
+		deventry.idev_src_deviceid = al2.ent16;
+		ASSERT(cp[4] == 0);
+		ASSERT(cp[7] == 0);
+		break;
+	case 70:
+		deventry.idev_type = DEVENTRY_EXTENDED_SELECT;
+		deventry.idev_deviceid = al1.ent16;
+		break;
+	case 71:
+		deventry.idev_type = DEVENTRY_EXTENDED_RANGE;
+		deventry.idev_deviceid = al1.ent16;
+		break;
+	case 72:
+		deventry.idev_type = DEVENTRY_SPECIAL_DEVICE;
+		ASSERT(al1.ent16 == 0);
+		deventry.idev_deviceid = -1;
+		deventry.idev_handle = cp[4];
+		deventry.idev_variety = cp[7];
+		deventry.idev_src_deviceid = al2.ent16;
+	default:
+#ifdef BROKEN_ASSERT
+		for (i = 0; i < 7; i++) {
+			ASSERT(cp[i] == 0);
+		}
+#endif
+		return;
+	}
+
+
+	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
+	*devp = deventry;
+
+	if (c->ivhdc_first_deventry == NULL)
+		c->ivhdc_first_deventry =  devp;
+	else
+		c->ivhdc_last_deventry->idev_next = devp;
+
+	c->ivhdc_last_deventry = devp;
+
+	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_LINT1PASS);
+
+	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_LINT0PASS);
+
+	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_SYSMGT);
+
+	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_DATRSV) == 0);
+
+	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_NMIPASS);
+
+	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_EXTINTPASS);
+
+	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
+	    AMD_IOMMU_ACPI_INITPASS);
+
+	if (entry_type != 70 && entry_type != 71) {
+		return;
+	}
+
+	/* Type 70 and 71 */
+	for (i = 0; i < 4; i++) {
+		al3.ent8[i] = *((uint8_t *)&cp[i+4]);
+	}
+
+	devp->idev_AtsDisabled = AMD_IOMMU_REG_GET8(&al3.ent32,
+	    AMD_IOMMU_ACPI_ATSDISABLED);
+
+	ASSERT(AMD_IOMMU_REG_GET8(&al3.ent32, AMD_IOMMU_ACPI_EXTDATRSV) == 0);
+}
+
+static void
+process_ivhd(amd_iommu_acpi_t *acpi, ivhd_t *ivhdp)
+{
+	ivhd_container_t *c;
+	caddr_t ivhd_end;
+	caddr_t ivhd_tot_end;
+	caddr_t cp;
+
+	ASSERT(ivhdp->ivhd_type == 0x10);
+
+	c = kmem_zalloc(sizeof (ivhd_container_t), KM_SLEEP);
+	c->ivhdc_ivhd = kmem_alloc(sizeof (ivhd_t), KM_SLEEP);
+	*(c->ivhdc_ivhd) = *ivhdp;
+
+	if (acpi->acp_first_ivhdc == NULL)
+		acpi->acp_first_ivhdc = c;
+	else
+		acpi->acp_last_ivhdc->ivhdc_next = c;
+
+	acpi->acp_last_ivhdc = c;
+
+	ivhd_end = (caddr_t)ivhdp + sizeof (ivhd_t);
+	ivhd_tot_end = (caddr_t)ivhdp + ivhdp->ivhd_len;
+
+	for (cp = ivhd_end; cp < ivhd_tot_end; cp += type_byte_size(cp)) {
+		/* 16 byte and 32 byte size are currently reserved */
+		switch (type_byte_size(cp)) {
+		case 4:
+			process_4byte_deventry(c, cp);
+			break;
+		case 8:
+			process_8byte_deventry(c, cp);
+			break;
+		case 16:
+		case 32:
+			/* Reserved */
+			break;
+		default:
+			cmn_err(CE_WARN, "%s: unsupported length for device "
+			    "entry in ACPI IVRS table's IVHD entry",
+			    amd_iommu_modname);
+			break;
+		}
+	}
+}
+
+static void
+process_ivmd(amd_iommu_acpi_t *acpi, ivmd_t *ivmdp)
+{
+	ivmd_container_t *c;
+
+	ASSERT(ivmdp->ivmd_type != 0x10);
+
+	c = kmem_zalloc(sizeof (ivmd_container_t), KM_SLEEP);
+	c->ivmdc_ivmd = kmem_alloc(sizeof (ivmd_t), KM_SLEEP);
+	*(c->ivmdc_ivmd) = *ivmdp;
+
+	if (acpi->acp_first_ivmdc == NULL)
+		acpi->acp_first_ivmdc = c;
+	else
+		acpi->acp_last_ivmdc->ivmdc_next = c;
+
+	acpi->acp_last_ivmdc = c;
+}
+
+int
+amd_iommu_acpi_init(void)
+{
+	ivrs_t *ivrsp;
+	caddr_t ivrsp_end;
+	caddr_t table_end;
+	caddr_t cp;
+	uint8_t type8;
+	amd_iommu_acpi_t *acpi;
+	align_ivhd_t al_vhd = {0};
+	align_ivmd_t al_vmd = {0};
+
+	if (AcpiGetTable(IVRS_SIG, 1, (ACPI_TABLE_HEADER **)&ivrsp) != AE_OK) {
+		cmn_err(CE_NOTE, "!amd_iommu: No AMD IOMMU ACPI IVRS table");
+		return (DDI_FAILURE);
+	}
+
+	/*
+	 * Reserved field must be 0
+	 */
+	ASSERT(ivrsp->ivrs_resv == 0);
+
+	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
+	    AMD_IOMMU_ACPI_IVINFO_RSV1) == 0);
+	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
+	    AMD_IOMMU_ACPI_IVINFO_RSV2) == 0);
+
+	ivrsp_end = (caddr_t)ivrsp + sizeof (struct ivrs);
+	table_end = (caddr_t)ivrsp + ivrsp->ivrs_hdr.Length;
+
+	acpi = kmem_zalloc(sizeof (amd_iommu_acpi_t), KM_SLEEP);
+	acpi->acp_ivrs = kmem_alloc(sizeof (ivrs_t), KM_SLEEP);
+	*(acpi->acp_ivrs) = *ivrsp;
+
+	for (cp = ivrsp_end; cp < table_end; cp += (al_vhd.ivhdp)->ivhd_len) {
+		al_vhd.cp = cp;
+		if (al_vhd.ivhdp->ivhd_type == 0x10)
+			process_ivhd(acpi, al_vhd.ivhdp);
+	}
+
+	for (cp = ivrsp_end; cp < table_end; cp += (al_vmd.ivmdp)->ivmd_len) {
+		al_vmd.cp = cp;
+		type8 = al_vmd.ivmdp->ivmd_type;
+		if (type8 == 0x20 || type8 == 0x21 || type8 == 0x22)
+			process_ivmd(acpi, al_vmd.ivmdp);
+	}
+
+	if (create_acpi_hash(acpi) != DDI_SUCCESS) {
+		return (DDI_FAILURE);
+	}
+
+	amd_iommu_acpi_table_fini(&acpi);
+
+	ASSERT(acpi == NULL);
+
+	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
+		dump_acpi_aliases();
+		debug_enter("dump");
+	}
+
+	return (DDI_SUCCESS);
+}
+
+static ivhd_deventry_t *
+free_ivhd_deventry(ivhd_deventry_t *devp)
+{
+	ivhd_deventry_t *next = devp->idev_next;
+
+	kmem_free(devp, sizeof (ivhd_deventry_t));
+
+	return (next);
+}
+
+static ivhd_container_t *
+free_ivhd_container(ivhd_container_t *ivhdcp)
+{
+	ivhd_container_t *next = ivhdcp->ivhdc_next;
+	ivhd_deventry_t *devp;
+
+	for (devp = ivhdcp->ivhdc_first_deventry; devp; ) {
+		devp = free_ivhd_deventry(devp);
+	}
+
+	kmem_free(ivhdcp->ivhdc_ivhd, sizeof (ivhd_t));
+	kmem_free(ivhdcp, sizeof (ivhd_container_t));
+
+	return (next);
+}
+
+static ivmd_container_t *
+free_ivmd_container(ivmd_container_t *ivmdcp)
+{
+	ivmd_container_t *next = ivmdcp->ivmdc_next;
+
+	kmem_free(ivmdcp->ivmdc_ivmd, sizeof (ivmd_t));
+	kmem_free(ivmdcp, sizeof (ivmd_container_t));
+
+	return (next);
+}
+
+void
+amd_iommu_acpi_fini(void)
+{
+}
+
+/*
+ * TODO: Do we need to free the ACPI table for om GetFirmwareTable()
+ */
+static void
+amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp)
+{
+	amd_iommu_acpi_t *acpi = *acpipp;
+	ivhd_container_t *ivhdcp;
+	ivmd_container_t *ivmdcp;
+
+	ASSERT(acpi);
+
+	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp; ) {
+		ivhdcp = free_ivhd_container(ivhdcp);
+	}
+	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp; ) {
+		ivmdcp = free_ivmd_container(ivmdcp);
+	}
+
+	kmem_free(acpi->acp_ivrs, sizeof (struct ivrs));
+	kmem_free(acpi, sizeof (amd_iommu_acpi_t));
+
+	*acpipp = NULL;
+}
+
+static uint16_t
+deviceid_hashfn(uint16_t deviceid)
+{
+	return (deviceid % AMD_IOMMU_ACPI_INFO_HASH_SZ);
+}
+
+static void
+add_deventry_info(ivhd_t *ivhdp, ivhd_deventry_t *deventry,
+    amd_iommu_acpi_ivhd_t **hash)
+{
+	static amd_iommu_acpi_ivhd_t *last;
+	amd_iommu_acpi_ivhd_t *acpi_ivhdp;
+	uint8_t uint8_flags;
+	uint16_t uint16_info;
+	uint16_t idx;
+
+	if (deventry->idev_type == DEVENTRY_RANGE_END) {
+		ASSERT(last);
+		acpi_ivhdp = last;
+		last = NULL;
+		ASSERT(acpi_ivhdp->ach_dev_type == DEVENTRY_RANGE ||
+		    acpi_ivhdp->ach_dev_type == DEVENTRY_ALIAS_RANGE ||
+		    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE);
+		ASSERT(acpi_ivhdp->ach_deviceid_end == -1);
+		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
+		/* TODO ASSERT data is 0 */
+		return;
+	}
+
+	ASSERT(last == NULL);
+	acpi_ivhdp = kmem_zalloc(sizeof (*acpi_ivhdp), KM_SLEEP);
+
+	uint8_flags = ivhdp->ivhd_flags;
+
+#ifdef BROKEN_ASSERT
+	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_RSV) == 0);
+#endif
+
+	acpi_ivhdp->ach_IotlbSup = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP);
+	acpi_ivhdp->ach_Isoc = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC);
+	acpi_ivhdp->ach_ResPassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW);
+	acpi_ivhdp->ach_PassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW);
+	acpi_ivhdp->ach_HtTunEn = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN);
+
+	/* IVHD fields */
+	acpi_ivhdp->ach_IOMMU_deviceid = ivhdp->ivhd_deviceid;
+	acpi_ivhdp->ach_IOMMU_cap_off = ivhdp->ivhd_cap_off;
+	acpi_ivhdp->ach_IOMMU_reg_base = ivhdp->ivhd_reg_base;
+	acpi_ivhdp->ach_IOMMU_pci_seg = ivhdp->ivhd_pci_seg;
+
+	/* IVHD IOMMU info fields */
+	uint16_info = ivhdp->ivhd_iommu_info;
+
+#ifdef BROKEN_ASSERT
+	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
+	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV1) == 0);
+#endif
+
+	acpi_ivhdp->ach_IOMMU_UnitID = AMD_IOMMU_REG_GET16(&uint16_info,
+	    AMD_IOMMU_ACPI_IOMMU_INFO_UNITID);
+	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
+	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV2) == 0);
+	acpi_ivhdp->ach_IOMMU_MSInum = AMD_IOMMU_REG_GET16(&uint16_info,
+	    AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM);
+
+	/* Initialize  deviceids to -1 */
+	acpi_ivhdp->ach_deviceid_start = -1;
+	acpi_ivhdp->ach_deviceid_end = -1;
+	acpi_ivhdp->ach_src_deviceid = -1;
+
+	/* All range type entries are put on hash entry 0 */
+	switch (deventry->idev_type) {
+	case DEVENTRY_ALL:
+		acpi_ivhdp->ach_deviceid_start = 0;
+		acpi_ivhdp->ach_deviceid_end = (uint16_t)-1;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_ALL;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		break;
+	case DEVENTRY_SELECT:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_SELECT;
+		idx = deviceid_hashfn(deventry->idev_deviceid);
+		break;
+	case DEVENTRY_RANGE:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = -1;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_RANGE;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		last = acpi_ivhdp;
+		break;
+	case DEVENTRY_RANGE_END:
+		cmn_err(CE_PANIC, "%s: Unexpected Range End Deventry",
+		    amd_iommu_modname);
+		/*NOTREACHED*/
+	case DEVENTRY_ALIAS_SELECT:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
+		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_SELECT;
+		idx = deviceid_hashfn(deventry->idev_deviceid);
+		break;
+	case DEVENTRY_ALIAS_RANGE:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = -1;
+		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_RANGE;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		last = acpi_ivhdp;
+		break;
+	case DEVENTRY_EXTENDED_SELECT:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_SELECT;
+		idx = deviceid_hashfn(deventry->idev_deviceid);
+		break;
+	case DEVENTRY_EXTENDED_RANGE:
+		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
+		acpi_ivhdp->ach_deviceid_end = -1;
+		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_RANGE;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		last = acpi_ivhdp;
+		break;
+	case DEVENTRY_SPECIAL_DEVICE:
+		acpi_ivhdp->ach_deviceid_start = -1;
+		acpi_ivhdp->ach_deviceid_end = -1;
+		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
+		acpi_ivhdp->ach_special_handle = deventry->idev_handle;
+		acpi_ivhdp->ach_special_variety = deventry->idev_variety;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+	default:
+		cmn_err(CE_PANIC, "%s: Unsupported deventry type",
+		    amd_iommu_modname);
+		/*NOTREACHED*/
+	}
+
+	acpi_ivhdp->ach_Lint1Pass = deventry->idev_Lint1Pass;
+	acpi_ivhdp->ach_Lint0Pass = deventry->idev_Lint0Pass;
+	acpi_ivhdp->ach_SysMgt = deventry->idev_SysMgt;
+	acpi_ivhdp->ach_NMIPass = deventry->idev_NMIPass;
+	acpi_ivhdp->ach_ExtIntPass = deventry->idev_ExtIntPass;
+	acpi_ivhdp->ach_INITPass = deventry->idev_INITPass;
+
+
+	/* extended data */
+	if (acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_SELECT ||
+	    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE) {
+		acpi_ivhdp->ach_AtsDisabled = deventry->idev_AtsDisabled;
+	}
+
+	/*
+	 * Now add it to the hash
+	 */
+	ASSERT(hash[idx] != acpi_ivhdp);
+	acpi_ivhdp->ach_next = hash[idx];
+	hash[idx] = acpi_ivhdp;
+}
+
+static void
+add_ivhdc_info(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
+{
+	ivhd_deventry_t *deventry;
+	ivhd_t *ivhdp = ivhdcp->ivhdc_ivhd;
+
+	for (deventry = ivhdcp->ivhdc_first_deventry; deventry;
+	    deventry = deventry->idev_next) {
+		add_deventry_info(ivhdp, deventry, hash);
+	}
+}
+
+static void
+add_ivhd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivhd_t **hash)
+{
+	ivhd_container_t *ivhdcp;
+
+	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp;
+	    ivhdcp = ivhdcp->ivhdc_next) {
+		add_ivhdc_info(ivhdcp, hash);
+	}
+}
+
+static void
+set_ivmd_info(ivmd_t *ivmdp, amd_iommu_acpi_ivmd_t **hash)
+{
+	amd_iommu_acpi_ivmd_t *acpi_ivmdp;
+	uint8_t uint8_flags;
+	uint16_t idx;
+
+	uint8_flags = ivmdp->ivmd_flags;
+
+	acpi_ivmdp = kmem_zalloc(sizeof (*acpi_ivmdp), KM_SLEEP);
+
+	switch (ivmdp->ivmd_type) {
+	case 0x20:
+		acpi_ivmdp->acm_deviceid_start = 0;
+		acpi_ivmdp->acm_deviceid_end = (uint16_t)-1;
+		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_ALL;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		break;
+	case 0x21:
+		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
+		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_deviceid;
+		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_SELECT;
+		idx = deviceid_hashfn(ivmdp->ivmd_deviceid);
+		break;
+	case 0x22:
+		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
+		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_auxdata;
+		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_RANGE;
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		break;
+	default:
+		cmn_err(CE_PANIC, "Unknown AMD IOMMU ACPI IVMD deviceid type: "
+		    "%x", ivmdp->ivmd_type);
+		/*NOTREACHED*/
+	}
+
+	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVMD_RSV) == 0);
+
+	acpi_ivmdp->acm_ExclRange = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVMD_EXCL_RANGE);
+	acpi_ivmdp->acm_IW = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVMD_IW);
+	acpi_ivmdp->acm_IR = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVMD_IR);
+	acpi_ivmdp->acm_Unity = AMD_IOMMU_REG_GET8(&uint8_flags,
+	    AMD_IOMMU_ACPI_IVMD_UNITY);
+
+	acpi_ivmdp->acm_ivmd_phys_start = ivmdp->ivmd_phys_start;
+	acpi_ivmdp->acm_ivmd_phys_len = ivmdp->ivmd_phys_len;
+
+	acpi_ivmdp->acm_next = hash[idx];
+	hash[idx] = acpi_ivmdp;
+}
+
+static void
+add_ivmdc_info(ivmd_container_t *ivmdcp, amd_iommu_acpi_ivmd_t **hash)
+{
+	set_ivmd_info(ivmdcp->ivmdc_ivmd, hash);
+}
+
+static void
+add_ivmd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivmd_t **hash)
+{
+	ivmd_container_t *ivmdcp;
+
+	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp;
+	    ivmdcp = ivmdcp->ivmdc_next) {
+		add_ivmdc_info(ivmdcp, hash);
+	}
+}
+
+static void
+add_global_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_global_t *global)
+{
+	uint32_t ivrs_ivinfo = acpi->acp_ivrs->ivrs_ivinfo;
+
+	global->acg_HtAtsResv =
+	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_HT_ATSRSV);
+	global->acg_VAsize =
+	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_VA_SIZE);
+	global->acg_PAsize =
+	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_PA_SIZE);
+}
+
+static int
+create_acpi_hash(amd_iommu_acpi_t *acpi)
+{
+	/* Last hash entry is for deviceid ranges including "all" */
+
+	amd_iommu_acpi_global = kmem_zalloc(sizeof (amd_iommu_acpi_global_t),
+	    KM_SLEEP);
+
+	amd_iommu_acpi_ivhd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivhd_t *)
+	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
+
+	amd_iommu_acpi_ivmd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivmd_t *)
+	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
+
+	add_global_info(acpi, amd_iommu_acpi_global);
+
+	add_ivhd_info(acpi, amd_iommu_acpi_ivhd_hash);
+
+	add_ivmd_info(acpi, amd_iommu_acpi_ivmd_hash);
+
+	return (DDI_SUCCESS);
+}
+
+amd_iommu_acpi_global_t *
+amd_iommu_lookup_acpi_global(void)
+{
+	ASSERT(amd_iommu_acpi_global);
+
+	return (amd_iommu_acpi_global);
+}
+
+amd_iommu_acpi_ivhd_t *
+amd_iommu_lookup_all_ivhd(void)
+{
+	amd_iommu_acpi_ivhd_t *hinfop;
+
+	hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
+	for (; hinfop; hinfop = hinfop->ach_next) {
+		if (hinfop->ach_deviceid_start == 0 &&
+		    hinfop->ach_deviceid_end == (uint16_t)-1) {
+			break;
+		}
+	}
+
+	return (hinfop);
+}
+
+amd_iommu_acpi_ivmd_t *
+amd_iommu_lookup_all_ivmd(void)
+{
+	amd_iommu_acpi_ivmd_t *minfop;
+
+	minfop = amd_iommu_acpi_ivmd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
+	for (; minfop; minfop = minfop->acm_next) {
+		if (minfop->acm_deviceid_start == 0 &&
+		    minfop->acm_deviceid_end == (uint16_t)-1) {
+			break;
+		}
+	}
+
+	return (minfop);
+}
+
+amd_iommu_acpi_ivhd_t *
+amd_iommu_lookup_any_ivhd(void)
+{
+	int i;
+	amd_iommu_acpi_ivhd_t *hinfop;
+
+	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
+		/*LINTED*/
+		if (hinfop = amd_iommu_acpi_ivhd_hash[i])
+			break;
+	}
+
+	return (hinfop);
+}
+
+amd_iommu_acpi_ivmd_t *
+amd_iommu_lookup_any_ivmd(void)
+{
+	int i;
+	amd_iommu_acpi_ivmd_t *minfop;
+
+	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
+		/*LINTED*/
+		if (minfop = amd_iommu_acpi_ivmd_hash[i])
+			break;
+	}
+
+	return (minfop);
+}
+
+static void
+dump_acpi_aliases(void)
+{
+	amd_iommu_acpi_ivhd_t *hinfop;
+	uint16_t idx;
+
+	for (idx = 0; idx <= AMD_IOMMU_ACPI_INFO_HASH_SZ; idx++) {
+		hinfop = amd_iommu_acpi_ivhd_hash[idx];
+		for (; hinfop; hinfop = hinfop->ach_next) {
+			cmn_err(CE_NOTE, "start=%d, end=%d, src_bdf=%d",
+			    hinfop->ach_deviceid_start,
+			    hinfop->ach_deviceid_end,
+			    hinfop->ach_src_deviceid);
+		}
+	}
+}
+
+amd_iommu_acpi_ivhd_t *
+amd_iommu_lookup_ivhd(int32_t deviceid)
+{
+	amd_iommu_acpi_ivhd_t *hinfop;
+	uint16_t idx;
+
+	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+		cmn_err(CE_NOTE, "Attempting to get ACPI IVHD info "
+		    "for deviceid: %d", deviceid);
+	}
+
+	ASSERT(amd_iommu_acpi_ivhd_hash);
+
+	/* check if special device */
+	if (deviceid == -1) {
+		hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
+		for (; hinfop; hinfop = hinfop->ach_next) {
+			if (hinfop->ach_deviceid_start  == -1 &&
+			    hinfop->ach_deviceid_end == -1) {
+				break;
+			}
+		}
+		return (hinfop);
+	}
+
+	/* First search for an exact match */
+
+	idx = deviceid_hashfn(deviceid);
+
+
+range:
+	hinfop = amd_iommu_acpi_ivhd_hash[idx];
+
+	for (; hinfop; hinfop = hinfop->ach_next) {
+		if (deviceid < hinfop->ach_deviceid_start ||
+		    deviceid > hinfop->ach_deviceid_end)
+			continue;
+
+		if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+			cmn_err(CE_NOTE, "Found ACPI IVHD match: %p, "
+			    "actual deviceid = %u, start = %u, end = %u",
+			    (void *)hinfop, deviceid,
+			    hinfop->ach_deviceid_start,
+			    hinfop->ach_deviceid_end);
+		}
+		goto out;
+	}
+
+	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		goto range;
+	} else {
+		cmn_err(CE_PANIC, "IVHD not found for deviceid: %x", deviceid);
+	}
+
+out:
+	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+		cmn_err(CE_NOTE, "%u: %s ACPI IVHD %p", deviceid,
+		    hinfop ? "GOT" : "Did NOT get", (void *)hinfop);
+	}
+
+	return (hinfop);
+}
+
+amd_iommu_acpi_ivmd_t *
+amd_iommu_lookup_ivmd(int32_t deviceid)
+{
+	amd_iommu_acpi_ivmd_t *minfop;
+	uint16_t idx;
+
+	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+		cmn_err(CE_NOTE, "Attempting to get ACPI IVMD info "
+		    "for deviceid: %u", deviceid);
+	}
+
+	ASSERT(amd_iommu_acpi_ivmd_hash);
+
+	/* First search for an exact match */
+
+	idx = deviceid_hashfn(deviceid);
+
+
+range:
+	minfop = amd_iommu_acpi_ivmd_hash[idx];
+
+	for (; minfop; minfop = minfop->acm_next) {
+		if (deviceid < minfop->acm_deviceid_start &&
+		    deviceid > minfop->acm_deviceid_end)
+			continue;
+
+		if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+			cmn_err(CE_NOTE, "Found ACPI IVMD match: %p, "
+			    "actual deviceid = %u, start = %u, end = %u",
+			    (void *)minfop, deviceid,
+			    minfop->acm_deviceid_start,
+			    minfop->acm_deviceid_end);
+		}
+
+		goto out;
+	}
+
+	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
+		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
+		goto range;
+	} else {
+		cmn_err(CE_PANIC, "IVMD not found for deviceid: %x", deviceid);
+	}
+
+out:
+	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
+		cmn_err(CE_NOTE, "%u: %s ACPI IVMD info %p", deviceid,
+		    minfop ? "GOT" : "Did NOT get", (void *)minfop);
+	}
+
+	return (minfop);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_acpi.h	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,306 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD_IOMMU_ACPI_H
+#define	_AMD_IOMMU_ACPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/sunddi.h>
+#include <sys/acpi/acpi.h>
+#include <sys/acpica.h>
+#include <sys/amd_iommu.h>
+#include "amd_iommu_impl.h"
+
+#ifdef _KERNEL
+
+#define	IVRS_SIG	"IVRS"
+
+/*
+ * IVINFO settings
+ */
+#define	AMD_IOMMU_ACPI_IVINFO_RSV1	(31 << 16 | 23)
+#define	AMD_IOMMU_ACPI_HT_ATSRSV	(22 << 16 | 22)
+#define	AMD_IOMMU_ACPI_VA_SIZE		(21 << 16 | 15)
+#define	AMD_IOMMU_ACPI_PA_SIZE		(14 << 16 | 8)
+#define	AMD_IOMMU_ACPI_IVINFO_RSV2	(7 << 16 | 0)
+
+/*
+ * IVHD Device entry len field
+ */
+#define	AMD_IOMMU_ACPI_DEVENTRY_LEN	(7 << 16 | 6)
+
+/*
+ * IVHD flag fields definition
+ */
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_RSV		(7 << 16 | 5)
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP	(4 << 16 | 4)
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC		(3 << 16 | 3)
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW	(2 << 16 | 2)
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW	(1 << 16 | 1)
+#define	AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN	(0 << 16 | 0)
+
+/*
+ * IVHD IOMMU info fields
+ */
+#define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV1		(15 << 16 | 13)
+#define	AMD_IOMMU_ACPI_IOMMU_INFO_UNITID	(12 << 16 | 8)
+#define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV2		(7 << 16 | 5)
+#define	AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM	(4 << 16 | 0)
+
+/*
+ * IVHD deventry data settings
+ */
+#define	AMD_IOMMU_ACPI_LINT1PASS	(7 << 16 | 7)
+#define	AMD_IOMMU_ACPI_LINT0PASS	(6 << 16 | 6)
+#define	AMD_IOMMU_ACPI_SYSMGT		(5 << 16 | 4)
+#define	AMD_IOMMU_ACPI_DATRSV		(3 << 16 | 3)
+#define	AMD_IOMMU_ACPI_NMIPASS		(2 << 16 | 2)
+#define	AMD_IOMMU_ACPI_EXTINTPASS	(1 << 16 | 1)
+#define	AMD_IOMMU_ACPI_INITPASS		(0 << 16 | 0)
+
+/*
+ * IVHD deventry extended data settings
+ */
+#define	AMD_IOMMU_ACPI_ATSDISABLED	(31 << 16 | 31)
+#define	AMD_IOMMU_ACPI_EXTDATRSV	(30 << 16 | 0)
+
+/*
+ * IVMD flags fields settings
+ */
+#define	AMD_IOMMU_ACPI_IVMD_RSV		(7 << 16 | 4)
+#define	AMD_IOMMU_ACPI_IVMD_EXCL_RANGE	(3 << 16 | 3)
+#define	AMD_IOMMU_ACPI_IVMD_IW		(2 << 16 | 2)
+#define	AMD_IOMMU_ACPI_IVMD_IR		(1 << 16 | 1)
+#define	AMD_IOMMU_ACPI_IVMD_UNITY	(0 << 16 | 0)
+
+#define	AMD_IOMMU_ACPI_INFO_HASH_SZ	(256)
+
+/*
+ * Deventry special device "variety"
+ */
+#define	AMD_IOMMU_ACPI_SPECIAL_APIC	0x1
+#define	AMD_IOMMU_ACPI_SPECIAL_HPET	0x2
+
+typedef enum {
+	DEVENTRY_INVALID = 0,
+	DEVENTRY_ALL = 1,
+	DEVENTRY_SELECT,
+	DEVENTRY_RANGE,
+	DEVENTRY_RANGE_END,
+	DEVENTRY_ALIAS_SELECT,
+	DEVENTRY_ALIAS_RANGE,
+	DEVENTRY_EXTENDED_SELECT,
+	DEVENTRY_EXTENDED_RANGE,
+	DEVENTRY_SPECIAL_DEVICE
+} ivhd_deventry_type_t;
+
+typedef enum {
+	IVMD_DEVICE_INVALID = 0,
+	IVMD_DEVICEID_ALL,
+	IVMD_DEVICEID_SELECT,
+	IVMD_DEVICEID_RANGE
+} ivmd_deviceid_type_t;
+
+typedef struct ivhd_deventry {
+	uint8_t idev_len;
+	ivhd_deventry_type_t  idev_type;
+	int32_t idev_deviceid;
+	int32_t idev_src_deviceid;
+	uint8_t idev_handle;
+	uint8_t idev_variety;
+	uint8_t idev_Lint1Pass;
+	uint8_t idev_Lint0Pass;
+	uint8_t idev_SysMgt;
+	uint8_t idev_NMIPass;
+	uint8_t idev_ExtIntPass;
+	uint8_t idev_INITPass;
+	uint8_t idev_AtsDisabled;
+	struct ivhd_deventry *idev_next;
+} ivhd_deventry_t;
+
+typedef struct ivhd {
+	uint8_t ivhd_type;
+	uint8_t ivhd_flags;
+	uint16_t ivhd_len;
+	uint16_t ivhd_deviceid;
+	uint16_t ivhd_cap_off;
+	uint64_t ivhd_reg_base;
+	uint16_t ivhd_pci_seg;
+	uint16_t ivhd_iommu_info;
+	uint32_t ivhd_resv;
+} ivhd_t;
+
+typedef struct ivhd_container {
+	ivhd_t *ivhdc_ivhd;
+	ivhd_deventry_t *ivhdc_first_deventry;
+	ivhd_deventry_t *ivhdc_last_deventry;
+	struct ivhd_container *ivhdc_next;
+} ivhd_container_t;
+
+typedef struct ivmd {
+	uint8_t ivmd_type;
+	uint8_t ivmd_flags;
+	uint16_t ivmd_len;
+	uint16_t ivmd_deviceid;
+	uint16_t ivmd_auxdata;
+	uint64_t ivmd_resv;
+	uint64_t ivmd_phys_start;
+	uint64_t ivmd_phys_len;
+} ivmd_t;
+
+typedef struct ivmd_container {
+	ivmd_t *ivmdc_ivmd;
+	struct ivmd_container *ivmdc_next;
+} ivmd_container_t;
+
+typedef struct ivrs {
+	struct acpi_table_header ivrs_hdr;
+	uint32_t ivrs_ivinfo;
+	uint64_t ivrs_resv;
+} ivrs_t;
+
+typedef struct amd_iommu_acpi {
+	struct ivrs *acp_ivrs;
+	ivhd_container_t *acp_first_ivhdc;
+	ivhd_container_t *acp_last_ivhdc;
+	ivmd_container_t *acp_first_ivmdc;
+	ivmd_container_t *acp_last_ivmdc;
+} amd_iommu_acpi_t;
+
+
+/* Global IVINFo fields */
+typedef struct amd_iommu_acpi_global {
+	uint8_t acg_HtAtsResv;
+	uint8_t acg_VAsize;
+	uint8_t acg_PAsize;
+} amd_iommu_acpi_global_t;
+
+typedef struct amd_iommu_acpi_ivhd {
+	int32_t ach_deviceid_start;
+	int32_t ach_deviceid_end;
+
+	/* IVHD deventry type */
+	ivhd_deventry_type_t ach_dev_type;
+
+	/* IVHD flag fields */
+	uint8_t ach_IotlbSup;
+	uint8_t ach_Isoc;
+	uint8_t ach_ResPassPW;
+	uint8_t ach_PassPW;
+	uint8_t ach_HtTunEn;
+
+	/* IVHD fields */
+	uint16_t ach_IOMMU_deviceid;
+	uint16_t ach_IOMMU_cap_off;
+	uint64_t ach_IOMMU_reg_base;
+	uint16_t ach_IOMMU_pci_seg;
+
+	/* IVHD IOMMU info fields */
+	uint8_t ach_IOMMU_UnitID;
+	uint8_t ach_IOMMU_MSInum;
+
+	/* IVHD deventry data settings */
+	uint8_t ach_Lint1Pass;
+	uint8_t ach_Lint0Pass;
+	uint8_t ach_SysMgt;
+	uint8_t ach_NMIPass;
+	uint8_t ach_ExtIntPass;
+	uint8_t ach_INITPass;
+
+	/* alias */
+	int32_t ach_src_deviceid;
+
+	/* IVHD deventry extended data settings */
+	uint8_t ach_AtsDisabled;
+
+	/* IVHD deventry special device */
+	uint8_t ach_special_handle;
+	uint8_t ach_special_variety;
+
+	struct amd_iommu_acpi_ivhd *ach_next;
+} amd_iommu_acpi_ivhd_t;
+
+typedef struct amd_iommu_acpi_ivmd {
+	int32_t acm_deviceid_start;
+	int32_t acm_deviceid_end;
+
+	/* IVMD type */
+	ivmd_deviceid_type_t acm_dev_type;
+
+	/* IVMD flags */
+	uint8_t acm_ExclRange;
+	uint8_t acm_IW;
+	uint8_t acm_IR;
+	uint8_t acm_Unity;
+
+	/* IVMD mem block */
+	uint64_t acm_ivmd_phys_start;
+	uint64_t acm_ivmd_phys_len;
+
+	struct amd_iommu_acpi_ivmd *acm_next;
+} amd_iommu_acpi_ivmd_t;
+
+typedef union {
+	uint16_t   ent16;
+	uint8_t	   ent8[2];
+} align_16_t;
+
+typedef union {
+	uint32_t   ent32;
+	uint8_t	   ent8[4];
+} align_32_t;
+
+typedef union {
+	ivhd_t *ivhdp;
+	char   *cp;
+} align_ivhd_t;
+
+typedef union {
+	ivmd_t *ivmdp;
+	char   *cp;
+} align_ivmd_t;
+
+#pragma pack()
+
+int amd_iommu_acpi_init(void);
+void amd_iommu_acpi_fini(void);
+amd_iommu_acpi_ivhd_t *amd_iommu_lookup_all_ivhd(void);
+amd_iommu_acpi_ivmd_t *amd_iommu_lookup_all_ivmd(void);
+amd_iommu_acpi_ivhd_t *amd_iommu_lookup_any_ivhd(void);
+amd_iommu_acpi_ivmd_t *amd_iommu_lookup_any_ivmd(void);
+amd_iommu_acpi_global_t *amd_iommu_lookup_acpi_global(void);
+amd_iommu_acpi_ivhd_t *amd_iommu_lookup_ivhd(int32_t deviceid);
+amd_iommu_acpi_ivmd_t *amd_iommu_lookup_ivmd(int32_t deviceid);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AMD_IOMMU_ACPI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_cmd.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,321 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/sunddi.h>
+#include <sys/amd_iommu.h>
+#include "amd_iommu_impl.h"
+
+extern int servicing_interrupt(void);
+
+static void
+amd_iommu_wait_for_completion(amd_iommu_t *iommu)
+{
+	ASSERT(MUTEX_HELD(&iommu->aiomt_cmdlock));
+	while (AMD_IOMMU_REG_GET64(REGADDR64(
+	    iommu->aiomt_reg_status_va), AMD_IOMMU_COMWAIT_INT) != 1) {
+		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
+		    AMD_IOMMU_CMDBUF_ENABLE, 1);
+		WAIT_SEC(1);
+	}
+}
+
+static int
+create_compl_wait_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
+    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
+{
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "create_compl_wait_cmd";
+
+	ASSERT(cmdargsp == NULL);
+
+	if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S) {
+		cmn_err(CE_WARN, "%s: %s%d: idx=%d: 'store' completion "
+		    "not supported for completion wait command",
+		    f, driver, instance, iommu->aiomt_idx);
+		return (DDI_FAILURE);
+	}
+
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_S, 0);
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_I, 1);
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_F,
+	    (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F) != 0);
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO,
+	    0);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x01);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI,
+	    0);
+	cmdptr[2] = 0;
+	cmdptr[3] = 0;
+
+	return (DDI_SUCCESS);
+}
+
+static int
+create_inval_devtab_entry_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
+    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
+{
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "create_inval_devtab_entry_cmd";
+	uint16_t deviceid;
+
+	ASSERT(cmdargsp);
+
+	if (flags != AMD_IOMMU_CMD_FLAGS_NONE) {
+		cmn_err(CE_WARN, "%s: %s%d: idx=%d: invalidate devtab entry "
+		    "no flags supported", f, driver, instance,
+		    iommu->aiomt_idx);
+		return (DDI_FAILURE);
+	}
+
+	deviceid = cmdargsp->ca_deviceid;
+
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID,
+	    deviceid);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x02);
+	cmdptr[2] = 0;
+	cmdptr[3] = 0;
+
+	return (DDI_SUCCESS);
+}
+
+/*ARGSUSED*/
+static int
+create_inval_iommu_pages_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
+    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
+{
+	uint32_t addr_lo;
+	uint32_t addr_hi;
+
+	ASSERT(cmdargsp);
+
+	addr_lo = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
+	    AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO);
+	addr_hi = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
+	    AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI);
+
+	cmdptr[0] = 0;
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID,
+	    cmdargsp->ca_domainid);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x03);
+	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_PDE,
+	    (flags & AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL) != 0);
+	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_S,
+	    (flags & AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S) != 0);
+	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO,
+	    addr_lo);
+	cmdptr[3] = addr_hi;
+
+	return (DDI_SUCCESS);
+
+}
+
+/*ARGSUSED*/
+static int
+create_inval_iotlb_pages_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
+    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
+{
+	uint32_t addr_lo;
+	uint32_t addr_hi;
+
+	ASSERT(cmdargsp);
+
+	addr_lo = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
+	    AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO);
+
+	addr_hi = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
+	    AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI);
+
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID,
+	    cmdargsp->ca_deviceid);
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND,
+	    AMD_IOMMU_DEFAULT_MAXPEND);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x04);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID,
+	    cmdargsp->ca_deviceid);
+	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO,
+	    addr_lo);
+	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_IOTLB_S,
+	    (flags & AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S) != 0);
+	cmdptr[3] = addr_hi;
+
+	return (DDI_SUCCESS);
+}
+
+static int
+create_inval_intr_table_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
+    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
+{
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "create_inval_intr_table_cmd";
+
+	ASSERT(cmdargsp);
+
+	if (flags != AMD_IOMMU_CMD_FLAGS_NONE) {
+		cmn_err(CE_WARN, "%s: %s%d: idx=%d: flags not supported "
+		    "for invalidate interrupt table command",
+		    f, driver, instance, iommu->aiomt_idx);
+		return (DDI_FAILURE);
+	}
+
+	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_INTR_DEVICEID,
+	    cmdargsp->ca_deviceid);
+	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x05);
+	cmdptr[2] = 0;
+	cmdptr[3] = 0;
+
+	return (DDI_SUCCESS);
+}
+
+int
+amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
+    amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held)
+{
+	int error;
+	int i;
+	uint32_t cmdptr[4] = {0};
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	uint64_t cmdhead_off;
+	uint64_t cmdtail_off;
+	const char *f = "amd_iommu_cmd";
+
+	ASSERT(lock_held == 0 || lock_held == 1);
+	ASSERT(lock_held == 0 || MUTEX_HELD(&iommu->aiomt_cmdlock));
+
+	if (!lock_held)
+		mutex_enter(&iommu->aiomt_cmdlock);
+
+	/*
+	 * Prepare the command
+	 */
+	switch (cmd) {
+	case AMD_IOMMU_CMD_COMPL_WAIT:
+		if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT) {
+			cmn_err(CE_WARN, "%s: %s%d: idx=%d: No completion wait "
+			    " after completion wait command",
+			    f, driver, instance, iommu->aiomt_idx);
+			error = DDI_FAILURE;
+			goto out;
+		}
+		error = create_compl_wait_cmd(iommu, cmdargs, flags, cmdptr);
+		break;
+	case AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY:
+		error = create_inval_devtab_entry_cmd(iommu, cmdargs,
+		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
+		break;
+	case AMD_IOMMU_CMD_INVAL_IOMMU_PAGES:
+		error = create_inval_iommu_pages_cmd(iommu, cmdargs,
+		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
+		break;
+	case AMD_IOMMU_CMD_INVAL_IOTLB_PAGES:
+		error = create_inval_iotlb_pages_cmd(iommu, cmdargs,
+		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
+		break;
+	case AMD_IOMMU_CMD_INVAL_INTR_TABLE:
+		error = create_inval_intr_table_cmd(iommu, cmdargs,
+		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
+		break;
+	default:
+		cmn_err(CE_WARN, "%s: %s%d: idx=%d: Unsupported cmd: %d",
+		    f, driver, instance, iommu->aiomt_idx, cmd);
+		error = DDI_FAILURE;
+		goto out;
+	}
+
+	if (error != DDI_SUCCESS) {
+		error = DDI_FAILURE;
+		goto out;
+	}
+
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
+	    AMD_IOMMU_CMDBUF_ENABLE, 1);
+
+	ASSERT(iommu->aiomt_cmd_tail != NULL);
+
+	for (i = 0; i < 4; i++) {
+		iommu->aiomt_cmd_tail[i] = cmdptr[i];
+	}
+
+wait_for_drain:
+	cmdhead_off = AMD_IOMMU_REG_GET64(
+	    REGADDR64(iommu->aiomt_reg_cmdbuf_head_va),
+	    AMD_IOMMU_CMDHEADPTR);
+
+	cmdhead_off = CMD2OFF(cmdhead_off);
+
+	ASSERT(cmdhead_off < iommu->aiomt_cmdbuf_sz);
+
+	/* check for overflow */
+	if ((caddr_t)iommu->aiomt_cmd_tail <
+	    (cmdhead_off + iommu->aiomt_cmdbuf)) {
+		if ((caddr_t)iommu->aiomt_cmd_tail + 16 >=
+		    (cmdhead_off + iommu->aiomt_cmdbuf))
+#ifdef DEBUG
+			cmn_err(CE_WARN, "cmdbuffer overflow: waiting for "
+			    "drain");
+#endif
+			goto wait_for_drain;
+	}
+
+	SYNC_FORDEV(iommu->aiomt_dmahdl);
+
+	/*
+	 * Update the tail pointer in soft state
+	 * and the tail pointer register
+	 */
+	iommu->aiomt_cmd_tail += 4;
+	if ((caddr_t)iommu->aiomt_cmd_tail >= (iommu->aiomt_cmdbuf
+	    + iommu->aiomt_cmdbuf_sz)) {
+		/* wraparound */
+		/*LINTED*/
+		iommu->aiomt_cmd_tail = (uint32_t *)iommu->aiomt_cmdbuf;
+		cmdtail_off = 0;
+	} else {
+		cmdtail_off = (caddr_t)iommu->aiomt_cmd_tail
+		/*LINTED*/
+		    - iommu->aiomt_cmdbuf;
+	}
+
+	ASSERT(cmdtail_off < iommu->aiomt_cmdbuf_sz);
+
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_tail_va),
+	    AMD_IOMMU_CMDTAILPTR, OFF2CMD(cmdtail_off));
+
+	if (cmd == AMD_IOMMU_CMD_COMPL_WAIT) {
+		amd_iommu_wait_for_completion(iommu);
+	} else if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT) {
+		error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_COMPL_WAIT,
+		    NULL, 0, 1);
+	}
+
+out:
+	if (!lock_held)
+		mutex_exit(&iommu->aiomt_cmdlock);
+	return (error);
+}
--- a/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_impl.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_impl.c	Mon Sep 21 11:26:40 2009 -0400
@@ -35,7 +35,7 @@
 #include "amd_iommu_acpi.h"
 #include "amd_iommu_page_tables.h"
 
-static int amd_iommu_fini(amd_iommu_t *iommu);
+static int amd_iommu_fini(amd_iommu_t *iommu, int type);
 static void amd_iommu_teardown_interrupts(amd_iommu_t *iommu);
 static void amd_iommu_stop(amd_iommu_t *iommu);
 
@@ -481,7 +481,7 @@
 }
 
 static void
-amd_iommu_teardown_tables_and_buffers(amd_iommu_t *iommu)
+amd_iommu_teardown_tables_and_buffers(amd_iommu_t *iommu, int type)
 {
 	dev_info_t *dip = iommu->aiomt_dip;
 	int instance = ddi_get_instance(dip);
@@ -493,12 +493,22 @@
 	    AMD_IOMMU_EVENTBASE, 0);
 	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_va),
 	    AMD_IOMMU_EVENTLEN, 0);
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_head_va),
+	    AMD_IOMMU_EVENTHEADPTR, 0);
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_head_va),
+	    AMD_IOMMU_EVENTTAILPTR, 0);
+
 
 	iommu->aiomt_cmdbuf = NULL;
 	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
 	    AMD_IOMMU_COMBASE, 0);
 	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
 	    AMD_IOMMU_COMLEN, 0);
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_head_va),
+	    AMD_IOMMU_CMDHEADPTR, 0);
+	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_head_va),
+	    AMD_IOMMU_CMDTAILPTR, 0);
+
 
 	iommu->aiomt_devtbl = NULL;
 	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
@@ -506,7 +516,7 @@
 	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
 	    AMD_IOMMU_DEVTABSIZE, 0);
 
-	if (iommu->aiomt_dmahdl == NULL)
+	if (iommu->aiomt_dmahdl == NULL || type == AMD_IOMMU_QUIESCE)
 		return;
 
 	/* Unbind the handle */
@@ -1050,7 +1060,7 @@
 		    "control regs. Skipping IOMMU idx=%d", f, driver,
 		    instance, idx);
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
@@ -1094,13 +1104,13 @@
 	 */
 	if (amd_iommu_setup_tables_and_buffers(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
 	if (amd_iommu_setup_exclusion(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
@@ -1108,7 +1118,7 @@
 
 	if (amd_iommu_setup_interrupts(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
@@ -1125,20 +1135,20 @@
 	 */
 	if (amd_iommu_setup_passthru(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
 	if (amd_iommu_start(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
 	/* xxx register/start race  */
 	if (amd_iommu_register(iommu) != DDI_SUCCESS) {
 		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
+		(void) amd_iommu_fini(iommu, AMD_IOMMU_TEARDOWN);
 		return (NULL);
 	}
 
@@ -1151,7 +1161,7 @@
 }
 
 static int
-amd_iommu_fini(amd_iommu_t *iommu)
+amd_iommu_fini(amd_iommu_t *iommu, int type)
 {
 	int idx = iommu->aiomt_idx;
 	dev_info_t *dip = iommu->aiomt_dip;
@@ -1159,17 +1169,28 @@
 	const char *driver = ddi_driver_name(dip);
 	const char *f = "amd_iommu_fini";
 
-	mutex_enter(&iommu->aiomt_mutex);
-	if (amd_iommu_unregister(iommu) != DDI_SUCCESS) {
-		cmn_err(CE_NOTE, "%s: %s%d: Fini of IOMMU unit failed. "
-		    "idx = %d", f, driver, instance, idx);
-		return (DDI_FAILURE);
+	if (type == AMD_IOMMU_TEARDOWN) {
+		mutex_enter(&iommu->aiomt_mutex);
+		if (amd_iommu_unregister(iommu) != DDI_SUCCESS) {
+			cmn_err(CE_NOTE, "%s: %s%d: Fini of IOMMU unit failed. "
+			    "idx = %d", f, driver, instance, idx);
+			return (DDI_FAILURE);
+		}
 	}
+
 	amd_iommu_stop(iommu);
-	amd_iommu_fini_page_tables(iommu);
-	amd_iommu_teardown_interrupts(iommu);
-	amd_iommu_teardown_exclusion(iommu);
-	amd_iommu_teardown_tables_and_buffers(iommu);
+
+	if (type == AMD_IOMMU_TEARDOWN) {
+		amd_iommu_fini_page_tables(iommu);
+		amd_iommu_teardown_interrupts(iommu);
+		amd_iommu_teardown_exclusion(iommu);
+	}
+
+	amd_iommu_teardown_tables_and_buffers(iommu, type);
+
+	if (type == AMD_IOMMU_QUIESCE)
+		return (DDI_SUCCESS);
+
 	if (iommu->aiomt_va != NULL) {
 		hat_unload(kas.a_hat, (void *)(uintptr_t)iommu->aiomt_va,
 		    iommu->aiomt_reg_size, HAT_UNLOAD_UNLOCK);
@@ -1246,7 +1267,7 @@
 		/* check if cap ID is secure device cap id */
 		if (id != PCI_CAP_ID_SECURE_DEV) {
 			if (amd_iommu_debug) {
-				cmn_err(CE_WARN,
+				cmn_err(CE_NOTE,
 				    "%s: %s%d: skipping IOMMU: idx(0x%x) "
 				    "cap ID (0x%x) != secure dev capid (0x%x)",
 				    f, driver, instance, idx, id,
@@ -1299,20 +1320,21 @@
 }
 
 int
-amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep)
+amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep, int type)
 {
 	int instance = ddi_get_instance(dip);
 	const char *driver = ddi_driver_name(dip);
-	amd_iommu_t *iommu;
+	amd_iommu_t *iommu, *next_iommu;
 	int teardown;
 	int error = DDI_SUCCESS;
 	const char *f = "amd_iommu_teardown";
 
 	teardown = 0;
 	for (iommu = statep->aioms_iommu_start; iommu;
-	    iommu = iommu->aiomt_next) {
+	    iommu = next_iommu) {
 		ASSERT(statep->aioms_nunits > 0);
-		if (amd_iommu_fini(iommu) != DDI_SUCCESS) {
+		next_iommu = iommu->aiomt_next;
+		if (amd_iommu_fini(iommu, type) != DDI_SUCCESS) {
 			error = DDI_FAILURE;
 			continue;
 		}
@@ -1394,7 +1416,7 @@
 	mutex_enter(&amd_iommu_pgtable_lock);
 
 	if (amd_iommu_debug == AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d Attempting to get cookies "
+		cmn_err(CE_NOTE, "%s: %s%d: idx=%d Attempting to get cookies "
 		    "from handle for device %s",
 		    f, driver, instance, idx, path);
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_impl.h	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,494 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_AMD_IOMMU_IMPL_H
+#define	_AMD_IOMMU_IMPL_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/pci.h>
+
+#ifdef	_KERNEL
+
+#define	AMD_IOMMU_PCI_PROG_IF	(0x0)
+
+#define	AMD_IOMMU_CAP		(0x3)
+
+#define	AMD_IOMMU_REG_SIZE	(0x2028)
+#define	AMD_IOMMU_DEVTBL_SZ	(16)
+#define	AMD_IOMMU_CMDBUF_SZ	(15)
+#define	AMD_IOMMU_EVENTLOG_SZ	(15)
+#define	AMD_IOMMU_DEVENT_SZ	(32)
+#define	AMD_IOMMU_CMD_SZ	(16)
+#define	AMD_IOMMU_EVENT_SZ	(16)
+
+/* Capability Register offsets */
+#define	AMD_IOMMU_CAP_HDR_OFF		(0x00)
+#define	AMD_IOMMU_CAP_ADDR_LOW_OFF	(0x04)
+#define	AMD_IOMMU_CAP_ADDR_HI_OFF	(0x08)
+#define	AMD_IOMMU_CAP_RANGE_OFF		(0x0C)
+#define	AMD_IOMMU_CAP_MISC_OFF		(0x10)
+
+/* ControL Registers offsets */
+#define	AMD_IOMMU_DEVTBL_REG_OFF	(0x00)
+#define	AMD_IOMMU_CMDBUF_REG_OFF	(0x08)
+#define	AMD_IOMMU_EVENTLOG_REG_OFF	(0x10)
+#define	AMD_IOMMU_CTRL_REG_OFF		(0x18)
+#define	AMD_IOMMU_EXCL_BASE_REG_OFF	(0x20)
+#define	AMD_IOMMU_EXCL_LIM_REG_OFF	(0x28)
+#define	AMD_IOMMU_CMDBUF_HEAD_REG_OFF	(0x2000)
+#define	AMD_IOMMU_CMDBUF_TAIL_REG_OFF	(0x2008)
+#define	AMD_IOMMU_EVENTLOG_HEAD_REG_OFF	(0x2010)
+#define	AMD_IOMMU_EVENTLOG_TAIL_REG_OFF	(0x2018)
+#define	AMD_IOMMU_STATUS_REG_OFF	(0x2020)
+
+/* Capability Header Register Bits */
+#define	AMD_IOMMU_CAP_NPCACHE	(26 << 16 | 26)
+#define	AMD_IOMMU_CAP_HTTUN	(25 << 16 | 25)
+#define	AMD_IOMMU_CAP_IOTLB	(24 << 16 | 24)
+#define	AMD_IOMMU_CAP_TYPE	(18 << 16 | 16)
+#define	AMD_IOMMU_CAP_ID	(7 << 16 | 0)
+
+/* Capability Range Register bits */
+#define	AMD_IOMMU_LAST_DEVFN	(31 << 16 | 24)
+#define	AMD_IOMMU_FIRST_DEVFN	(23 << 16 | 16)
+#define	AMD_IOMMU_RNG_BUS	(15 << 16 | 8)
+#define	AMD_IOMMU_RNG_VALID	(7 << 16 | 7)
+#define	AMD_IOMMU_HT_UNITID	(4 << 16 | 0)
+
+
+/* Capability Misc Register bits */
+#define	AMD_IOMMU_HT_ATSRSV	(22 << 16 | 22)
+#define	AMD_IOMMU_VA_SIZE	(21 << 16 | 15)
+#define	AMD_IOMMU_PA_SIZE	(14 << 16 | 8)
+#define	AMD_IOMMU_MSINUM	(4 << 16 | 0)
+
+/* Device Table Base Address register bits */
+#define	AMD_IOMMU_DEVTABBASE	(51 << 16 | 12)
+#define	AMD_IOMMU_DEVTABSIZE	(8 << 16 | 0)
+
+/* Command Buffer Base Address register bits */
+#define	AMD_IOMMU_COMLEN	(59 << 16 | 56)
+#define	AMD_IOMMU_COMBASE	(51 << 16 | 12)
+
+#define	AMD_IOMMU_CMDBUF_MINSZ	(8)
+#define	AMD_IOMMU_CMDBUF_MAXSZ	(15)
+
+/* Event Log Base Address register bits */
+#define	AMD_IOMMU_EVENTLEN	(59 << 16 | 56)
+#define	AMD_IOMMU_EVENTBASE	(51 << 16 | 12)
+
+#define	AMD_IOMMU_EVENTLOG_MINSZ	(8)
+#define	AMD_IOMMU_EVENTLOG_MAXSZ	(15)
+
+/* Control register bits */
+#define	AMD_IOMMU_CMDBUF_ENABLE		(12 << 16 | 12)
+#define	AMD_IOMMU_ISOC			(11 << 16 | 11)
+#define	AMD_IOMMU_COHERENT		(10 << 16 | 10)
+#define	AMD_IOMMU_RESPASSPW		(9 << 16 | 9)
+#define	AMD_IOMMU_PASSPW		(8 << 16 | 8)
+#define	AMD_IOMMU_INVTO			(7 << 16 | 5)
+#define	AMD_IOMMU_COMWAITINT_ENABLE	(4 << 16 | 4)
+#define	AMD_IOMMU_EVENTINT_ENABLE	(3 << 16 | 3)
+#define	AMD_IOMMU_EVENTLOG_ENABLE	(2 << 16 | 2)
+#define	AMD_IOMMU_HT_TUN_ENABLE		(1 << 16 | 1)
+#define	AMD_IOMMU_ENABLE		(0 << 16 | 0)
+
+/* Exclusion Base Register bits */
+#define	AMD_IOMMU_EXCL_BASE_ADDR	(51 << 16 | 12)
+#define	AMD_IOMMU_EXCL_BASE_ALLOW	(1 << 16 | 1)
+#define	AMD_IOMMU_EXCL_BASE_EXEN	(0 << 16 | 0)
+
+/* Exclusion Limit Register bits */
+#define	AMD_IOMMU_EXCL_LIM		(51 << 16 | 12)
+
+/* Command Buffer Head Pointer Register bits */
+#define	AMD_IOMMU_CMDHEADPTR		(18 << 16 | 4)
+
+/* Command Buffer Tail Pointer Register bits */
+#define	AMD_IOMMU_CMDTAILPTR		(18 << 16 | 4)
+
+/* Event Log Head Pointer Register bits */
+#define	AMD_IOMMU_EVENTHEADPTR		(18 << 16 | 4)
+
+/* Event Log Tail Pointer Register bits */
+#define	AMD_IOMMU_EVENTTAILPTR		(18 << 16 | 4)
+
+/* Status Register bits */
+#define	AMD_IOMMU_CMDBUF_RUN		(4 << 16 | 4)
+#define	AMD_IOMMU_EVENT_LOG_RUN		(3 << 16 | 3)
+#define	AMD_IOMMU_COMWAIT_INT		(2 << 16 | 2)
+#define	AMD_IOMMU_EVENT_LOG_INT		(1 << 16 | 1)
+#define	AMD_IOMMU_EVENT_OVERFLOW_INT	(0 << 16 | 0)
+
+/* Device Table Bits */
+
+/* size in bytes of each device table entry */
+#define	AMD_IOMMU_DEVTBL_ENTRY_SZ	(32)
+
+/* Interrupt Remapping related Device Table bits */
+#define	AMD_IOMMU_DEVTBL_LINT1PASS	((191-128) << 16 | (191-128))
+#define	AMD_IOMMU_DEVTBL_LINT0PASS	((190-128) << 16 | (190-128))
+#define	AMD_IOMMU_DEVTBL_INTCTL		((189-128) << 16 | (188-128))
+#define	AMD_IOMMU_DEVTBL_NMIPASS	((186-128) << 16 | (186-128))
+#define	AMD_IOMMU_DEVTBL_EXTINTPAS	((185-128) << 16 | (185-128))
+#define	AMD_IOMMU_DEVTBL_INITPASS	((184-128) << 16 | (184-128))
+#define	AMD_IOMMU_DEVTBL_INTR_ROOT	((179-128) << 16 | (134-128))
+#define	AMD_IOMMU_DEVTBL_IG		((133-128) << 16 | (133-128))
+#define	AMD_IOMMU_DEVTBL_INTTABLEN	((132-128) << 16 | (129-128))
+#define	AMD_IOMMU_DEVTBL_IV		((128-128) << 16 | (128-128))
+
+/* DMA Remapping related Device Table Bits */
+#define	AMD_IOMMU_DEVTBL_SYSMGT		((105-64) << 16 | (104-64))
+#define	AMD_IOMMU_DEVTBL_EX		((103-64) << 16 | (103-64))
+#define	AMD_IOMMU_DEVTBL_SD		((102-64) << 16 | (102-64))
+#define	AMD_IOMMU_DEVTBL_CACHE		((101-64) << 16 | (101-64))
+#define	AMD_IOMMU_DEVTBL_IOCTL		((100-64) << 16 | (99-64))
+#define	AMD_IOMMU_DEVTBL_SA		((98-64) << 16 | (98-64))
+#define	AMD_IOMMU_DEVTBL_SE		((97-64) << 16 | (97-64))
+#define	AMD_IOMMU_DEVTBL_IOTLB		((96-64) << 16 | (96-64))
+#define	AMD_IOMMU_DEVTBL_DOMAINID	((79-64) << 16 | (64-64))
+#define	AMD_IOMMU_DEVTBL_IW		(62 << 16 | 62)
+#define	AMD_IOMMU_DEVTBL_IR		(61 << 16 | 61)
+#define	AMD_IOMMU_DEVTBL_ROOT_PGTBL	(51 << 16 | 12)
+#define	AMD_IOMMU_DEVTBL_PG_MODE	(11 << 16 | 9)
+#define	AMD_IOMMU_DEVTBL_TV		(1 << 16 | 1)
+#define	AMD_IOMMU_DEVTBL_V		(0 << 16 | 0)
+
+#define	BUS_DEVFN_TO_BDF(b, devfn)	(devfn)
+#define	AMD_IOMMU_ALIAS_HASH_SZ		(256)
+
+#define	AMD_IOMMU_REG_ADDR_LOCKED	(0x1)
+
+/*
+ * IOMMU Command bits
+ */
+
+typedef enum {
+	AMD_IOMMU_CMD_INVAL = 0,
+	AMD_IOMMU_CMD_COMPL_WAIT,
+	AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
+	AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
+	AMD_IOMMU_CMD_INVAL_IOTLB_PAGES,
+	AMD_IOMMU_CMD_INVAL_INTR_TABLE,
+} amd_iommu_cmd_t;
+
+typedef enum {
+	AMD_IOMMU_CMD_FLAGS_NONE = 0,
+	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT = 1,
+	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F = 2,
+	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S = 4,
+	AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL = 8,
+	AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S = 16,
+	AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S = 32
+} amd_iommu_cmd_flags_t;
+
+/* Common command bits */
+#define	AMD_IOMMU_CMD_OPCODE		(31 << 16 | 28)
+
+/* Completion Wait command bits */
+#define	AMD_IOMMU_CMD_COMPL_WAIT_S		(0 << 16 | 0)
+#define	AMD_IOMMU_CMD_COMPL_WAIT_I		(1 << 16 | 1)
+#define	AMD_IOMMU_CMD_COMPL_WAIT_F		(2 << 16 | 2)
+#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO	(31 << 16 | 3)
+#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI	(19 << 16 | 0)
+
+/* Invalidate Device Table entry command bits */
+#define	AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID		(15 << 16 | 0)
+
+/* Invalidate IOMMU Pages command bits */
+#define	AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID		(15 << 16 | 0)
+#define	AMD_IOMMU_CMD_INVAL_PAGES_S			(0 << 16 | 0)
+#define	AMD_IOMMU_CMD_INVAL_PAGES_PDE			(1 << 16 | 1)
+#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO		(31 << 16 | 12)
+#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI		(63 << 16 | 32)
+
+
+/* Invalidate IOTLB command bits */
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID		(15 << 16 | 0)
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND		(31 << 16 | 24)
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID		(15 << 16 | 0)
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_S			(0 << 16 | 0)
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO		(31 << 16 | 12)
+#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI		(31 << 16 | 0)
+
+#define	AMD_IOMMU_DEFAULT_MAXPEND			(10)
+
+/* Invalidate Interrupt Table bits */
+#define	AMD_IOMMU_CMD_INVAL_INTR_DEVICEID		(15 << 16 | 0)
+
+#if defined(__amd64)
+#define	dmac_cookie_addr	dmac_laddress
+#else
+#define	dmac_cookie_addr	dmac_address
+#endif
+
+#define	AMD_IOMMU_TABLE_ALIGN	((1ULL << 12) - 1)
+
+#define	AMD_IOMMU_MAX_DEVICEID	(0xFFFF)
+
+/*
+ * DMA sync macros
+ * TODO: optimize sync only small ranges
+ */
+#define	SYNC_FORDEV(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORDEV)
+#define	SYNC_FORKERN(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORKERNEL)
+
+#define	WAIT_SEC(s)	drv_usecwait(1000000*(s))
+
+#define	CMD2OFF(c)	((c) << 4)
+#define	OFF2CMD(o)	((o) >> 4)
+
+typedef union split {
+	uint64_t u64;
+	uint32_t u32[2];
+} split_t;
+
+#define	BITPOS_START(b)	((b) >> 16)
+#define	BITPOS_END(b)	((b) & 0xFFFF)
+
+#define	START_MASK64(s)	(((s) == 63) ? ~((uint64_t)0) : \
+	(uint64_t)((1ULL << ((s)+1)) - 1))
+#define	START_MASK32(s)	(((s) == 31) ? ~((uint32_t)0) : \
+	(uint32_t)((1ULL << ((s)+1)) - 1))
+#define	START_MASK16(s)	(((s) == 15) ? ~((uint16_t)0) : \
+	(uint16_t)((1ULL << ((s)+1)) - 1))
+#define	START_MASK8(s)	(((s) == 7) ? ~((uint8_t)0) : \
+	(uint8_t)((1ULL << ((s)+1)) - 1))
+
+#define	END_MASK(e)	((1ULL << (e)) - 1)
+
+#define	BIT_MASK64(s, e)	(uint64_t)(START_MASK64(s) & ~END_MASK(e))
+#define	BIT_MASK32(s, e)	(uint32_t)(START_MASK32(s) & ~END_MASK(e))
+#define	BIT_MASK16(s, e)	(uint16_t)(START_MASK16(s) & ~END_MASK(e))
+#define	BIT_MASK8(s, e)		(uint8_t)(START_MASK8(s) & ~END_MASK(e))
+
+#define	AMD_IOMMU_REG_GET64_IMPL(rp, b) \
+	(((*(rp)) & (START_MASK64(BITPOS_START(b)))) >> BITPOS_END(b))
+#define	AMD_IOMMU_REG_GET64(rp, b) 					 \
+	((amd_iommu_64bit_bug) ? amd_iommu_reg_get64_workaround(rp, b) : \
+	AMD_IOMMU_REG_GET64_IMPL(rp, b))
+#define	AMD_IOMMU_REG_GET32(rp, b) \
+	(((*(rp)) & (START_MASK32(BITPOS_START(b)))) >> BITPOS_END(b))
+#define	AMD_IOMMU_REG_GET16(rp, b) \
+	(((*(rp)) & (START_MASK16(BITPOS_START(b)))) >> BITPOS_END(b))
+#define	AMD_IOMMU_REG_GET8(rp, b) \
+	(((*(rp)) & (START_MASK8(BITPOS_START(b)))) >> BITPOS_END(b))
+
+#define	AMD_IOMMU_REG_SET64_IMPL(rp, b, v) \
+	((*(rp)) = \
+	(((uint64_t)(*(rp)) & ~(BIT_MASK64(BITPOS_START(b), BITPOS_END(b)))) \
+	| ((uint64_t)(v) << BITPOS_END(b))))
+
+#define	AMD_IOMMU_REG_SET64(rp, b, v) 			\
+	(void) ((amd_iommu_64bit_bug) ?			\
+	amd_iommu_reg_set64_workaround(rp, b, v) : 	\
+	AMD_IOMMU_REG_SET64_IMPL(rp, b, v))
+
+#define	AMD_IOMMU_REG_SET32(rp, b, v) \
+	((*(rp)) = \
+	(((uint32_t)(*(rp)) & ~(BIT_MASK32(BITPOS_START(b), BITPOS_END(b)))) \
+	| ((uint32_t)(v) << BITPOS_END(b))))
+
+#define	AMD_IOMMU_REG_SET16(rp, b, v) \
+	((*(rp)) = \
+	(((uint16_t)(*(rp)) & ~(BIT_MASK16(BITPOS_START(b), BITPOS_END(b)))) \
+	| ((uint16_t)(v) << BITPOS_END(b))))
+
+#define	AMD_IOMMU_REG_SET8(rp, b, v) \
+	((*(rp)) = \
+	(((uint8_t)(*(rp)) & ~(BIT_MASK8(BITPOS_START(b), BITPOS_END(b)))) \
+	| ((uint8_t)(v) << BITPOS_END(b))))
+
+/*
+ * Cast a 64 bit pointer to a uint64_t *
+ */
+#define	REGADDR64(a)	((uint64_t *)(uintptr_t)(a))
+
+typedef enum {
+	AMD_IOMMU_INTR_INVALID = 0,
+	AMD_IOMMU_INTR_TABLE,
+	AMD_IOMMU_INTR_ALLOCED,
+	AMD_IOMMU_INTR_HANDLER,
+	AMD_IOMMU_INTR_ENABLED
+} amd_iommu_intr_state_t;
+
+
+typedef struct amd_iommu {
+	kmutex_t aiomt_mutex;
+	kmutex_t aiomt_eventlock;
+	kmutex_t aiomt_cmdlock;
+	dev_info_t *aiomt_dip;
+	int aiomt_idx;
+	iommulib_handle_t aiomt_iommulib_handle;
+	iommulib_ops_t *aiomt_iommulib_ops;
+	uint32_t aiomt_cap_hdr;
+	uint8_t aiomt_npcache;
+	uint8_t aiomt_httun;
+	uint8_t aiomt_iotlb;
+	uint8_t aiomt_captype;
+	uint8_t aiomt_capid;
+	uint32_t aiomt_low_addr32;
+	uint32_t aiomt_hi_addr32;
+	uint64_t aiomt_reg_pa;
+	uint64_t aiomt_va;
+	uint64_t aiomt_reg_va;
+	uint32_t aiomt_range;
+	uint8_t aiomt_rng_bus;
+	uint8_t aiomt_first_devfn;
+	uint8_t aiomt_last_devfn;
+	uint8_t aiomt_rng_valid;
+	uint8_t aiomt_ht_unitid;
+	uint32_t aiomt_misc;
+	uint8_t aiomt_htatsresv;
+	uint8_t aiomt_vasize;
+	uint8_t aiomt_pasize;
+	uint8_t aiomt_msinum;
+	uint8_t aiomt_reg_pages;
+	uint32_t aiomt_reg_size;
+	uint32_t aiomt_devtbl_sz;
+	uint32_t aiomt_cmdbuf_sz;
+	uint32_t aiomt_eventlog_sz;
+	caddr_t aiomt_devtbl;
+	caddr_t aiomt_cmdbuf;
+	caddr_t aiomt_eventlog;
+	uint32_t *aiomt_cmd_tail;
+	uint32_t *aiomt_event_head;
+	ddi_dma_handle_t aiomt_dmahdl;
+	void *aiomt_dma_bufva;
+	uint64_t aiomt_dma_mem_realsz;
+	ddi_acc_handle_t aiomt_dma_mem_hdl;
+	ddi_dma_cookie_t aiomt_buf_dma_cookie;
+	uint_t aiomt_buf_dma_ncookie;
+	amd_iommu_intr_state_t aiomt_intr_state;
+	ddi_intr_handle_t *aiomt_intr_htable;
+	uint32_t aiomt_intr_htable_sz;
+	uint32_t aiomt_actual_intrs;
+	uint32_t aiomt_intr_cap;
+	uint64_t aiomt_reg_devtbl_va;
+	uint64_t aiomt_reg_cmdbuf_va;
+	uint64_t aiomt_reg_eventlog_va;
+	uint64_t aiomt_reg_ctrl_va;
+	uint64_t aiomt_reg_excl_base_va;
+	uint64_t aiomt_reg_excl_lim_va;
+	uint64_t aiomt_reg_cmdbuf_head_va;
+	uint64_t aiomt_reg_cmdbuf_tail_va;
+	uint64_t aiomt_reg_eventlog_head_va;
+	uint64_t aiomt_reg_eventlog_tail_va;
+	uint64_t aiomt_reg_status_va;
+	struct amd_iommu *aiomt_next;
+} amd_iommu_t;
+
+typedef struct amd_iommu_dma_devtbl_ent {
+	uint16_t de_domainid;
+	uint8_t de_R;
+	uint8_t de_W;
+	caddr_t de_root_pgtbl;
+	uint8_t de_pgmode;
+} amd_iommu_dma_devtbl_entry_t;
+
+typedef struct amd_iommu_alias {
+	uint16_t al_bdf;
+	uint16_t al_src_bdf;
+	struct amd_iommu_alias *al_next;
+} amd_iommu_alias_t;
+
+typedef struct amd_iommu_cmdargs {
+	uint64_t ca_addr;
+	uint16_t ca_domainid;
+	uint16_t ca_deviceid;
+} amd_iommu_cmdargs_t;
+
+struct amd_iommu_page_table;
+
+typedef struct amd_iommu_page_table_hash {
+	kmutex_t ampt_lock;
+	struct amd_iommu_page_table **ampt_hash;
+} amd_iommu_page_table_hash_t;
+
+typedef enum {
+	AMD_IOMMU_LOG_INVALID_OP = 0,
+	AMD_IOMMU_LOG_DISPLAY,
+	AMD_IOMMU_LOG_DISCARD
+} amd_iommu_log_op_t;
+
+typedef enum {
+	AMD_IOMMU_DEBUG_NONE = 0,
+	AMD_IOMMU_DEBUG_ALLOCHDL = 0x1,
+	AMD_IOMMU_DEBUG_FREEHDL = 0x2,
+	AMD_IOMMU_DEBUG_BIND = 0x4,
+	AMD_IOMMU_DEBUG_UNBIND = 0x8,
+	AMD_IOMMU_DEBUG_WIN = 0x10,
+	AMD_IOMMU_DEBUG_PAGE_TABLES = 0x20,
+	AMD_IOMMU_DEBUG_DEVTBL = 0x40,
+	AMD_IOMMU_DEBUG_CMDBUF = 0x80,
+	AMD_IOMMU_DEBUG_EVENTLOG = 0x100,
+	AMD_IOMMU_DEBUG_ACPI = 0x200,
+	AMD_IOMMU_DEBUG_PA2VA = 0x400,
+	AMD_IOMMU_DEBUG_TABLES = 0x800,
+	AMD_IOMMU_DEBUG_EXCL = 0x1000,
+	AMD_IOMMU_DEBUG_INTR = 0x2000
+} amd_iommu_debug_t;
+
+extern const char *amd_iommu_modname;
+extern kmutex_t amd_iommu_global_lock;
+extern amd_iommu_alias_t **amd_iommu_alias;
+extern amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
+extern ddi_device_acc_attr_t amd_iommu_devacc;
+extern amd_iommu_debug_t amd_iommu_debug;
+
+extern uint8_t amd_iommu_htatsresv;
+extern uint8_t amd_iommu_vasize;
+extern uint8_t amd_iommu_pasize;
+extern int amd_iommu_64bit_bug;
+extern int amd_iommu_unity_map;
+extern int amd_iommu_no_RW_perms;
+extern int amd_iommu_no_unmap;
+extern int amd_iommu_pageva_inval_all;
+extern int amd_iommu_disable;
+extern char *amd_iommu_disable_list;
+
+extern uint64_t amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits);
+extern uint64_t amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits,
+    uint64_t value);
+
+int amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
+    amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held);
+int amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt);
+void amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt);
+
+int amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op);
+void amd_iommu_read_boot_props(void);
+void amd_iommu_lookup_conf_props(dev_info_t *dip);
+
+#endif	/* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _AMD_IOMMU_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_log.c	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,582 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/sunddi.h>
+#include <sys/amd_iommu.h>
+#include "amd_iommu_impl.h"
+#include "amd_iommu_log.h"
+
+
+static const char *
+get_hw_error(uint8_t type)
+{
+	const char *hwerr;
+
+	switch (type) {
+	case 0:
+		hwerr = "Reserved";
+		break;
+	case 1:
+		hwerr = "Master Abort";
+		break;
+	case 2:
+		hwerr = "Target Abort";
+		break;
+	case 3:
+		hwerr = "Data Error";
+		break;
+	default:
+		hwerr = "Unknown";
+		break;
+	}
+
+	return (hwerr);
+}
+
+const char *
+get_illegal_req(uint8_t type, uint8_t TR)
+{
+	const char *illreq;
+
+	switch (type) {
+	case 0:
+		illreq = (TR == 1) ? "Translation I=0/V=0/V=1&&TV=0" :
+		    "Read or Non-posted Write in INTR Range";
+		break;
+	case 1:
+		illreq = (TR == 1) ? "Translation INTR/Port-IO/SysMgt; OR"
+		    "Translation when SysMgt=11b/Port-IO when IOCTL=10b "
+		    "while V=1 && TV=0" :
+		    "Pre-translated transaction from device with I=0 or V=0";
+		break;
+	case 2:
+		illreq = (TR == 1) ? "Reserved":
+		    "Port-IO transaction for device with IoCtl = 00b";
+		break;
+	case 3:
+		illreq = (TR == 1) ? "Reserved":
+		    "Posted write to SysMgt with device SysMgt=00b "
+		    "OR SysMgt=10b && message not INTx "
+		    "OR Posted write to addr transaltion range with "
+		    "HtAtsResv=1";
+		break;
+	case 4:
+		illreq = (TR == 1) ? "Reserved":
+		    "Read request or non-posted write in SysMgt with "
+		    "device SysMgt=10b or 0xb"
+		    "OR Read request or non-posted write in "
+		    "addr translation range with HtAtsResv=1";
+		break;
+	case 5:
+		illreq = (TR == 1) ? "Reserved":
+		    "Posted write to Interrupt/EOI Range "
+		    "for device that has IntCtl=00b";
+		break;
+	case 6:
+		illreq = (TR == 1) ? "Reserved":
+		    "Posted write to reserved Interrupt Address Range";
+		break;
+	case 7:
+		illreq = (TR == 1) ? "Reserved":
+		    "transaction to SysMgt when SysMgt=11b OR "
+		    "transaction to Port-IO when IoCtl=10b while "
+		    "while V=1 TV=0";
+		break;
+	default:
+		illreq = "Unknown error";
+		break;
+	}
+	return (illreq);
+}
+
+static void
+devtab_illegal_entry(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint8_t TR;
+	uint8_t RZ;
+	uint8_t RW;
+	uint8_t I;
+	uint32_t vaddr_lo;
+	uint32_t vaddr_hi;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "devtab_illegal_entry";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_DEVICEID);
+
+	TR = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_TR);
+
+	RZ = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_RZ);
+
+	RW = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_RW);
+
+	I = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_INTR);
+
+	vaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_DEVTAB_ILL_VADDR_LO);
+
+	vaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal device table entry "
+	    "deviceid=%u, %s request, %s %s transaction, %s request, "
+	    "virtual address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    deviceid,
+	    TR == 1 ? "Translation" : "Transaction",
+	    RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding",
+	    RW == 1 ? "Write" : "Read",
+	    I == 1 ? "Interrupt" : "Memory",
+	    (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo));
+}
+
+static void
+io_page_fault(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint16_t domainid;
+	uint8_t TR;
+	uint8_t RZ;
+	uint8_t RW;
+	uint8_t PE;
+	uint8_t PR;
+	uint8_t I;
+	uint32_t vaddr_lo;
+	uint32_t vaddr_hi;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "io_page_fault";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_IO_PAGE_FAULT);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_IO_PGFAULT_DEVICEID);
+
+	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_TR);
+
+	RZ = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RZ);
+
+	PE = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PE);
+
+	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RW);
+
+	PR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PR);
+
+	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_INTR);
+
+	domainid = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_IO_PGFAULT_DOMAINID);
+
+	vaddr_lo = event[2];
+
+	vaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. IO Page Fault. "
+	    "deviceid=%u, %s request, %s, %s permissions, %s transaction, "
+	    "%s, %s request, domainid=%u, virtual address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    deviceid,
+	    TR == 1 ? "Translation" : "Transaction",
+	    RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding",
+	    PE == 1 ? "did not have" : "had",
+	    RW == 1 ? "Write" : "Read",
+	    PR == 1 ? "Page present or Interrupt Remapped" :
+	    "Page not present or Interrupt Blocked",
+	    I == 1 ? "Interrupt" : "Memory",
+	    domainid,
+	    (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo));
+}
+
+static void
+devtab_hw_error(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint8_t type;
+	uint8_t TR;
+	uint8_t RW;
+	uint8_t I;
+	uint32_t physaddr_lo;
+	uint32_t physaddr_hi;
+	const char *hwerr;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "devtab_hw_error";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_DEVTAB_HW_ERROR);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_DEVTAB_HWERR_DEVICEID);
+
+	type = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE);
+
+	hwerr = get_hw_error(type);
+
+	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_TR);
+
+	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_RW);
+
+	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_INTR);
+
+	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_DEVTAB_HWERR_PHYSADDR_LO);
+
+	physaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Device Table HW Error. "
+	    "deviceid=%u, HW error type: %s, %s request, %s transaction, "
+	    "%s request, physical address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    deviceid, hwerr,
+	    TR == 1 ? "Translation" : "Transaction",
+	    RW == 1 ? "Write" : "Read",
+	    I == 1 ? "Interrupt" : "Memory",
+	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
+}
+
+
+static void
+pgtable_hw_error(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint16_t domainid;
+	uint8_t type;
+	uint8_t TR;
+	uint8_t RW;
+	uint8_t I;
+	uint32_t physaddr_lo;
+	uint32_t physaddr_hi;
+	const char *hwerr;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "pgtable_hw_error";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_PGTABLE_HW_ERROR);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_PGTABLE_HWERR_DEVICEID);
+
+	type = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE);
+
+	hwerr = get_hw_error(type);
+
+	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_TR);
+
+	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_RW);
+
+	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_INTR);
+
+	domainid = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_PGTABLE_HWERR_DOMAINID);
+
+	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_PGTABLE_HWERR_PHYSADDR_LO);
+
+	physaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Page Table HW Error. "
+	    "deviceid=%u, HW error type: %s, %s request, %s transaction, "
+	    "%s request, domainid=%u, physical address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    deviceid, hwerr,
+	    TR == 1 ? "Translation" : "Transaction",
+	    RW == 1 ? "Write" : "Read",
+	    I == 1 ? "Interrupt" : "Memory",
+	    domainid,
+	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
+}
+
+static void
+cmdbuf_illegal_cmd(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint32_t physaddr_lo;
+	uint32_t physaddr_hi;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "cmdbuf_illegal_cmd";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD);
+
+	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD_PHYS_LO);
+
+	physaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal IOMMU command. "
+	    "command physical address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
+}
+
+static void
+cmdbuf_hw_error(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint32_t physaddr_lo;
+	uint32_t physaddr_hi;
+	uint8_t type;
+	const char *hwerr;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "cmdbuf_hw_error";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_CMDBUF_HW_ERROR);
+
+	type = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_CMDBUF_HWERR_TYPE);
+
+	hwerr = get_hw_error(type);
+
+	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_CMDBUF_HWERR_PHYS_LO);
+
+	physaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Command Buffer HW error. "
+	    "HW error type = %s, command buffer physical address = %p",
+	    f, driver, instance, iommu->aiomt_idx,
+	    hwerr,
+	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
+}
+
+static void
+iotlb_inval_to(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint32_t physaddr_lo;
+	uint32_t physaddr_hi;
+	uint8_t type;
+	const char *hwerr;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "iotlb_inval_to";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_DEVICEID);
+
+	/*
+	 * XXX bug in spec. Is the type field available +04 26:25 or is
+	 * it reserved
+	 */
+	type = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_TYPE);
+	hwerr = get_hw_error(type);
+
+	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
+	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_PHYS_LO);
+
+	physaddr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %u "
+	    "IOTLB invalidation Timeout. "
+	    "HW error type = %s, invalidation command physical address = %p",
+	    f, driver, instance, iommu->aiomt_idx, deviceid,
+	    hwerr,
+	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
+}
+
+static void
+device_illegal_req(amd_iommu_t *iommu, uint32_t *event)
+{
+	uint16_t deviceid;
+	uint8_t TR;
+	uint32_t addr_lo;
+	uint32_t addr_hi;
+	uint8_t type;
+	const char *reqerr;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "device_illegal_req";
+
+	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
+	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ);
+
+	deviceid = AMD_IOMMU_REG_GET32(&event[0],
+	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_DEVICEID);
+
+	TR = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TR);
+
+	type = AMD_IOMMU_REG_GET32(&event[1],
+	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TYPE);
+
+	reqerr = get_illegal_req(type, TR);
+
+
+	addr_lo = event[2];
+	addr_hi = event[3];
+
+	cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %d "
+	    "Illegal Device Request. "
+	    "Illegal Request type = %s, %s request, address accessed = %p",
+	    f, driver, instance, iommu->aiomt_idx, deviceid,
+	    reqerr,
+	    TR == 1 ? "Translation" : "Transaction",
+	    (void *)(uintptr_t)(((uint64_t)addr_hi) << 32 | addr_lo));
+}
+
+static void
+amd_iommu_process_one_event(amd_iommu_t *iommu)
+{
+	uint32_t event[4];
+	amd_iommu_event_t event_type;
+	int i;
+	const char *driver = ddi_driver_name(iommu->aiomt_dip);
+	int instance = ddi_get_instance(iommu->aiomt_dip);
+	const char *f = "amd_iommu_process_one_event";
+
+	ASSERT(MUTEX_HELD(&iommu->aiomt_eventlock));
+
+	SYNC_FORKERN(iommu->aiomt_dmahdl);
+	for (i = 0; i < 4; i++) {
+		event[i] =  iommu->aiomt_event_head[i];
+	}
+
+	event_type = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE);
+
+	switch (event_type) {
+	case AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY:
+		devtab_illegal_entry(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_IO_PAGE_FAULT:
+		io_page_fault(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_DEVTAB_HW_ERROR:
+		devtab_hw_error(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_PGTABLE_HW_ERROR:
+		pgtable_hw_error(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_CMDBUF_HW_ERROR:
+		cmdbuf_hw_error(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD:
+		cmdbuf_illegal_cmd(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_IOTLB_INVAL_TO:
+		iotlb_inval_to(iommu, event);
+		break;
+	case AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ:
+		device_illegal_req(iommu, event);
+		break;
+	default:
+		cmn_err(CE_WARN, "%s: %s%d: idx = %d. Unknown event: %u",
+		    f, driver, instance, iommu->aiomt_idx, event_type);
+		break;
+	}
+}
+
+int
+amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op)
+{
+	caddr_t evtail;
+	uint64_t evtail_off;
+	uint64_t evhead_off;
+
+	ASSERT(op != AMD_IOMMU_LOG_INVALID_OP);
+
+	mutex_enter(&iommu->aiomt_eventlock);
+
+	ASSERT(iommu->aiomt_event_head != NULL);
+
+	/* XXX verify */
+	evtail_off = AMD_IOMMU_REG_GET64(
+	    REGADDR64(iommu->aiomt_reg_eventlog_tail_va),
+	    AMD_IOMMU_EVENTTAILPTR);
+
+	evtail_off = EV2OFF(evtail_off);
+
+	ASSERT(evtail_off <  iommu->aiomt_eventlog_sz);
+
+	evtail = iommu->aiomt_eventlog + evtail_off;
+
+	if (op == AMD_IOMMU_LOG_DISCARD) {
+		/*LINTED*/
+		iommu->aiomt_event_head = (uint32_t *)evtail;
+		AMD_IOMMU_REG_SET64(REGADDR64(
+		    iommu->aiomt_reg_eventlog_head_va),
+		    AMD_IOMMU_EVENTHEADPTR, OFF2EV(evtail_off));
+		cmn_err(CE_NOTE, "Discarded IOMMU event log");
+		mutex_exit(&iommu->aiomt_eventlock);
+		return (DDI_SUCCESS);
+	}
+
+	/*LINTED*/
+	while (1) {
+		if ((caddr_t)iommu->aiomt_event_head == evtail)
+			break;
+
+		cmn_err(CE_WARN, "evtail_off = %p, head = %p, tail = %p",
+		    (void *)(uintptr_t)evtail_off,
+		    (void *)iommu->aiomt_event_head,
+		    (void *)evtail);
+
+		amd_iommu_process_one_event(iommu);
+
+		/*
+		 * Update the head pointer in soft state
+		 * and the head pointer register
+		 */
+		iommu->aiomt_event_head += 4;
+		if ((caddr_t)iommu->aiomt_event_head >=
+		    iommu->aiomt_eventlog + iommu->aiomt_eventlog_sz) {
+			/* wraparound */
+			iommu->aiomt_event_head =
+			/*LINTED*/
+			    (uint32_t *)iommu->aiomt_eventlog;
+			evhead_off = 0;
+		} else {
+			evhead_off =  (caddr_t)iommu->aiomt_event_head
+			/*LINTED*/
+			    - iommu->aiomt_eventlog;
+		}
+
+		ASSERT(evhead_off < iommu->aiomt_eventlog_sz);
+
+		AMD_IOMMU_REG_SET64(REGADDR64(
+		    iommu->aiomt_reg_eventlog_head_va),
+		    AMD_IOMMU_EVENTHEADPTR, OFF2EV(evhead_off));
+	}
+	mutex_exit(&iommu->aiomt_eventlock);
+
+	return (DDI_SUCCESS);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_log.h	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD_IOMMU_LOG_H
+#define	_AMD_IOMMU_LOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/amd_iommu.h>
+
+#ifdef _KERNEL
+
+#define	EV2OFF(e)	((e) << 4)
+#define	OFF2EV(o)	((o) >> 4)
+
+typedef enum {
+	AMD_IOMMU_EVENT_INVALID = 0,
+	AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY = 1,
+	AMD_IOMMU_EVENT_IO_PAGE_FAULT = 2,
+	AMD_IOMMU_EVENT_DEVTAB_HW_ERROR = 3,
+	AMD_IOMMU_EVENT_PGTABLE_HW_ERROR = 4,
+	AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD = 5,
+	AMD_IOMMU_EVENT_CMDBUF_HW_ERROR = 6,
+	AMD_IOMMU_EVENT_IOTLB_INVAL_TO = 7,
+	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ = 8
+} amd_iommu_event_t;
+
+/* Common to all events */
+#define	AMD_IOMMU_EVENT_TYPE			(31 << 16 | 28)
+
+/* Illegal device Table Entry Event bits */
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_TR		(24 << 16 | 24)
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_RZ		(23 << 16 | 23)
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_RW		(21 << 16 | 21)
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_INTR		(19 << 16 | 19)
+#define	AMD_IOMMU_EVENT_DEVTAB_ILL_VADDR_LO	(31 << 16 | 2)
+
+/* IO Page Fault event bits */
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_TR		(24 << 16 | 24)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_RZ		(23 << 16 | 23)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_PE		(22 << 16 | 22)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_RW		(21 << 16 | 21)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_PR		(20 << 16 | 20)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_INTR		(19 << 16 | 19)
+#define	AMD_IOMMU_EVENT_IO_PGFAULT_DOMAINID	(15 << 16 | 0)
+
+
+/* Device Table HW Error event bits */
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE	(26 << 16 | 25)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TR		(24 << 16 | 24)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_RW		(21 << 16 | 21)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_INTR	(19 << 16 | 19)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_PHYSADDR_LO	(31 << 16 | 4)
+
+
+/* Page Table HW Error event bits */
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE	(26 << 16 | 25)
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_TR	(24 << 16 | 24)
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_RW	(21 << 16 | 21)
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_INTR	(19 << 16 | 19)
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_DOMAINID  (15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_PHYSADDR_LO	(31 << 16 | 3)
+
+/* Illegal Command Error event bits */
+#define	AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD_PHYS_LO	(31 << 16 | 4)
+
+/* Command Buffer HW Error event bits */
+#define	AMD_IOMMU_EVENT_CMDBUF_HWERR_TYPE	(26 << 16 | 25)
+#define	AMD_IOMMU_EVENT_CMDBUF_HWERR_PHYS_LO	(31 << 16 | 4)
+
+
+/* IOTLB Invalidation TO event bits */
+#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_TYPE	(26 << 16 | 25)
+#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_PHYS_LO	(31 << 16 | 4)
+
+/* Illegal Device request event bits */
+#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_DEVICEID	(15 << 16 | 0)
+#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TYPE		(27 << 16 | 25)
+#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TR		(24 << 16 | 24)
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AMD_IOMMU_LOG_H */
--- a/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_page_tables.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_page_tables.c	Mon Sep 21 11:26:40 2009 -0400
@@ -510,14 +510,14 @@
 {
 	uint64_t *devtbl_entry;
 	amd_iommu_cmdargs_t cmdargs = {0};
-	int error;
+	int error, flags;
 	dev_info_t *idip = iommu->aiomt_dip;
 	const char *driver = ddi_driver_name(idip);
 	int instance = ddi_get_instance(idip);
 	const char *f = "amd_iommu_set_devtbl_entry";
 
 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: attempting to set devtbl entry for %s",
+		cmn_err(CE_NOTE, "%s: attempting to set devtbl entry for %s",
 		    f, path);
 	}
 
@@ -536,10 +536,39 @@
 	    [deviceid * AMD_IOMMU_DEVTBL_ENTRY_SZ];
 
 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: deviceid=%u devtbl entry (%p) for %s",
+		cmn_err(CE_NOTE, "%s: deviceid=%u devtbl entry (%p) for %s",
 		    f, deviceid, (void *)(uintptr_t)(*devtbl_entry), path);
 	}
 
+	/*
+	 * Flush internal caches, need to do this if we came up from
+	 * fast boot
+	 */
+	cmdargs.ca_deviceid = deviceid;
+	error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
+	    &cmdargs, 0, 0);
+	if (error != DDI_SUCCESS) {
+		cmn_err(CE_WARN, "%s: idx=%d: deviceid=%d"
+		    "Failed to invalidate domain in IOMMU HW cache",
+		    f, iommu->aiomt_idx, deviceid);
+		return (error);
+	}
+
+	cmdargs.ca_domainid = (uint16_t)domainid;
+	cmdargs.ca_addr = (uintptr_t)0x7FFFFFFFFFFFF000;
+	flags = AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL |
+	    AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S;
+
+	error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
+	    &cmdargs, flags, 0);
+	if (error != DDI_SUCCESS) {
+		cmn_err(CE_WARN, "%s: idx=%d: domainid=%d"
+		    "Failed to invalidate translations in IOMMU HW cache",
+		    f, iommu->aiomt_idx, cmdargs.ca_domainid);
+		return (error);
+	}
+
+	/* Initialize device table entry */
 	if (init_devtbl(iommu, devtbl_entry, domainid, dp)) {
 		cmdargs.ca_deviceid = deviceid;
 		error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
@@ -582,7 +611,7 @@
 	    [deviceid * AMD_IOMMU_DEVTBL_ENTRY_SZ];
 
 	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: deviceid=%u devtbl entry (%p) for %s",
+		cmn_err(CE_NOTE, "%s: deviceid=%u devtbl entry (%p) for %s",
 		    f, deviceid, (void *)(uintptr_t)(*devtbl_entry), path);
 	}
 
@@ -1548,7 +1577,7 @@
 	for (pfn = pfn_start; pfn <= pfn_end; pfn++, pg++) {
 
 		if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-			cmn_err(CE_WARN, "%s: attempting to create page tables "
+			cmn_err(CE_NOTE, "%s: attempting to create page tables "
 			    "for pfn = %p, va = %p, path = %s",
 			    f, (void *)(uintptr_t)(pfn << MMU_PAGESHIFT),
 			    (void *)(uintptr_t)(pg << MMU_PAGESHIFT), path);
@@ -1568,7 +1597,7 @@
 		}
 
 		if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-			cmn_err(CE_WARN, "%s: successfuly created page tables "
+			cmn_err(CE_NOTE, "%s: successfuly created page tables "
 			    "for pfn = %p, vapg = %p, path = %s",
 			    f, (void *)(uintptr_t)pfn,
 			    (void *)(uintptr_t)pg, path);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/i86pc/io/amd_iommu/amd_iommu_page_tables.h	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,134 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _AMD_IOMMU_PAGE_TABLES_H
+#define	_AMD_IOMMU_PAGE_TABLES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+
+/* Common to PTEs and PDEs */
+#define	AMD_IOMMU_PTDE_IW		(62 << 16 | 62)
+#define	AMD_IOMMU_PTDE_IR		(61 << 16 | 61)
+#define	AMD_IOMMU_PTDE_ADDR		(51 << 16 | 12)
+#define	AMD_IOMMU_PTDE_NXT_LVL		(11 << 16 | 9)
+#define	AMD_IOMMU_PTDE_PR		(0 << 16 | 0)
+
+#define	AMD_IOMMU_PTE_FC		(60 << 16 | 60)
+#define	AMD_IOMMU_PTE_U			(59 << 16 | 59)
+
+#define	AMD_IOMMU_VA_NBITS(l)		((l) == 6 ? 7 : 9)
+#define	AMD_IOMMU_VA_BITMASK(l)		((1 << AMD_IOMMU_VA_NBITS(l)) - 1)
+#define	AMD_IOMMU_VA_SHIFT(v, l)	\
+	((v) >> (MMU_PAGESHIFT + (AMD_IOMMU_VA_NBITS(l - 1) * (l - 1))))
+#define	AMD_IOMMU_VA_BITS(v, l)		\
+	(AMD_IOMMU_VA_SHIFT(v, l) & AMD_IOMMU_VA_BITMASK(l))
+#define	AMD_IOMMU_VA_TOTBITS(l)		\
+	(((l) == 6 ? 7 + (l - 1) * 9: l*9) + MMU_PAGESHIFT)
+#define	AMD_IOMMU_VA_TOTMASK(l)		((1 << AMD_IOMMU_VA_TOTBITS(l)) - 1)
+#define	AMD_IOMMU_VA_INVAL_SETMASK(l)	\
+	(((1 << AMD_IOMMU_VA_TOTBITS(l)) - 1) >> 1)
+#define	AMD_IOMMU_VA_INVAL_CLRMASK(l)	\
+	(~(1 << (AMD_IOMMU_VA_TOTBITS(l) - 1)))
+#define	AMD_IOMMU_VA_INVAL(v, l)	\
+	(((v) & AMD_IOMMU_VA_INVAL_CLRMASK(l)) | AMD_IOMMU_VA_INVAL_SETMASK(l))
+
+#define	AMD_IOMMU_PGTABLE_SZ		(4096)
+#define	AMD_IOMMU_PGTABLE_MAXLEVEL	(6)
+#define	AMD_IOMMU_PGTABLE_HASH_SZ	(256)
+
+#define	AMD_IOMMU_PGTABLE_ALIGN		((1ULL << 12) - 1)
+#define	AMD_IOMMU_PGTABLE_SIZE		(1ULL << 12)
+
+#define	AMD_IOMMU_MAX_PDTE		(1ULL << AMD_IOMMU_VA_NBITS(1))
+#define	PT_REF_VALID(p)			((p)->pt_ref >= 0 && \
+					(p)->pt_ref <= AMD_IOMMU_MAX_PDTE)
+
+#define	AMD_IOMMU_DOMAIN_HASH_SZ	(256)
+#define	AMD_IOMMU_PGTABLE_FREELIST_MAX	(256)
+#define	AMD_IOMMU_PA2VA_HASH_SZ		(256)
+
+#define	AMD_IOMMU_SIZE_4G		((uint64_t)1 << 32)
+#define	AMD_IOMMU_VMEM_NAMELEN		(30)
+
+typedef enum {
+	AMD_IOMMU_INVALID_DOMAIN = 0,
+	AMD_IOMMU_IDENTITY_DOMAIN = 0xFFFD,
+	AMD_IOMMU_PASSTHRU_DOMAIN = 0xFFFE,
+	AMD_IOMMU_SYS_DOMAIN = 0xFFFF
+} domain_id_t;
+
+typedef enum {
+	AMD_IOMMU_INVALID_MAP = 0,
+	AMD_IOMMU_UNITY_MAP,
+	AMD_IOMMU_VMEM_MAP
+} map_type_t;
+
+typedef struct amd_iommu_page_table {
+	domain_id_t pt_domainid;
+	int pt_level;
+	ddi_dma_handle_t pt_dma_hdl;
+	ddi_acc_handle_t pt_mem_hdl;
+	uint64_t pt_mem_reqsz;
+	uint64_t pt_mem_realsz;
+	uint64_t *pt_pgtblva;
+	uint64_t pt_pte_ref[AMD_IOMMU_MAX_PDTE];
+	uint16_t pt_index;
+	int pt_ref;
+	ddi_dma_cookie_t pt_cookie;
+	struct amd_iommu_page_table *pt_next;
+	struct amd_iommu_page_table *pt_prev;
+	struct amd_iommu_page_table *pt_parent;
+} amd_iommu_page_table_t;
+
+typedef struct amd_iommu_domain {
+	domain_id_t d_domainid;
+	uint64_t d_pgtable_root_4K;
+	int64_t d_ref;
+	vmem_t *d_vmem;
+	struct amd_iommu_domain *d_prev;
+	struct amd_iommu_domain *d_next;
+} amd_iommu_domain_t;
+
+int amd_iommu_map_pa2va(amd_iommu_t *iommu, dev_info_t *rdip,
+    ddi_dma_attr_t *attrp, struct ddi_dma_req *dmareq,
+    uint64_t pa, uint64_t pa_sz, map_type_t type,
+    uint64_t *start_vap, int km_flags);
+int amd_iommu_unmap_va(amd_iommu_t *iommu, dev_info_t *rdip,
+    uint64_t va, uint64_t va_sz, map_type_t type);
+void amd_iommu_init_page_tables(amd_iommu_t *iommu);
+void amd_iommu_fini_page_tables(amd_iommu_t *iommu);
+void amd_iommu_set_passthru(amd_iommu_t *iommu, dev_info_t *rdip);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _AMD_IOMMU_PAGE_TABLES_H */
--- a/usr/src/uts/i86pc/io/intel_iommu.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/io/intel_iommu.c	Mon Sep 21 11:26:40 2009 -0400
@@ -92,10 +92,14 @@
 
 /*
  * internal variables
- *   iommu_state	- the list of iommu structures
+ *   iommu_states	- the list of iommu
+ *   domain_states	- the list of domain
+ *   rmrr_states	- the list of rmrr
  *   page_num		- the count of pages for iommu page tables
  */
 static list_t iommu_states;
+static list_t domain_states;
+static list_t rmrr_states;
 static uint_t page_num;
 
 /*
@@ -2042,6 +2046,8 @@
 		    offsetof(dvma_cache_node_t, node));
 	}
 
+	list_insert_tail(&domain_states, domain);
+
 	return (DDI_SUCCESS);
 }
 
@@ -2759,6 +2765,7 @@
 		if (list_is_empty(&(dmar_info->dmari_rmrr[i])))
 			break;
 		for_each_in_list(&(dmar_info->dmari_rmrr[i]), rmrr) {
+			list_insert_tail(&rmrr_states, rmrr);
 			build_single_rmrr_identity_map(rmrr);
 		}
 	}
@@ -3030,6 +3037,10 @@
 	 */
 	list_create(&iommu_states, sizeof (intel_iommu_state_t),
 	    offsetof(intel_iommu_state_t, node));
+	list_create(&domain_states, sizeof (dmar_domain_state_t),
+	    offsetof(dmar_domain_state_t, node));
+	list_create(&rmrr_states, sizeof (rmrr_info_t),
+	    offsetof(rmrr_info_t, node4states));
 
 	root_devinfo = ddi_root_node();
 	ASSERT(root_devinfo);
--- a/usr/src/uts/i86pc/os/cpuid_subr.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/os/cpuid_subr.c	Mon Sep 21 11:26:40 2009 -0400
@@ -67,36 +67,48 @@
  * Second index by (model & 0x3) for family 0fh
  * or CPUID bits for later families
  */
-static uint32_t amd_skts[4][4] = {
+static uint32_t amd_skts[4][8] = {
 	/*
 	 * Family 0xf revisions B through E
 	 */
 #define	A_SKTS_0			0
 	{
-		X86_SOCKET_754,		/* 0b00 */
-		X86_SOCKET_940,		/* 0b01 */
-		X86_SOCKET_754,		/* 0b10 */
-		X86_SOCKET_939		/* 0b11 */
+		X86_SOCKET_754,		/* 0b000 */
+		X86_SOCKET_940,		/* 0b001 */
+		X86_SOCKET_754,		/* 0b010 */
+		X86_SOCKET_939,		/* 0b011 */
+		X86_SOCKET_UNKNOWN,	/* 0b100 */
+		X86_SOCKET_UNKNOWN,	/* 0b101 */
+		X86_SOCKET_UNKNOWN,	/* 0b110 */
+		X86_SOCKET_UNKNOWN	/* 0b111 */
 	},
 	/*
 	 * Family 0xf revisions F and G
 	 */
 #define	A_SKTS_1			1
 	{
-		X86_SOCKET_S1g1,	/* 0b00 */
-		X86_SOCKET_F1207,	/* 0b01 */
-		X86_SOCKET_UNKNOWN,	/* 0b10 */
-		X86_SOCKET_AM2		/* 0b11 */
+		X86_SOCKET_S1g1,	/* 0b000 */
+		X86_SOCKET_F1207,	/* 0b001 */
+		X86_SOCKET_UNKNOWN,	/* 0b010 */
+		X86_SOCKET_AM2,		/* 0b011 */
+		X86_SOCKET_UNKNOWN,	/* 0b100 */
+		X86_SOCKET_UNKNOWN,	/* 0b101 */
+		X86_SOCKET_UNKNOWN,	/* 0b110 */
+		X86_SOCKET_UNKNOWN	/* 0b111 */
 	},
 	/*
 	 * Family 0x10
 	 */
 #define	A_SKTS_2			2
 	{
-		X86_SOCKET_F1207,	/* 0b00 */
-		X86_SOCKET_AM,		/* 0b01 */
-		X86_SOCKET_S1g3,	/* 0b10 */
-		X86_SOCKET_G34,		/* 0b11 */
+		X86_SOCKET_F1207,	/* 0b000 */
+		X86_SOCKET_AM,		/* 0b001 */
+		X86_SOCKET_S1g3,	/* 0b010 */
+		X86_SOCKET_G34,		/* 0b011 */
+		X86_SOCKET_ASB2,	/* 0b100 */
+		X86_SOCKET_C32,		/* 0b101 */
+		X86_SOCKET_UNKNOWN,	/* 0b110 */
+		X86_SOCKET_UNKNOWN	/* 0b111 */
 	},
 
 	/*
@@ -104,10 +116,14 @@
 	 */
 #define	A_SKTS_3			3
 	{
-		X86_SOCKET_UNKNOWN,	/* 0b00 */
-		X86_SOCKET_UNKNOWN,	/* 0b01 */
-		X86_SOCKET_S1g2,	/* 0b10 */
-		X86_SOCKET_UNKNOWN,	/* 0b11 */
+		X86_SOCKET_UNKNOWN,	/* 0b000 */
+		X86_SOCKET_UNKNOWN,	/* 0b001 */
+		X86_SOCKET_S1g2,	/* 0b010 */
+		X86_SOCKET_UNKNOWN,	/* 0b011 */
+		X86_SOCKET_UNKNOWN,	/* 0b100 */
+		X86_SOCKET_UNKNOWN,	/* 0b101 */
+		X86_SOCKET_UNKNOWN,	/* 0b110 */
+		X86_SOCKET_UNKNOWN	/* 0b111 */
 	}
 };
 
@@ -115,7 +131,7 @@
 	uint32_t	skt_code;
 	char		sktstr[16];
 };
-static struct amd_sktmap_s amd_sktmap[13] = {
+static struct amd_sktmap_s amd_sktmap[15] = {
 	{ X86_SOCKET_754,	"754" },
 	{ X86_SOCKET_939,	"939" },
 	{ X86_SOCKET_940,	"940" },
@@ -128,6 +144,8 @@
 	{ X86_SOCKET_AM2R2,	"AM2r2" },
 	{ X86_SOCKET_AM3,	"AM3" },
 	{ X86_SOCKET_G34,	"G34" },
+	{ X86_SOCKET_ASB2,	"ASB2" },
+	{ X86_SOCKET_C32,	"C32" },
 	{ X86_SOCKET_UNKNOWN,	"Unknown" }
 };
 
@@ -277,7 +295,7 @@
 			/* PkgType bits */
 			idx = BITX(cp.cp_ebx, 31, 28);
 
-			if (idx > 3) {
+			if (idx > 7) {
 				/* Reserved bits */
 				*skt_p = X86_SOCKET_UNKNOWN;
 			} else if (family == 0x10 &&
--- a/usr/src/uts/i86pc/os/fakebop.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/os/fakebop.c	Mon Sep 21 11:26:40 2009 -0400
@@ -124,7 +124,7 @@
 static int early_allocation = 1;
 
 int force_fastreboot = 0;
-int fastreboot_onpanic = 0;
+volatile int fastreboot_onpanic = 0;
 int post_fastreboot = 0;
 #ifdef	__xpv
 int fastreboot_capable = 0;
@@ -696,10 +696,17 @@
 
 		consoledev = outputdev + v_len + 1;
 		v_len = do_bsys_getproplen(NULL, "console");
-		if (v_len > 0)
+		if (v_len > 0) {
 			(void) do_bsys_getprop(NULL, "console", consoledev);
-		else
+			if (post_fastreboot &&
+			    strcmp(consoledev, "graphics") == 0) {
+				bsetprops("console", "text");
+				v_len = strlen("text");
+				bcopy("text", consoledev, v_len);
+			}
+		} else {
 			v_len = 0;
+		}
 		consoledev[v_len] = 0;
 		bcons_init2(inputdev, outputdev, consoledev);
 	} else {
@@ -1696,8 +1703,6 @@
 	HYPERVISOR_shared_info = (void *)xbootp->bi_shared_info;
 	xen_info = xbootp->bi_xen_start_info;
 #endif
-	bcons_init((void *)xbootp->bi_cmdline);
-	have_console = 1;
 
 #ifndef __xpv
 	if (*((uint32_t *)(FASTBOOT_SWTCH_PA + FASTBOOT_STACK_OFFSET)) ==
@@ -1707,6 +1712,9 @@
 	}
 #endif
 
+	bcons_init((void *)xbootp->bi_cmdline);
+	have_console = 1;
+
 	/*
 	 * enable debugging
 	 */
--- a/usr/src/uts/i86pc/os/fastboot.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/os/fastboot.c	Mon Sep 21 11:26:40 2009 -0400
@@ -136,6 +136,11 @@
 int reserve_mem_enabled = 1;
 
 /*
+ * Mutex to protect fastreboot_onpanic.
+ */
+kmutex_t fastreboot_config_mutex;
+
+/*
  * Amount of memory below PA 1G to reserve for constructing the multiboot
  * data structure and the page tables as we tend to run out of those
  * when more drivers are loaded.
@@ -868,7 +873,8 @@
 	int		is_retry = 0;
 	uint64_t	end_addr;
 
-	ASSERT(fastreboot_capable);
+	if (!fastreboot_capable)
+		return;
 
 	if (newkernel.fi_valid)
 		fastboot_free_newkernel(&newkernel);
@@ -1408,12 +1414,16 @@
 	if (!fastreboot_capable)
 		return;
 
+	mutex_enter(&fastreboot_config_mutex);
+
 	fastboot_get_bootprop();
 
 	if (fastreboot_onpanic)
 		fastboot_load_kernel(fastreboot_onpanic_cmdline);
 	else if (reserve_mem_enabled)
 		fastboot_reserve_mem(&newkernel);
+
+	mutex_exit(&fastreboot_config_mutex);
 }
 
 /*
@@ -1427,15 +1437,69 @@
 fastboot_update_config(const char *mdep)
 {
 	uint8_t boot_config = (uint8_t)*mdep;
-	int cur_fastreboot_onpanic = fastreboot_onpanic;
+	int cur_fastreboot_onpanic;
 
 	if (!fastreboot_capable)
 		return;
 
+	mutex_enter(&fastreboot_config_mutex);
+
+	cur_fastreboot_onpanic = fastreboot_onpanic;
 	fastreboot_onpanic = boot_config & UA_FASTREBOOT_ONPANIC;
+
 	if (fastreboot_onpanic && (!cur_fastreboot_onpanic ||
 	    !newkernel.fi_valid))
 		fastboot_load_kernel(fastreboot_onpanic_cmdline);
 	if (cur_fastreboot_onpanic && !fastreboot_onpanic)
 		fastboot_free_newkernel(&newkernel);
+
+	mutex_exit(&fastreboot_config_mutex);
 }
+
+/*
+ * This is the interface to be called by other kernel components to
+ * disable fastreboot_onpanic.
+ */
+void
+fastreboot_disable()
+{
+	uint8_t boot_config = (uint8_t)(~UA_FASTREBOOT_ONPANIC);
+	fastboot_update_config((const char *)&boot_config);
+}
+
+/*
+ * This is the interface to be called by fm_panic() in case FMA has diagnosed
+ * a terminal machine check exception.  It does not free up memory allocated
+ * for the backup kernel.  General disabling fastreboot_onpanic in a
+ * non-panicking situation must go through fastboot_update_config().
+ */
+void
+fastreboot_disable_highpil()
+{
+	fastreboot_onpanic = 0;
+}
+
+
+/*
+ * A simplified interface for uadmin to call to update the configuration
+ * setting and load a new kernel if necessary.
+ */
+void
+fastboot_update_and_load(int fcn, char *mdep)
+{
+	if (fcn != AD_FASTREBOOT) {
+		/*
+		 * If user has explicitly requested reboot to prom,
+		 * or uadmin(1M) was invoked with other functions,
+		 * don't try to fast reboot after dumping.
+		 */
+		fastreboot_disable();
+	}
+
+	mutex_enter(&fastreboot_config_mutex);
+
+	if (fastreboot_onpanic)
+		fastboot_load_kernel(mdep);
+
+	mutex_exit(&fastreboot_config_mutex);
+}
--- a/usr/src/uts/i86pc/os/mlsetup.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/os/mlsetup.c	Mon Sep 21 11:26:40 2009 -0400
@@ -49,10 +49,10 @@
 #include <sys/machsystm.h>
 #include <sys/ontrap.h>
 #include <sys/bootconf.h>
+#include <sys/boot_console.h>
 #include <sys/kdi_machimpl.h>
 #include <sys/archsystm.h>
 #include <sys/promif.h>
-#include <sys/bootconf.h>
 #include <sys/pci_cfgspace.h>
 #ifdef __xpv
 #include <sys/hypervisor.h>
@@ -78,6 +78,21 @@
 	0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf
 };
 
+/*
+ * Set console mode
+ */
+static void
+set_console_mode(uint8_t val)
+{
+	struct bop_regs rp = {0};
+
+	rp.eax.byte.ah = 0x0;
+	rp.eax.byte.al = val;
+	rp.ebx.word.bx = 0x0;
+
+	BOP_DOINT(bootops, 0x10, &rp);
+}
+
 
 /*
  * Setup routine called right before main(). Interposing this function
@@ -90,6 +105,8 @@
 	extern struct classfuncs sys_classfuncs;
 	extern disp_t cpu0_disp;
 	extern char t0stack[];
+	extern int post_fastreboot;
+	extern int console;
 
 	ASSERT_STACK_ALIGNED();
 
@@ -304,6 +321,13 @@
 		kdi_idt_sync();
 
 	/*
+	 * Explicitly set console to text mode (0x3) if this is a boot
+	 * post Fast Reboot, and the console is set to CONS_SCREEN_TEXT.
+	 */
+	if (post_fastreboot && console == CONS_SCREEN_TEXT)
+		set_console_mode(0x3);
+
+	/*
 	 * If requested (boot -d) drop into kmdb.
 	 *
 	 * This must be done after cpu_list_init() on the 64-bit kernel
--- a/usr/src/uts/i86pc/sys/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/sys/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -38,6 +38,7 @@
 
 HDRS=  \
 	acpidev.h	\
+	amd_iommu.h	\
 	asm_misc.h	\
 	clock.h		\
 	cram.h		\
--- a/usr/src/uts/i86pc/sys/amd_iommu.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/sys/amd_iommu.h	Mon Sep 21 11:26:40 2009 -0400
@@ -43,8 +43,11 @@
 	int aioms_nunits;			/* # of IOMMUs in function */
 } amd_iommu_state_t;
 
+#define	AMD_IOMMU_QUIESCE	(0)
+#define	AMD_IOMMU_TEARDOWN	(1)
+
 int amd_iommu_setup(dev_info_t *dip, amd_iommu_state_t *statep);
-int amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep);
+int amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep, int type);
 int amd_iommu_lookup_src_bdf(uint16_t bdf, uint16_t *src_bdfp);
 
 #endif	/* _KERNEL */
--- a/usr/src/uts/i86pc/sys/dmar_acpi.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/sys/dmar_acpi.h	Mon Sep 21 11:26:40 2009 -0400
@@ -160,6 +160,7 @@
  */
 typedef struct rmrr_info {
 	list_node_t	node;
+	list_node_t	node4states;
 	uint16_t	ri_segment;
 	uint64_t	ri_baseaddr;
 	uint64_t	ri_limiaddr;
--- a/usr/src/uts/i86pc/sys/fastboot.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/sys/fastboot.h	Mon Sep 21 11:26:40 2009 -0400
@@ -173,7 +173,7 @@
 extern int force_fastreboot;
 
 /* If set, fast reboot after panic. */
-extern int fastreboot_onpanic;
+extern volatile int fastreboot_onpanic;
 extern char fastreboot_onpanic_cmdline[FASTBOOT_SAVED_CMDLINE_LEN];
 
 #endif	/* _ASM */
--- a/usr/src/uts/i86pc/sys/intel_iommu.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/i86pc/sys/intel_iommu.h	Mon Sep 21 11:26:40 2009 -0400
@@ -145,20 +145,29 @@
 #define	IOMMU_CAP_GET_DWD(x)		(((x) >> 54) & 1)
 #define	IOMMU_CAP_GET_DRD(x)		(((x) >> 55) & 1)
 #define	IOMMU_CAP_GET_PSI(x)		(((x) >> 39) & 1)
+#define	IOMMU_CAP_GET_SPS(x)		(((x) >> 34) & 0xf)
+#define	IOMMU_CAP_GET_ISOCH(x)		(((x) >> 23) & 1)
+#define	IOMMU_CAP_GET_ZLR(x)		(((x) >> 22) & 1)
 #define	IOMMU_CAP_GET_MAMV(x)		(((x) >> 48) & 0x3f)
 #define	IOMMU_CAP_GET_CM(x)		(((x) >> 7) & 1)
+#define	IOMMU_CAP_GET_PHMR(x)		(((x) >> 6) & 1)
+#define	IOMMU_CAP_GET_PLMR(x)		(((x) >> 5) & 1)
 #define	IOMMU_CAP_GET_RWBF(x)		(((x) >> 4) & 1)
+#define	IOMMU_CAP_GET_AFL(x)		(((x) >> 3) & 1)
 #define	IOMMU_CAP_GET_FRO(x)		((((x) >> 24) & 0x3ff) * 16)
 #define	IOMMU_CAP_MGAW(x)		(((((uint64_t)x) >> 16) & 0x3f) + 1)
 #define	IOMMU_CAP_SAGAW(x)		(((x) >> 8) & 0x1f)
 #define	IOMMU_CAP_ND(x)			(1 << (((x) & 0x7) *2 + 4)) -1
 #define	IOMMU_ECAP_GET_IRO(x)		((((x) >> 8) & 0x3ff) << 4)
-#define	IOMMU_ECAP_GET_C(x)		((x) & 0x1)
 #define	IOMMU_ECAP_GET_MHMV(x)		((x >> 20) & 0xf)
+#define	IOMMU_ECAP_GET_SC(x)		((x) & 0x80)
+#define	IOMMU_ECAP_GET_PT(x)		((x) & 0x40)
+#define	IOMMU_ECAP_GET_CH(x)		((x) & 0x20)
 #define	IOMMU_ECAP_GET_EIM(x)		((x) & 0x10)
 #define	IOMMU_ECAP_GET_IR(x)		((x) & 0x8)
 #define	IOMMU_ECAP_GET_DI(x)		((x) & 0x4)
 #define	IOMMU_ECAP_GET_QI(x)		((x) & 0x2)
+#define	IOMMU_ECAP_GET_C(x)		((x) & 0x1)
 
 
 /* iotlb invalidation */
@@ -343,7 +352,7 @@
 
 typedef enum {
 	IEC_INV_GLOBAL = 0,
-	IEC_INV_INDEX,
+	IEC_INV_INDEX
 } iec_inv_g_t;
 
 /*
@@ -523,6 +532,7 @@
  * dm_identity		- does this domain identity mapped
  */
 typedef struct dmar_domain_state {
+	list_node_t		node;
 	uint_t			dm_domain_id;
 	intel_iommu_state_t	*dm_iommu;
 	vmem_t			*dm_dvma_map;
--- a/usr/src/uts/intel/Makefile.files	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/Makefile.files	Mon Sep 21 11:26:40 2009 -0400
@@ -252,17 +252,6 @@
 AMR_OBJS = amr.o
 
 #
-#	AMD_IOMMU module
-#
-AMD_IOMMU_OBJS = 		\
-	amd_iommu.o		\
-	amd_iommu_impl.o	\
-	amd_iommu_acpi.o	\
-	amd_iommu_cmd.o		\
-	amd_iommu_log.o		\
-	amd_iommu_page_tables.o	
-
-#
 #	IOMMULIB module
 #
 IOMMULIB_OBJS = iommulib.o
--- a/usr/src/uts/intel/Makefile.intel.shared	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/Makefile.intel.shared	Mon Sep 21 11:26:40 2009 -0400
@@ -206,6 +206,7 @@
 DRV_KMODS	+= audiols
 DRV_KMODS	+= audiop16x
 DRV_KMODS	+= audiopci
+DRV_KMODS	+= audiosolo
 DRV_KMODS	+= audiots
 DRV_KMODS	+= audiovia823x
 DRV_KMODS_32	+= audiovia97
@@ -400,7 +401,6 @@
 DRV_KMODS	+= rtls
 DRV_KMODS	+= sfe
 DRV_KMODS	+= amd8111s
-DRV_KMODS	+= amd_iommu
 DRV_KMODS	+= igb
 DRV_KMODS	+= ixgbe
 DRV_KMODS	+= vr
--- a/usr/src/uts/intel/Makefile.rules	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/Makefile.rules	Mon Sep 21 11:26:40 2009 -0400
@@ -153,10 +153,6 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
-$(OBJS_DIR)/%.o:		$(UTSBASE)/intel/io/amd_iommu/%.c
-	$(COMPILE.c) -o $@ $<
-	$(CTFCONVERT_O)
-
 $(OBJS_DIR)/%.o:		$(UTSBASE)/intel/io/amr/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -394,9 +390,6 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/intel/io/amd8111s/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
-$(LINTS_DIR)/%.ln:		$(UTSBASE)/intel/io/amd_iommu/%.c
-	@($(LHEAD) $(LINT.c) $< $(LTAIL))
-
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/intel/io/amr/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- a/usr/src/uts/intel/amd_iommu/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#	This Makefile drives production of the amd_iommu driver kernel module.
-#
-#	intel implementation architecture dependent
-#
-
-#
-#	Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE	= ../..
-
-#
-#	Define the module and object file sets.
-#
-MODULE		= amd_iommu
-OBJECTS		= $(AMD_IOMMU_OBJS:%=$(OBJS_DIR)/%)
-LINTS		= $(AMD_IOMMU_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR     = $(UTSBASE)/intel/io/amd_iommu
-
-#
-#	Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-#	Define targets
-#
-ALL_TARGET	= $(BINARY) $(SRC_CONFILE)
-LINT_TARGET	= $(MODULE).lint
-INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
-
-#
-# depends on misc/iommulib and misc/acpica
-#
-LDFLAGS         += -dy -Nmisc/iommulib -Nmisc/acpica
-
-#
-#	Default build targets.
-#
-.KEEP_STATE:
-
-def:		$(DEF_DEPS)
-
-all:		$(ALL_DEPS)
-
-clean:		$(CLEAN_DEPS)
-
-clobber:	$(CLOBBER_DEPS)
-
-lint:		$(LINT_DEPS)
-
-modlintlib:	$(MODLINTLIB_DEPS)
-
-clean.lint:	$(CLEAN_LINT_DEPS)
-
-install:	$(INSTALL_DEPS) $(CONF_INSTALL_DEPS)
-
-#
-#	Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/intel/audiosolo/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -0,0 +1,81 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# uts/intel/audiosolo/Makefile
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+#	This makefile drives the production of the audiosolo driver.
+#
+
+#
+#	Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+#	Define the module and object file sets.
+#
+MODULE		= audiosolo
+OBJECTS		= $(AUDIOSOLO_OBJS:%=$(OBJS_DIR)/%)
+LINTS		= $(AUDIOSOLO_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
+
+#
+#	Include common rules.
+#
+include $(UTSBASE)/intel/Makefile.intel
+
+#
+#	Define targets
+#
+ALL_TARGET	= $(BINARY)
+LINT_TARGET	= $(MODULE).lint
+INSTALL_TARGET	= $(BINARY) $(ROOTMODULE)
+
+LDFLAGS		+= -dy -Ndrv/audio
+
+#
+#	Default build targets.
+#
+.KEEP_STATE:
+
+def:		$(DEF_DEPS)
+
+all:		$(ALL_DEPS)
+
+clean:		$(CLEAN_DEPS)
+
+clobber:	$(CLOBBER_DEPS)
+
+lint:		$(LINT_DEPS)
+
+modlintlib:	$(MODLINTLIB_DEPS)
+
+clean.lint:	$(CLEAN_LINT_DEPS)
+
+install:	$(INSTALL_DEPS)
+
+#
+#	Include common targets.
+#
+include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,440 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/errno.h>
-#include <sys/open.h>
-#include <sys/stat.h>
-#include <sys/cred.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/devops.h>
-#include <sys/ddi.h>
-
-#include <sys/amd_iommu.h>
-#include "amd_iommu_impl.h"
-#include "amd_iommu_acpi.h"
-
-
-#define	AMD_IOMMU_MINOR2INST(x)	(x)
-#define	AMD_IOMMU_INST2MINOR(x)	(x)
-#define	AMD_IOMMU_NODETYPE	"ddi_iommu"
-#define	AMD_IOMMU_MINOR_NAME	"amd-iommu"
-
-static int amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
-    void **result);
-static int amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
-static int amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
-static int amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp);
-static int amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp);
-static int amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
-    cred_t *credp, int *rvalp);
-
-static struct cb_ops amd_iommu_cb_ops = {
-	amd_iommu_open,		/* cb_open */
-	amd_iommu_close,	/* cb_close */
-	nodev,			/* cb_strategy */
-	nodev,			/* cb_print */
-	nodev,			/* cb_dump */
-	nodev,			/* cb_read */
-	nodev,			/* cb_write */
-	amd_iommu_ioctl,	/* cb_ioctl */
-	nodev,			/* cb_devmap */
-	nodev,			/* cb_mmap */
-	nodev,			/* cb_segmap */
-	nochpoll,		/* cb_chpoll */
-	ddi_prop_op,		/* cb_prop_op */
-	NULL,			/* cb_str */
-	D_NEW | D_MP,		/* cb_flag */
-	CB_REV,			/* cb_rev */
-	nodev,			/* cb_aread */
-	nodev			/* cb_awrite */
-};
-
-static struct dev_ops amd_iommu_dev_ops = {
-	DEVO_REV,		/* devo_rev */
-	0,			/* devo_refcnt */
-	amd_iommu_getinfo,	/* devo_getinfo */
-	nulldev,		/* devo_identify */
-	nulldev,		/* devo_probe */
-	amd_iommu_attach,	/* devo_attach */
-	amd_iommu_detach,	/* devo_detach */
-	nodev,			/* devo_reset */
-	&amd_iommu_cb_ops,	/* devo_cb_ops */
-	NULL,			/* devo_bus_ops */
-	nulldev			/* devo_power */
-};
-
-static struct modldrv modldrv = {
-	&mod_driverops,
-	"AMD IOMMU 0.1",
-	&amd_iommu_dev_ops
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modldrv,
-	NULL
-};
-
-amd_iommu_debug_t amd_iommu_debug;
-kmutex_t amd_iommu_global_lock;
-const char *amd_iommu_modname = "amd_iommu";
-amd_iommu_alias_t **amd_iommu_alias;
-amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
-static void *amd_iommu_statep;
-int amd_iommu_64bit_bug;
-int amd_iommu_unity_map;
-int amd_iommu_no_RW_perms;
-int amd_iommu_no_unmap;
-int amd_iommu_pageva_inval_all;
-int amd_iommu_disable;		/* disable IOMMU */
-char *amd_iommu_disable_list;	/* list of drivers bypassing IOMMU */
-
-int
-_init(void)
-{
-	int error = ENOTSUP;
-
-#if defined(__amd64) && !defined(__xpv)
-
-	error = ddi_soft_state_init(&amd_iommu_statep,
-	    sizeof (struct amd_iommu_state), 1);
-	if (error) {
-		cmn_err(CE_WARN, "%s: _init: failed to init soft state.",
-		    amd_iommu_modname);
-		return (error);
-	}
-
-	if (amd_iommu_acpi_init() != DDI_SUCCESS) {
-		if (amd_iommu_debug) {
-			cmn_err(CE_WARN, "%s: _init: ACPI init failed.",
-			    amd_iommu_modname);
-		}
-		ddi_soft_state_fini(&amd_iommu_statep);
-		return (ENOTSUP);
-	}
-
-	amd_iommu_read_boot_props();
-
-	if (amd_iommu_page_table_hash_init(&amd_iommu_page_table_hash)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: _init: Page table hash init failed.",
-		    amd_iommu_modname);
-		if (amd_iommu_disable_list) {
-			kmem_free(amd_iommu_disable_list,
-			    strlen(amd_iommu_disable_list) + 1);
-			amd_iommu_disable_list = NULL;
-		}
-		amd_iommu_acpi_fini();
-		ddi_soft_state_fini(&amd_iommu_statep);
-		amd_iommu_statep = NULL;
-		return (EFAULT);
-	}
-
-	error = mod_install(&modlinkage);
-	if (error) {
-		cmn_err(CE_WARN, "%s: _init: mod_install failed.",
-		    amd_iommu_modname);
-		amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
-		if (amd_iommu_disable_list) {
-			kmem_free(amd_iommu_disable_list,
-			    strlen(amd_iommu_disable_list) + 1);
-			amd_iommu_disable_list = NULL;
-		}
-		amd_iommu_acpi_fini();
-		ddi_soft_state_fini(&amd_iommu_statep);
-		amd_iommu_statep = NULL;
-		return (error);
-	}
-	error = 0;
-#endif
-
-	return (error);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-	return (mod_info(&modlinkage, modinfop));
-}
-
-int
-_fini(void)
-{
-	int error;
-
-	error = mod_remove(&modlinkage);
-	if (error)
-		return (error);
-
-	amd_iommu_page_table_hash_fini(&amd_iommu_page_table_hash);
-	if (amd_iommu_disable_list) {
-		kmem_free(amd_iommu_disable_list,
-		    strlen(amd_iommu_disable_list) + 1);
-		amd_iommu_disable_list = NULL;
-	}
-	amd_iommu_acpi_fini();
-	ddi_soft_state_fini(&amd_iommu_statep);
-	amd_iommu_statep = NULL;
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
-{
-	struct amd_iommu_state *statep;
-
-	ASSERT(result);
-
-	*result = NULL;
-
-	switch (cmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		statep = ddi_get_soft_state(amd_iommu_statep,
-		    AMD_IOMMU_MINOR2INST(getminor((dev_t)arg)));
-		if (statep) {
-			*result = statep->aioms_devi;
-			return (DDI_SUCCESS);
-		}
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*result = (void *)(uintptr_t)
-		    AMD_IOMMU_MINOR2INST(getminor((dev_t)arg));
-		return (DDI_SUCCESS);
-	}
-
-	return (DDI_FAILURE);
-}
-
-static int
-amd_iommu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	struct amd_iommu_state *statep;
-
-	ASSERT(instance >= 0);
-	ASSERT(driver);
-
-	switch (cmd) {
-	case DDI_ATTACH:
-		if (ddi_soft_state_zalloc(amd_iommu_statep, instance)
-		    != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "Unable to allocate soft state for "
-			    "%s%d", driver, instance);
-			return (DDI_FAILURE);
-		}
-
-		statep = ddi_get_soft_state(amd_iommu_statep, instance);
-		if (statep == NULL) {
-			cmn_err(CE_WARN, "Unable to get soft state for "
-			    "%s%d", driver, instance);
-			ddi_soft_state_free(amd_iommu_statep, instance);
-			return (DDI_FAILURE);
-		}
-
-		if (ddi_create_minor_node(dip, AMD_IOMMU_MINOR_NAME, S_IFCHR,
-		    AMD_IOMMU_INST2MINOR(instance), AMD_IOMMU_NODETYPE,
-		    0) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "Unable to create minor node for "
-			    "%s%d", driver, instance);
-			ddi_remove_minor_node(dip, NULL);
-			ddi_soft_state_free(amd_iommu_statep, instance);
-			return (DDI_FAILURE);
-		}
-
-		statep->aioms_devi = dip;
-		statep->aioms_instance = instance;
-		statep->aioms_iommu_start = NULL;
-		statep->aioms_iommu_end = NULL;
-
-		amd_iommu_lookup_conf_props(dip);
-
-		if (amd_iommu_disable_list) {
-			cmn_err(CE_NOTE, "AMD IOMMU disabled for the following"
-			    " drivers:\n%s", amd_iommu_disable_list);
-		}
-
-		if (amd_iommu_disable) {
-			cmn_err(CE_NOTE, "AMD IOMMU disabled by user");
-		} else if (amd_iommu_setup(dip, statep) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "Unable to initialize AMD IOMMU "
-			    "%s%d", driver, instance);
-			ddi_remove_minor_node(dip, NULL);
-			ddi_soft_state_free(amd_iommu_statep, instance);
-			return (DDI_FAILURE);
-		}
-
-		ddi_report_dev(dip);
-
-		return (DDI_SUCCESS);
-
-	case DDI_RESUME:
-		return (DDI_SUCCESS);
-	default:
-		return (DDI_FAILURE);
-	}
-}
-
-static int
-amd_iommu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	struct amd_iommu_state *statep;
-
-	ASSERT(instance >= 0);
-	ASSERT(driver);
-
-	switch (cmd) {
-	case DDI_DETACH:
-		statep = ddi_get_soft_state(amd_iommu_statep, instance);
-		if (statep == NULL) {
-			cmn_err(CE_WARN, "%s%d: Cannot get soft state",
-			    driver, instance);
-			return (DDI_FAILURE);
-		}
-		return (DDI_FAILURE);
-	case DDI_SUSPEND:
-		return (DDI_SUCCESS);
-	default:
-		return (DDI_FAILURE);
-	}
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_open(dev_t *devp, int flag, int otyp, cred_t *credp)
-{
-	int instance = AMD_IOMMU_MINOR2INST(getminor(*devp));
-	struct amd_iommu_state *statep;
-	const char *f = "amd_iommu_open";
-
-	if (instance < 0) {
-		cmn_err(CE_WARN, "%s: invalid instance %d",
-		    f, instance);
-		return (ENXIO);
-	}
-
-	if (!(flag & (FREAD|FWRITE))) {
-		cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
-		return (EINVAL);
-	}
-
-	if (otyp != OTYP_CHR) {
-		cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
-		return (EINVAL);
-	}
-
-	statep = ddi_get_soft_state(amd_iommu_statep, instance);
-	if (statep == NULL) {
-		cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
-		    f, instance);
-		return (ENXIO);
-	}
-
-	ASSERT(statep->aioms_instance == instance);
-
-	return (0);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_close(dev_t dev, int flag, int otyp, cred_t *credp)
-{
-	int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
-	struct amd_iommu_state *statep;
-	const char *f = "amd_iommu_close";
-
-	if (instance < 0) {
-		cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
-		return (ENXIO);
-	}
-
-	if (!(flag & (FREAD|FWRITE))) {
-		cmn_err(CE_WARN, "%s: invalid flags %d", f, flag);
-		return (EINVAL);
-	}
-
-	if (otyp != OTYP_CHR) {
-		cmn_err(CE_WARN, "%s: invalid otyp %d", f, otyp);
-		return (EINVAL);
-	}
-
-	statep = ddi_get_soft_state(amd_iommu_statep, instance);
-	if (statep == NULL) {
-		cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
-		    f, instance);
-		return (ENXIO);
-	}
-
-	ASSERT(statep->aioms_instance == instance);
-	return (0);
-
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
-    int *rvalp)
-{
-	int instance = AMD_IOMMU_MINOR2INST(getminor(dev));
-	struct amd_iommu_state *statep;
-	const char *f = "amd_iommu_ioctl";
-
-	ASSERT(*rvalp);
-
-	if (instance < 0) {
-		cmn_err(CE_WARN, "%s: invalid instance %d", f, instance);
-		return (ENXIO);
-	}
-
-
-	if (!(mode & (FREAD|FWRITE))) {
-		cmn_err(CE_WARN, "%s: invalid mode %d", f, mode);
-		return (EINVAL);
-	}
-
-	if (mode & FKIOCTL) {
-		cmn_err(CE_WARN, "%s: FKIOCTL unsupported mode %d", f, mode);
-		return (EINVAL);
-	}
-
-	statep = ddi_get_soft_state(amd_iommu_statep, instance);
-	if (statep == NULL) {
-		cmn_err(CE_WARN, "%s: cannot get soft state: instance %d",
-		    f, instance);
-		return (ENXIO);
-	}
-
-	ASSERT(statep->aioms_instance == instance);
-
-	return (ENOTTY);
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu.conf	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-#
-# To enable IOMMU set this to "yes" and rebuild boot archive
-amd-iommu="yes";
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_acpi.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,951 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include "amd_iommu_acpi.h"
-#include "amd_iommu_impl.h"
-
-static int create_acpi_hash(amd_iommu_acpi_t *acpi);
-static void amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp);
-
-static void dump_acpi_aliases(void);
-
-
-/*
- * Globals
- */
-static amd_iommu_acpi_global_t *amd_iommu_acpi_global;
-static amd_iommu_acpi_ivhd_t **amd_iommu_acpi_ivhd_hash;
-static amd_iommu_acpi_ivmd_t **amd_iommu_acpi_ivmd_hash;
-
-static int
-type_byte_size(char *cp)
-{
-	uint8_t type8 = *((uint8_t *)cp);
-	uint8_t len_bits;
-
-	len_bits = AMD_IOMMU_REG_GET8(&type8, AMD_IOMMU_ACPI_DEVENTRY_LEN);
-
-	switch (len_bits) {
-	case 0:
-			return (4);
-	case 1:
-			return (8);
-	case 2:
-			return (16);
-	case 3:
-			return (32);
-	default:
-			cmn_err(CE_WARN, "%s: Invalid deventry len: %d",
-			    amd_iommu_modname, len_bits);
-			return (len_bits);
-	}
-	/*NOTREACHED*/
-}
-
-static void
-process_4byte_deventry(ivhd_container_t *c, char *cp)
-{
-	int entry_type = *((uint8_t *)cp);
-	ivhd_deventry_t deventry = {0};
-	ivhd_deventry_t *devp;
-	uint8_t datsetting8;
-	align_16_t al = {0};
-	int i;
-
-	/* 4 byte entry */
-	deventry.idev_len = 4;
-	deventry.idev_deviceid = -1;
-	deventry.idev_src_deviceid = -1;
-
-	for (i = 0; i < 2; i++) {
-		al.ent8[i] = *((uint8_t *)&cp[i + 1]);
-	}
-
-	switch (entry_type) {
-	case 1:
-		deventry.idev_type = DEVENTRY_ALL;
-		break;
-	case 2:
-		deventry.idev_type = DEVENTRY_SELECT;
-		deventry.idev_deviceid = al.ent16;
-		break;
-	case 3:
-		deventry.idev_type = DEVENTRY_RANGE;
-		deventry.idev_deviceid = al.ent16;
-		break;
-	case 4:
-		deventry.idev_type = DEVENTRY_RANGE_END;
-		deventry.idev_deviceid = al.ent16;
-		ASSERT(cp[3] == 0);
-		break;
-	case 0:
-		ASSERT(al.ent16 == 0);
-		ASSERT(cp[3] == 0);
-	default:
-		return;
-	}
-
-
-	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
-	*devp = deventry;
-
-	if (c->ivhdc_first_deventry == NULL)
-		c->ivhdc_first_deventry =  devp;
-	else
-		c->ivhdc_last_deventry->idev_next = devp;
-
-	c->ivhdc_last_deventry = devp;
-
-	if (entry_type == 4)
-		return;
-
-	datsetting8 = (*((uint8_t *)&cp[3]));
-
-	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_LINT1PASS);
-
-	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_LINT0PASS);
-
-	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_SYSMGT);
-
-	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_DATRSV) == 0);
-
-	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_NMIPASS);
-
-	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_EXTINTPASS);
-
-	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_INITPASS);
-}
-
-static void
-process_8byte_deventry(ivhd_container_t *c, char *cp)
-{
-	uint8_t datsetting8;
-	int entry_type = (uint8_t)*cp;
-	ivhd_deventry_t deventry = {0};
-	ivhd_deventry_t *devp;
-	align_16_t al1 = {0};
-	align_16_t al2 = {0};
-	align_32_t al3 = {0};
-	int i;
-
-	/* Length is 8 bytes */
-	deventry.idev_len = 8;
-	deventry.idev_deviceid = -1;
-	deventry.idev_src_deviceid = -1;
-
-	for (i = 0; i < 2; i++) {
-		al1.ent8[i] = *((uint8_t *)&cp[i+1]);
-		al2.ent8[i] = *((uint8_t *)&cp[i+5]);
-	}
-
-	datsetting8 = *((uint8_t *)&cp[3]);
-
-	switch (entry_type) {
-	case 66:
-		deventry.idev_type = DEVENTRY_ALIAS_SELECT;
-		deventry.idev_deviceid = al1.ent16;
-		deventry.idev_src_deviceid = al2.ent16;
-		ASSERT(cp[4] == 0);
-		ASSERT(cp[7] == 0);
-		break;
-	case 67:
-		deventry.idev_type = DEVENTRY_ALIAS_RANGE;
-		deventry.idev_deviceid = al1.ent16;
-		deventry.idev_src_deviceid = al2.ent16;
-		ASSERT(cp[4] == 0);
-		ASSERT(cp[7] == 0);
-		break;
-	case 70:
-		deventry.idev_type = DEVENTRY_EXTENDED_SELECT;
-		deventry.idev_deviceid = al1.ent16;
-		break;
-	case 71:
-		deventry.idev_type = DEVENTRY_EXTENDED_RANGE;
-		deventry.idev_deviceid = al1.ent16;
-		break;
-	case 72:
-		deventry.idev_type = DEVENTRY_SPECIAL_DEVICE;
-		ASSERT(al1.ent16 == 0);
-		deventry.idev_deviceid = -1;
-		deventry.idev_handle = cp[4];
-		deventry.idev_variety = cp[7];
-		deventry.idev_src_deviceid = al2.ent16;
-	default:
-#ifdef BROKEN_ASSERT
-		for (i = 0; i < 7; i++) {
-			ASSERT(cp[i] == 0);
-		}
-#endif
-		return;
-	}
-
-
-	devp = kmem_alloc(sizeof (ivhd_deventry_t), KM_SLEEP);
-	*devp = deventry;
-
-	if (c->ivhdc_first_deventry == NULL)
-		c->ivhdc_first_deventry =  devp;
-	else
-		c->ivhdc_last_deventry->idev_next = devp;
-
-	c->ivhdc_last_deventry = devp;
-
-	devp->idev_Lint1Pass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_LINT1PASS);
-
-	devp->idev_Lint0Pass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_LINT0PASS);
-
-	devp->idev_SysMgt = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_SYSMGT);
-
-	ASSERT(AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_DATRSV) == 0);
-
-	devp->idev_NMIPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_NMIPASS);
-
-	devp->idev_ExtIntPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_EXTINTPASS);
-
-	devp->idev_INITPass = AMD_IOMMU_REG_GET8(&datsetting8,
-	    AMD_IOMMU_ACPI_INITPASS);
-
-	if (entry_type != 70 && entry_type != 71) {
-		return;
-	}
-
-	/* Type 70 and 71 */
-	for (i = 0; i < 4; i++) {
-		al3.ent8[i] = *((uint8_t *)&cp[i+4]);
-	}
-
-	devp->idev_AtsDisabled = AMD_IOMMU_REG_GET8(&al3.ent32,
-	    AMD_IOMMU_ACPI_ATSDISABLED);
-
-	ASSERT(AMD_IOMMU_REG_GET8(&al3.ent32, AMD_IOMMU_ACPI_EXTDATRSV) == 0);
-}
-
-static void
-process_ivhd(amd_iommu_acpi_t *acpi, ivhd_t *ivhdp)
-{
-	ivhd_container_t *c;
-	caddr_t ivhd_end;
-	caddr_t ivhd_tot_end;
-	caddr_t cp;
-
-	ASSERT(ivhdp->ivhd_type == 0x10);
-
-	c = kmem_zalloc(sizeof (ivhd_container_t), KM_SLEEP);
-	c->ivhdc_ivhd = kmem_alloc(sizeof (ivhd_t), KM_SLEEP);
-	*(c->ivhdc_ivhd) = *ivhdp;
-
-	if (acpi->acp_first_ivhdc == NULL)
-		acpi->acp_first_ivhdc = c;
-	else
-		acpi->acp_last_ivhdc->ivhdc_next = c;
-
-	acpi->acp_last_ivhdc = c;
-
-	ivhd_end = (caddr_t)ivhdp + sizeof (ivhd_t);
-	ivhd_tot_end = (caddr_t)ivhdp + ivhdp->ivhd_len;
-
-	for (cp = ivhd_end; cp < ivhd_tot_end; cp += type_byte_size(cp)) {
-		/* 16 byte and 32 byte size are currently reserved */
-		switch (type_byte_size(cp)) {
-		case 4:
-			process_4byte_deventry(c, cp);
-			break;
-		case 8:
-			process_8byte_deventry(c, cp);
-			break;
-		case 16:
-		case 32:
-			/* Reserved */
-			break;
-		default:
-			cmn_err(CE_WARN, "%s: unsupported length for device "
-			    "entry in ACPI IVRS table's IVHD entry",
-			    amd_iommu_modname);
-			break;
-		}
-	}
-}
-
-static void
-process_ivmd(amd_iommu_acpi_t *acpi, ivmd_t *ivmdp)
-{
-	ivmd_container_t *c;
-
-	ASSERT(ivmdp->ivmd_type != 0x10);
-
-	c = kmem_zalloc(sizeof (ivmd_container_t), KM_SLEEP);
-	c->ivmdc_ivmd = kmem_alloc(sizeof (ivmd_t), KM_SLEEP);
-	*(c->ivmdc_ivmd) = *ivmdp;
-
-	if (acpi->acp_first_ivmdc == NULL)
-		acpi->acp_first_ivmdc = c;
-	else
-		acpi->acp_last_ivmdc->ivmdc_next = c;
-
-	acpi->acp_last_ivmdc = c;
-}
-
-int
-amd_iommu_acpi_init(void)
-{
-	ivrs_t *ivrsp;
-	caddr_t ivrsp_end;
-	caddr_t table_end;
-	caddr_t cp;
-	uint8_t type8;
-	amd_iommu_acpi_t *acpi;
-	align_ivhd_t al_vhd = {0};
-	align_ivmd_t al_vmd = {0};
-
-	if (AcpiGetTable(IVRS_SIG, 1, (ACPI_TABLE_HEADER **)&ivrsp) != AE_OK) {
-		cmn_err(CE_NOTE, "!amd_iommu: No AMD IOMMU ACPI IVRS table");
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Reserved field must be 0
-	 */
-	ASSERT(ivrsp->ivrs_resv == 0);
-
-	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
-	    AMD_IOMMU_ACPI_IVINFO_RSV1) == 0);
-	ASSERT(AMD_IOMMU_REG_GET32(&ivrsp->ivrs_ivinfo,
-	    AMD_IOMMU_ACPI_IVINFO_RSV2) == 0);
-
-	ivrsp_end = (caddr_t)ivrsp + sizeof (struct ivrs);
-	table_end = (caddr_t)ivrsp + ivrsp->ivrs_hdr.Length;
-
-	acpi = kmem_zalloc(sizeof (amd_iommu_acpi_t), KM_SLEEP);
-	acpi->acp_ivrs = kmem_alloc(sizeof (ivrs_t), KM_SLEEP);
-	*(acpi->acp_ivrs) = *ivrsp;
-
-	for (cp = ivrsp_end; cp < table_end; cp += (al_vhd.ivhdp)->ivhd_len) {
-		al_vhd.cp = cp;
-		if (al_vhd.ivhdp->ivhd_type == 0x10)
-			process_ivhd(acpi, al_vhd.ivhdp);
-	}
-
-	for (cp = ivrsp_end; cp < table_end; cp += (al_vmd.ivmdp)->ivmd_len) {
-		al_vmd.cp = cp;
-		type8 = al_vmd.ivmdp->ivmd_type;
-		if (type8 == 0x20 || type8 == 0x21 || type8 == 0x22)
-			process_ivmd(acpi, al_vmd.ivmdp);
-	}
-
-	if (create_acpi_hash(acpi) != DDI_SUCCESS) {
-		return (DDI_FAILURE);
-	}
-
-	amd_iommu_acpi_table_fini(&acpi);
-
-	ASSERT(acpi == NULL);
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_ACPI) {
-		dump_acpi_aliases();
-		debug_enter("dump");
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static ivhd_deventry_t *
-free_ivhd_deventry(ivhd_deventry_t *devp)
-{
-	ivhd_deventry_t *next = devp->idev_next;
-
-	kmem_free(devp, sizeof (ivhd_deventry_t));
-
-	return (next);
-}
-
-static ivhd_container_t *
-free_ivhd_container(ivhd_container_t *ivhdcp)
-{
-	ivhd_container_t *next = ivhdcp->ivhdc_next;
-	ivhd_deventry_t *devp;
-
-	for (devp = ivhdcp->ivhdc_first_deventry; devp; ) {
-		devp = free_ivhd_deventry(devp);
-	}
-
-	kmem_free(ivhdcp->ivhdc_ivhd, sizeof (ivhd_t));
-	kmem_free(ivhdcp, sizeof (ivhd_container_t));
-
-	return (next);
-}
-
-static ivmd_container_t *
-free_ivmd_container(ivmd_container_t *ivmdcp)
-{
-	ivmd_container_t *next = ivmdcp->ivmdc_next;
-
-	kmem_free(ivmdcp->ivmdc_ivmd, sizeof (ivmd_t));
-	kmem_free(ivmdcp, sizeof (ivmd_container_t));
-
-	return (next);
-}
-
-void
-amd_iommu_acpi_fini(void)
-{
-}
-
-/*
- * TODO: Do we need to free the ACPI table for om GetFirmwareTable()
- */
-static void
-amd_iommu_acpi_table_fini(amd_iommu_acpi_t **acpipp)
-{
-	amd_iommu_acpi_t *acpi = *acpipp;
-	ivhd_container_t *ivhdcp;
-	ivmd_container_t *ivmdcp;
-
-	ASSERT(acpi);
-
-	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp; ) {
-		ivhdcp = free_ivhd_container(ivhdcp);
-	}
-	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp; ) {
-		ivmdcp = free_ivmd_container(ivmdcp);
-	}
-
-	kmem_free(acpi->acp_ivrs, sizeof (struct ivrs));
-	kmem_free(acpi, sizeof (amd_iommu_acpi_t));
-
-	*acpipp = NULL;
-}
-
-static uint16_t
-deviceid_hashfn(uint16_t deviceid)
-{
-	return (deviceid % AMD_IOMMU_ACPI_INFO_HASH_SZ);
-}
-
-static void
-add_deventry_info(ivhd_t *ivhdp, ivhd_deventry_t *deventry,
-    amd_iommu_acpi_ivhd_t **hash)
-{
-	static amd_iommu_acpi_ivhd_t *last;
-	amd_iommu_acpi_ivhd_t *acpi_ivhdp;
-	uint8_t uint8_flags;
-	uint16_t uint16_info;
-	uint16_t idx;
-
-	if (deventry->idev_type == DEVENTRY_RANGE_END) {
-		ASSERT(last);
-		acpi_ivhdp = last;
-		last = NULL;
-		ASSERT(acpi_ivhdp->ach_dev_type == DEVENTRY_RANGE ||
-		    acpi_ivhdp->ach_dev_type == DEVENTRY_ALIAS_RANGE ||
-		    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE);
-		ASSERT(acpi_ivhdp->ach_deviceid_end == -1);
-		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
-		/* TODO ASSERT data is 0 */
-		return;
-	}
-
-	ASSERT(last == NULL);
-	acpi_ivhdp = kmem_zalloc(sizeof (*acpi_ivhdp), KM_SLEEP);
-
-	uint8_flags = ivhdp->ivhd_flags;
-
-#ifdef BROKEN_ASSERT
-	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_RSV) == 0);
-#endif
-
-	acpi_ivhdp->ach_IotlbSup = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP);
-	acpi_ivhdp->ach_Isoc = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC);
-	acpi_ivhdp->ach_ResPassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW);
-	acpi_ivhdp->ach_PassPW = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW);
-	acpi_ivhdp->ach_HtTunEn = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN);
-
-	/* IVHD fields */
-	acpi_ivhdp->ach_IOMMU_deviceid = ivhdp->ivhd_deviceid;
-	acpi_ivhdp->ach_IOMMU_cap_off = ivhdp->ivhd_cap_off;
-	acpi_ivhdp->ach_IOMMU_reg_base = ivhdp->ivhd_reg_base;
-	acpi_ivhdp->ach_IOMMU_pci_seg = ivhdp->ivhd_pci_seg;
-
-	/* IVHD IOMMU info fields */
-	uint16_info = ivhdp->ivhd_iommu_info;
-
-#ifdef BROKEN_ASSERT
-	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
-	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV1) == 0);
-#endif
-
-	acpi_ivhdp->ach_IOMMU_UnitID = AMD_IOMMU_REG_GET16(&uint16_info,
-	    AMD_IOMMU_ACPI_IOMMU_INFO_UNITID);
-	ASSERT(AMD_IOMMU_REG_GET16(&uint16_info,
-	    AMD_IOMMU_ACPI_IOMMU_INFO_RSV2) == 0);
-	acpi_ivhdp->ach_IOMMU_MSInum = AMD_IOMMU_REG_GET16(&uint16_info,
-	    AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM);
-
-	/* Initialize  deviceids to -1 */
-	acpi_ivhdp->ach_deviceid_start = -1;
-	acpi_ivhdp->ach_deviceid_end = -1;
-	acpi_ivhdp->ach_src_deviceid = -1;
-
-	/* All range type entries are put on hash entry 0 */
-	switch (deventry->idev_type) {
-	case DEVENTRY_ALL:
-		acpi_ivhdp->ach_deviceid_start = 0;
-		acpi_ivhdp->ach_deviceid_end = (uint16_t)-1;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_ALL;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		break;
-	case DEVENTRY_SELECT:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_SELECT;
-		idx = deviceid_hashfn(deventry->idev_deviceid);
-		break;
-	case DEVENTRY_RANGE:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = -1;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_RANGE;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		last = acpi_ivhdp;
-		break;
-	case DEVENTRY_RANGE_END:
-		cmn_err(CE_PANIC, "%s: Unexpected Range End Deventry",
-		    amd_iommu_modname);
-		/*NOTREACHED*/
-	case DEVENTRY_ALIAS_SELECT:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
-		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_SELECT;
-		idx = deviceid_hashfn(deventry->idev_deviceid);
-		break;
-	case DEVENTRY_ALIAS_RANGE:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = -1;
-		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_ALIAS_RANGE;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		last = acpi_ivhdp;
-		break;
-	case DEVENTRY_EXTENDED_SELECT:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = deventry->idev_deviceid;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_SELECT;
-		idx = deviceid_hashfn(deventry->idev_deviceid);
-		break;
-	case DEVENTRY_EXTENDED_RANGE:
-		acpi_ivhdp->ach_deviceid_start = deventry->idev_deviceid;
-		acpi_ivhdp->ach_deviceid_end = -1;
-		acpi_ivhdp->ach_dev_type = DEVENTRY_EXTENDED_RANGE;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		last = acpi_ivhdp;
-		break;
-	case DEVENTRY_SPECIAL_DEVICE:
-		acpi_ivhdp->ach_deviceid_start = -1;
-		acpi_ivhdp->ach_deviceid_end = -1;
-		acpi_ivhdp->ach_src_deviceid = deventry->idev_src_deviceid;
-		acpi_ivhdp->ach_special_handle = deventry->idev_handle;
-		acpi_ivhdp->ach_special_variety = deventry->idev_variety;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-	default:
-		cmn_err(CE_PANIC, "%s: Unsupported deventry type",
-		    amd_iommu_modname);
-		/*NOTREACHED*/
-	}
-
-	acpi_ivhdp->ach_Lint1Pass = deventry->idev_Lint1Pass;
-	acpi_ivhdp->ach_Lint0Pass = deventry->idev_Lint0Pass;
-	acpi_ivhdp->ach_SysMgt = deventry->idev_SysMgt;
-	acpi_ivhdp->ach_NMIPass = deventry->idev_NMIPass;
-	acpi_ivhdp->ach_ExtIntPass = deventry->idev_ExtIntPass;
-	acpi_ivhdp->ach_INITPass = deventry->idev_INITPass;
-
-
-	/* extended data */
-	if (acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_SELECT ||
-	    acpi_ivhdp->ach_dev_type == DEVENTRY_EXTENDED_RANGE) {
-		acpi_ivhdp->ach_AtsDisabled = deventry->idev_AtsDisabled;
-	}
-
-	/*
-	 * Now add it to the hash
-	 */
-	ASSERT(hash[idx] != acpi_ivhdp);
-	acpi_ivhdp->ach_next = hash[idx];
-	hash[idx] = acpi_ivhdp;
-}
-
-static void
-add_ivhdc_info(ivhd_container_t *ivhdcp, amd_iommu_acpi_ivhd_t **hash)
-{
-	ivhd_deventry_t *deventry;
-	ivhd_t *ivhdp = ivhdcp->ivhdc_ivhd;
-
-	for (deventry = ivhdcp->ivhdc_first_deventry; deventry;
-	    deventry = deventry->idev_next) {
-		add_deventry_info(ivhdp, deventry, hash);
-	}
-}
-
-static void
-add_ivhd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivhd_t **hash)
-{
-	ivhd_container_t *ivhdcp;
-
-	for (ivhdcp = acpi->acp_first_ivhdc; ivhdcp;
-	    ivhdcp = ivhdcp->ivhdc_next) {
-		add_ivhdc_info(ivhdcp, hash);
-	}
-}
-
-static void
-set_ivmd_info(ivmd_t *ivmdp, amd_iommu_acpi_ivmd_t **hash)
-{
-	amd_iommu_acpi_ivmd_t *acpi_ivmdp;
-	uint8_t uint8_flags;
-	uint16_t idx;
-
-	uint8_flags = ivmdp->ivmd_flags;
-
-	acpi_ivmdp = kmem_zalloc(sizeof (*acpi_ivmdp), KM_SLEEP);
-
-	switch (ivmdp->ivmd_type) {
-	case 0x20:
-		acpi_ivmdp->acm_deviceid_start = 0;
-		acpi_ivmdp->acm_deviceid_end = (uint16_t)-1;
-		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_ALL;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		break;
-	case 0x21:
-		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
-		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_deviceid;
-		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_SELECT;
-		idx = deviceid_hashfn(ivmdp->ivmd_deviceid);
-		break;
-	case 0x22:
-		acpi_ivmdp->acm_deviceid_start = ivmdp->ivmd_deviceid;
-		acpi_ivmdp->acm_deviceid_end = ivmdp->ivmd_auxdata;
-		acpi_ivmdp->acm_dev_type = IVMD_DEVICEID_RANGE;
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		break;
-	default:
-		cmn_err(CE_PANIC, "Unknown AMD IOMMU ACPI IVMD deviceid type: "
-		    "%x", ivmdp->ivmd_type);
-		/*NOTREACHED*/
-	}
-
-	ASSERT(AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVMD_RSV) == 0);
-
-	acpi_ivmdp->acm_ExclRange = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVMD_EXCL_RANGE);
-	acpi_ivmdp->acm_IW = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVMD_IW);
-	acpi_ivmdp->acm_IR = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVMD_IR);
-	acpi_ivmdp->acm_Unity = AMD_IOMMU_REG_GET8(&uint8_flags,
-	    AMD_IOMMU_ACPI_IVMD_UNITY);
-
-	acpi_ivmdp->acm_ivmd_phys_start = ivmdp->ivmd_phys_start;
-	acpi_ivmdp->acm_ivmd_phys_len = ivmdp->ivmd_phys_len;
-
-	acpi_ivmdp->acm_next = hash[idx];
-	hash[idx] = acpi_ivmdp;
-}
-
-static void
-add_ivmdc_info(ivmd_container_t *ivmdcp, amd_iommu_acpi_ivmd_t **hash)
-{
-	set_ivmd_info(ivmdcp->ivmdc_ivmd, hash);
-}
-
-static void
-add_ivmd_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_ivmd_t **hash)
-{
-	ivmd_container_t *ivmdcp;
-
-	for (ivmdcp = acpi->acp_first_ivmdc; ivmdcp;
-	    ivmdcp = ivmdcp->ivmdc_next) {
-		add_ivmdc_info(ivmdcp, hash);
-	}
-}
-
-static void
-add_global_info(amd_iommu_acpi_t *acpi, amd_iommu_acpi_global_t *global)
-{
-	uint32_t ivrs_ivinfo = acpi->acp_ivrs->ivrs_ivinfo;
-
-	global->acg_HtAtsResv =
-	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_HT_ATSRSV);
-	global->acg_VAsize =
-	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_VA_SIZE);
-	global->acg_PAsize =
-	    AMD_IOMMU_REG_GET32(&ivrs_ivinfo, AMD_IOMMU_ACPI_PA_SIZE);
-}
-
-static int
-create_acpi_hash(amd_iommu_acpi_t *acpi)
-{
-	/* Last hash entry is for deviceid ranges including "all" */
-
-	amd_iommu_acpi_global = kmem_zalloc(sizeof (amd_iommu_acpi_global_t),
-	    KM_SLEEP);
-
-	amd_iommu_acpi_ivhd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivhd_t *)
-	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
-
-	amd_iommu_acpi_ivmd_hash = kmem_zalloc(sizeof (amd_iommu_acpi_ivmd_t *)
-	    * (AMD_IOMMU_ACPI_INFO_HASH_SZ + 1), KM_SLEEP);
-
-	add_global_info(acpi, amd_iommu_acpi_global);
-
-	add_ivhd_info(acpi, amd_iommu_acpi_ivhd_hash);
-
-	add_ivmd_info(acpi, amd_iommu_acpi_ivmd_hash);
-
-	return (DDI_SUCCESS);
-}
-
-amd_iommu_acpi_global_t *
-amd_iommu_lookup_acpi_global(void)
-{
-	ASSERT(amd_iommu_acpi_global);
-
-	return (amd_iommu_acpi_global);
-}
-
-amd_iommu_acpi_ivhd_t *
-amd_iommu_lookup_all_ivhd(void)
-{
-	amd_iommu_acpi_ivhd_t *hinfop;
-
-	hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
-	for (; hinfop; hinfop = hinfop->ach_next) {
-		if (hinfop->ach_deviceid_start == 0 &&
-		    hinfop->ach_deviceid_end == (uint16_t)-1) {
-			break;
-		}
-	}
-
-	return (hinfop);
-}
-
-amd_iommu_acpi_ivmd_t *
-amd_iommu_lookup_all_ivmd(void)
-{
-	amd_iommu_acpi_ivmd_t *minfop;
-
-	minfop = amd_iommu_acpi_ivmd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
-	for (; minfop; minfop = minfop->acm_next) {
-		if (minfop->acm_deviceid_start == 0 &&
-		    minfop->acm_deviceid_end == (uint16_t)-1) {
-			break;
-		}
-	}
-
-	return (minfop);
-}
-
-amd_iommu_acpi_ivhd_t *
-amd_iommu_lookup_any_ivhd(void)
-{
-	int i;
-	amd_iommu_acpi_ivhd_t *hinfop;
-
-	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
-		/*LINTED*/
-		if (hinfop = amd_iommu_acpi_ivhd_hash[i])
-			break;
-	}
-
-	return (hinfop);
-}
-
-amd_iommu_acpi_ivmd_t *
-amd_iommu_lookup_any_ivmd(void)
-{
-	int i;
-	amd_iommu_acpi_ivmd_t *minfop;
-
-	for (i = AMD_IOMMU_ACPI_INFO_HASH_SZ; i >= 0; i--) {
-		/*LINTED*/
-		if (minfop = amd_iommu_acpi_ivmd_hash[i])
-			break;
-	}
-
-	return (minfop);
-}
-
-static void
-dump_acpi_aliases(void)
-{
-	amd_iommu_acpi_ivhd_t *hinfop;
-	uint16_t idx;
-
-	for (idx = 0; idx <= AMD_IOMMU_ACPI_INFO_HASH_SZ; idx++) {
-		hinfop = amd_iommu_acpi_ivhd_hash[idx];
-		for (; hinfop; hinfop = hinfop->ach_next) {
-			cmn_err(CE_NOTE, "start=%d, end=%d, src_bdf=%d",
-			    hinfop->ach_deviceid_start,
-			    hinfop->ach_deviceid_end,
-			    hinfop->ach_src_deviceid);
-		}
-	}
-}
-
-amd_iommu_acpi_ivhd_t *
-amd_iommu_lookup_ivhd(int32_t deviceid)
-{
-	amd_iommu_acpi_ivhd_t *hinfop;
-	uint16_t idx;
-
-	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-		cmn_err(CE_NOTE, "Attempting to get ACPI IVHD info "
-		    "for deviceid: %d", deviceid);
-	}
-
-	ASSERT(amd_iommu_acpi_ivhd_hash);
-
-	/* check if special device */
-	if (deviceid == -1) {
-		hinfop = amd_iommu_acpi_ivhd_hash[AMD_IOMMU_ACPI_INFO_HASH_SZ];
-		for (; hinfop; hinfop = hinfop->ach_next) {
-			if (hinfop->ach_deviceid_start  == -1 &&
-			    hinfop->ach_deviceid_end == -1) {
-				break;
-			}
-		}
-		return (hinfop);
-	}
-
-	/* First search for an exact match */
-
-	idx = deviceid_hashfn(deviceid);
-
-
-range:
-	hinfop = amd_iommu_acpi_ivhd_hash[idx];
-
-	for (; hinfop; hinfop = hinfop->ach_next) {
-		if (deviceid < hinfop->ach_deviceid_start ||
-		    deviceid > hinfop->ach_deviceid_end)
-			continue;
-
-		if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-			cmn_err(CE_NOTE, "Found ACPI IVHD match: %p, "
-			    "actual deviceid = %u, start = %u, end = %u",
-			    (void *)hinfop, deviceid,
-			    hinfop->ach_deviceid_start,
-			    hinfop->ach_deviceid_end);
-		}
-		goto out;
-	}
-
-	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		goto range;
-	} else {
-		cmn_err(CE_PANIC, "IVHD not found for deviceid: %x", deviceid);
-	}
-
-out:
-	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-		cmn_err(CE_NOTE, "%u: %s ACPI IVHD %p", deviceid,
-		    hinfop ? "GOT" : "Did NOT get", (void *)hinfop);
-	}
-
-	return (hinfop);
-}
-
-amd_iommu_acpi_ivmd_t *
-amd_iommu_lookup_ivmd(int32_t deviceid)
-{
-	amd_iommu_acpi_ivmd_t *minfop;
-	uint16_t idx;
-
-	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-		cmn_err(CE_NOTE, "Attempting to get ACPI IVMD info "
-		    "for deviceid: %u", deviceid);
-	}
-
-	ASSERT(amd_iommu_acpi_ivmd_hash);
-
-	/* First search for an exact match */
-
-	idx = deviceid_hashfn(deviceid);
-
-
-range:
-	minfop = amd_iommu_acpi_ivmd_hash[idx];
-
-	for (; minfop; minfop = minfop->acm_next) {
-		if (deviceid < minfop->acm_deviceid_start &&
-		    deviceid > minfop->acm_deviceid_end)
-			continue;
-
-		if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-			cmn_err(CE_NOTE, "Found ACPI IVMD match: %p, "
-			    "actual deviceid = %u, start = %u, end = %u",
-			    (void *)minfop, deviceid,
-			    minfop->acm_deviceid_start,
-			    minfop->acm_deviceid_end);
-		}
-
-		goto out;
-	}
-
-	if (idx !=  AMD_IOMMU_ACPI_INFO_HASH_SZ) {
-		idx = AMD_IOMMU_ACPI_INFO_HASH_SZ;
-		goto range;
-	} else {
-		cmn_err(CE_PANIC, "IVMD not found for deviceid: %x", deviceid);
-	}
-
-out:
-	if (amd_iommu_debug == AMD_IOMMU_DEBUG_ACPI) {
-		cmn_err(CE_NOTE, "%u: %s ACPI IVMD info %p", deviceid,
-		    minfop ? "GOT" : "Did NOT get", (void *)minfop);
-	}
-
-	return (minfop);
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_acpi.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _AMD_IOMMU_ACPI_H
-#define	_AMD_IOMMU_ACPI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/sunddi.h>
-#include <sys/acpi/acpi.h>
-#include <sys/acpica.h>
-#include <sys/amd_iommu.h>
-#include "amd_iommu_impl.h"
-
-#ifdef _KERNEL
-
-#define	IVRS_SIG	"IVRS"
-
-/*
- * IVINFO settings
- */
-#define	AMD_IOMMU_ACPI_IVINFO_RSV1	(31 << 16 | 23)
-#define	AMD_IOMMU_ACPI_HT_ATSRSV	(22 << 16 | 22)
-#define	AMD_IOMMU_ACPI_VA_SIZE		(21 << 16 | 15)
-#define	AMD_IOMMU_ACPI_PA_SIZE		(14 << 16 | 8)
-#define	AMD_IOMMU_ACPI_IVINFO_RSV2	(7 << 16 | 0)
-
-/*
- * IVHD Device entry len field
- */
-#define	AMD_IOMMU_ACPI_DEVENTRY_LEN	(7 << 16 | 6)
-
-/*
- * IVHD flag fields definition
- */
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_RSV		(7 << 16 | 5)
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_IOTLBSUP	(4 << 16 | 4)
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_ISOC		(3 << 16 | 3)
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_RESPASSPW	(2 << 16 | 2)
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_PASSPW	(1 << 16 | 1)
-#define	AMD_IOMMU_ACPI_IVHD_FLAGS_HTTUNEN	(0 << 16 | 0)
-
-/*
- * IVHD IOMMU info fields
- */
-#define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV1		(15 << 16 | 13)
-#define	AMD_IOMMU_ACPI_IOMMU_INFO_UNITID	(12 << 16 | 8)
-#define	AMD_IOMMU_ACPI_IOMMU_INFO_RSV2		(7 << 16 | 5)
-#define	AMD_IOMMU_ACPI_IOMMU_INFO_MSINUM	(4 << 16 | 0)
-
-/*
- * IVHD deventry data settings
- */
-#define	AMD_IOMMU_ACPI_LINT1PASS	(7 << 16 | 7)
-#define	AMD_IOMMU_ACPI_LINT0PASS	(6 << 16 | 6)
-#define	AMD_IOMMU_ACPI_SYSMGT		(5 << 16 | 4)
-#define	AMD_IOMMU_ACPI_DATRSV		(3 << 16 | 3)
-#define	AMD_IOMMU_ACPI_NMIPASS		(2 << 16 | 2)
-#define	AMD_IOMMU_ACPI_EXTINTPASS	(1 << 16 | 1)
-#define	AMD_IOMMU_ACPI_INITPASS		(0 << 16 | 0)
-
-/*
- * IVHD deventry extended data settings
- */
-#define	AMD_IOMMU_ACPI_ATSDISABLED	(31 << 16 | 31)
-#define	AMD_IOMMU_ACPI_EXTDATRSV	(30 << 16 | 0)
-
-/*
- * IVMD flags fields settings
- */
-#define	AMD_IOMMU_ACPI_IVMD_RSV		(7 << 16 | 4)
-#define	AMD_IOMMU_ACPI_IVMD_EXCL_RANGE	(3 << 16 | 3)
-#define	AMD_IOMMU_ACPI_IVMD_IW		(2 << 16 | 2)
-#define	AMD_IOMMU_ACPI_IVMD_IR		(1 << 16 | 1)
-#define	AMD_IOMMU_ACPI_IVMD_UNITY	(0 << 16 | 0)
-
-#define	AMD_IOMMU_ACPI_INFO_HASH_SZ	(256)
-
-/*
- * Deventry special device "variety"
- */
-#define	AMD_IOMMU_ACPI_SPECIAL_APIC	0x1
-#define	AMD_IOMMU_ACPI_SPECIAL_HPET	0x2
-
-typedef enum {
-	DEVENTRY_INVALID = 0,
-	DEVENTRY_ALL = 1,
-	DEVENTRY_SELECT,
-	DEVENTRY_RANGE,
-	DEVENTRY_RANGE_END,
-	DEVENTRY_ALIAS_SELECT,
-	DEVENTRY_ALIAS_RANGE,
-	DEVENTRY_EXTENDED_SELECT,
-	DEVENTRY_EXTENDED_RANGE,
-	DEVENTRY_SPECIAL_DEVICE
-} ivhd_deventry_type_t;
-
-typedef enum {
-	IVMD_DEVICE_INVALID = 0,
-	IVMD_DEVICEID_ALL,
-	IVMD_DEVICEID_SELECT,
-	IVMD_DEVICEID_RANGE
-} ivmd_deviceid_type_t;
-
-typedef struct ivhd_deventry {
-	uint8_t idev_len;
-	ivhd_deventry_type_t  idev_type;
-	int32_t idev_deviceid;
-	int32_t idev_src_deviceid;
-	uint8_t idev_handle;
-	uint8_t idev_variety;
-	uint8_t idev_Lint1Pass;
-	uint8_t idev_Lint0Pass;
-	uint8_t idev_SysMgt;
-	uint8_t idev_NMIPass;
-	uint8_t idev_ExtIntPass;
-	uint8_t idev_INITPass;
-	uint8_t idev_AtsDisabled;
-	struct ivhd_deventry *idev_next;
-} ivhd_deventry_t;
-
-typedef struct ivhd {
-	uint8_t ivhd_type;
-	uint8_t ivhd_flags;
-	uint16_t ivhd_len;
-	uint16_t ivhd_deviceid;
-	uint16_t ivhd_cap_off;
-	uint64_t ivhd_reg_base;
-	uint16_t ivhd_pci_seg;
-	uint16_t ivhd_iommu_info;
-	uint32_t ivhd_resv;
-} ivhd_t;
-
-typedef struct ivhd_container {
-	ivhd_t *ivhdc_ivhd;
-	ivhd_deventry_t *ivhdc_first_deventry;
-	ivhd_deventry_t *ivhdc_last_deventry;
-	struct ivhd_container *ivhdc_next;
-} ivhd_container_t;
-
-typedef struct ivmd {
-	uint8_t ivmd_type;
-	uint8_t ivmd_flags;
-	uint16_t ivmd_len;
-	uint16_t ivmd_deviceid;
-	uint16_t ivmd_auxdata;
-	uint64_t ivmd_resv;
-	uint64_t ivmd_phys_start;
-	uint64_t ivmd_phys_len;
-} ivmd_t;
-
-typedef struct ivmd_container {
-	ivmd_t *ivmdc_ivmd;
-	struct ivmd_container *ivmdc_next;
-} ivmd_container_t;
-
-typedef struct ivrs {
-	struct acpi_table_header ivrs_hdr;
-	uint32_t ivrs_ivinfo;
-	uint64_t ivrs_resv;
-} ivrs_t;
-
-typedef struct amd_iommu_acpi {
-	struct ivrs *acp_ivrs;
-	ivhd_container_t *acp_first_ivhdc;
-	ivhd_container_t *acp_last_ivhdc;
-	ivmd_container_t *acp_first_ivmdc;
-	ivmd_container_t *acp_last_ivmdc;
-} amd_iommu_acpi_t;
-
-
-/* Global IVINFo fields */
-typedef struct amd_iommu_acpi_global {
-	uint8_t acg_HtAtsResv;
-	uint8_t acg_VAsize;
-	uint8_t acg_PAsize;
-} amd_iommu_acpi_global_t;
-
-typedef struct amd_iommu_acpi_ivhd {
-	int32_t ach_deviceid_start;
-	int32_t ach_deviceid_end;
-
-	/* IVHD deventry type */
-	ivhd_deventry_type_t ach_dev_type;
-
-	/* IVHD flag fields */
-	uint8_t ach_IotlbSup;
-	uint8_t ach_Isoc;
-	uint8_t ach_ResPassPW;
-	uint8_t ach_PassPW;
-	uint8_t ach_HtTunEn;
-
-	/* IVHD fields */
-	uint16_t ach_IOMMU_deviceid;
-	uint16_t ach_IOMMU_cap_off;
-	uint64_t ach_IOMMU_reg_base;
-	uint16_t ach_IOMMU_pci_seg;
-
-	/* IVHD IOMMU info fields */
-	uint8_t ach_IOMMU_UnitID;
-	uint8_t ach_IOMMU_MSInum;
-
-	/* IVHD deventry data settings */
-	uint8_t ach_Lint1Pass;
-	uint8_t ach_Lint0Pass;
-	uint8_t ach_SysMgt;
-	uint8_t ach_NMIPass;
-	uint8_t ach_ExtIntPass;
-	uint8_t ach_INITPass;
-
-	/* alias */
-	int32_t ach_src_deviceid;
-
-	/* IVHD deventry extended data settings */
-	uint8_t ach_AtsDisabled;
-
-	/* IVHD deventry special device */
-	uint8_t ach_special_handle;
-	uint8_t ach_special_variety;
-
-	struct amd_iommu_acpi_ivhd *ach_next;
-} amd_iommu_acpi_ivhd_t;
-
-typedef struct amd_iommu_acpi_ivmd {
-	int32_t acm_deviceid_start;
-	int32_t acm_deviceid_end;
-
-	/* IVMD type */
-	ivmd_deviceid_type_t acm_dev_type;
-
-	/* IVMD flags */
-	uint8_t acm_ExclRange;
-	uint8_t acm_IW;
-	uint8_t acm_IR;
-	uint8_t acm_Unity;
-
-	/* IVMD mem block */
-	uint64_t acm_ivmd_phys_start;
-	uint64_t acm_ivmd_phys_len;
-
-	struct amd_iommu_acpi_ivmd *acm_next;
-} amd_iommu_acpi_ivmd_t;
-
-typedef union {
-	uint16_t   ent16;
-	uint8_t	   ent8[2];
-} align_16_t;
-
-typedef union {
-	uint32_t   ent32;
-	uint8_t	   ent8[4];
-} align_32_t;
-
-typedef union {
-	ivhd_t *ivhdp;
-	char   *cp;
-} align_ivhd_t;
-
-typedef union {
-	ivmd_t *ivmdp;
-	char   *cp;
-} align_ivmd_t;
-
-#pragma pack()
-
-int amd_iommu_acpi_init(void);
-void amd_iommu_acpi_fini(void);
-amd_iommu_acpi_ivhd_t *amd_iommu_lookup_all_ivhd(void);
-amd_iommu_acpi_ivmd_t *amd_iommu_lookup_all_ivmd(void);
-amd_iommu_acpi_ivhd_t *amd_iommu_lookup_any_ivhd(void);
-amd_iommu_acpi_ivmd_t *amd_iommu_lookup_any_ivmd(void);
-amd_iommu_acpi_global_t *amd_iommu_lookup_acpi_global(void);
-amd_iommu_acpi_ivhd_t *amd_iommu_lookup_ivhd(int32_t deviceid);
-amd_iommu_acpi_ivmd_t *amd_iommu_lookup_ivmd(int32_t deviceid);
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _AMD_IOMMU_ACPI_H */
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_cmd.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/sunddi.h>
-#include <sys/amd_iommu.h>
-#include "amd_iommu_impl.h"
-
-extern int servicing_interrupt(void);
-
-static void
-amd_iommu_wait_for_completion(amd_iommu_t *iommu)
-{
-	ASSERT(MUTEX_HELD(&iommu->aiomt_cmdlock));
-	while (AMD_IOMMU_REG_GET64(REGADDR64(
-	    iommu->aiomt_reg_status_va), AMD_IOMMU_COMWAIT_INT) != 1) {
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-		    AMD_IOMMU_CMDBUF_ENABLE, 1);
-		WAIT_SEC(1);
-	}
-}
-
-static int
-create_compl_wait_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
-    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
-{
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "create_compl_wait_cmd";
-
-	ASSERT(cmdargsp == NULL);
-
-	if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: 'store' completion "
-		    "not supported for completion wait command",
-		    f, driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_S, 0);
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_I, 1);
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_F,
-	    (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F) != 0);
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO,
-	    0);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x01);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI,
-	    0);
-	cmdptr[2] = 0;
-	cmdptr[3] = 0;
-
-	return (DDI_SUCCESS);
-}
-
-static int
-create_inval_devtab_entry_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
-    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
-{
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "create_inval_devtab_entry_cmd";
-	uint16_t deviceid;
-
-	ASSERT(cmdargsp);
-
-	if (flags != AMD_IOMMU_CMD_FLAGS_NONE) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: invalidate devtab entry "
-		    "no flags supported", f, driver, instance,
-		    iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	deviceid = cmdargsp->ca_deviceid;
-
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID,
-	    deviceid);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x02);
-	cmdptr[2] = 0;
-	cmdptr[3] = 0;
-
-	return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static int
-create_inval_iommu_pages_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
-    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
-{
-	uint32_t addr_lo;
-	uint32_t addr_hi;
-
-	ASSERT(cmdargsp);
-
-	addr_lo = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
-	    AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO);
-	addr_hi = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
-	    AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI);
-
-	cmdptr[0] = 0;
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID,
-	    cmdargsp->ca_domainid);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x03);
-	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_PDE,
-	    (flags & AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL) != 0);
-	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_S,
-	    (flags & AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S) != 0);
-	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO,
-	    addr_lo);
-	cmdptr[3] = addr_hi;
-
-	return (DDI_SUCCESS);
-
-}
-
-/*ARGSUSED*/
-static int
-create_inval_iotlb_pages_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
-    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
-{
-	uint32_t addr_lo;
-	uint32_t addr_hi;
-
-	ASSERT(cmdargsp);
-
-	addr_lo = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
-	    AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO);
-
-	addr_hi = AMD_IOMMU_REG_GET64(REGADDR64(&cmdargsp->ca_addr),
-	    AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI);
-
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID,
-	    cmdargsp->ca_deviceid);
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND,
-	    AMD_IOMMU_DEFAULT_MAXPEND);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x04);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID,
-	    cmdargsp->ca_deviceid);
-	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO,
-	    addr_lo);
-	AMD_IOMMU_REG_SET32(&cmdptr[2], AMD_IOMMU_CMD_INVAL_IOTLB_S,
-	    (flags & AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S) != 0);
-	cmdptr[3] = addr_hi;
-
-	return (DDI_SUCCESS);
-}
-
-static int
-create_inval_intr_table_cmd(amd_iommu_t *iommu, amd_iommu_cmdargs_t *cmdargsp,
-    amd_iommu_cmd_flags_t flags, uint32_t *cmdptr)
-{
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "create_inval_intr_table_cmd";
-
-	ASSERT(cmdargsp);
-
-	if (flags != AMD_IOMMU_CMD_FLAGS_NONE) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: flags not supported "
-		    "for invalidate interrupt table command",
-		    f, driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	AMD_IOMMU_REG_SET32(&cmdptr[0], AMD_IOMMU_CMD_INVAL_INTR_DEVICEID,
-	    cmdargsp->ca_deviceid);
-	AMD_IOMMU_REG_SET32(&cmdptr[1], AMD_IOMMU_CMD_OPCODE, 0x05);
-	cmdptr[2] = 0;
-	cmdptr[3] = 0;
-
-	return (DDI_SUCCESS);
-}
-
-int
-amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
-    amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held)
-{
-	int error;
-	int i;
-	uint32_t cmdptr[4] = {0};
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	uint64_t cmdhead_off;
-	uint64_t cmdtail_off;
-	const char *f = "amd_iommu_cmd";
-
-	ASSERT(lock_held == 0 || lock_held == 1);
-	ASSERT(lock_held == 0 || MUTEX_HELD(&iommu->aiomt_cmdlock));
-
-	if (!lock_held)
-		mutex_enter(&iommu->aiomt_cmdlock);
-
-	/*
-	 * Prepare the command
-	 */
-	switch (cmd) {
-	case AMD_IOMMU_CMD_COMPL_WAIT:
-		if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT) {
-			cmn_err(CE_WARN, "%s: %s%d: idx=%d: No completion wait "
-			    " after completion wait command",
-			    f, driver, instance, iommu->aiomt_idx);
-			error = DDI_FAILURE;
-			goto out;
-		}
-		error = create_compl_wait_cmd(iommu, cmdargs, flags, cmdptr);
-		break;
-	case AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY:
-		error = create_inval_devtab_entry_cmd(iommu, cmdargs,
-		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
-		break;
-	case AMD_IOMMU_CMD_INVAL_IOMMU_PAGES:
-		error = create_inval_iommu_pages_cmd(iommu, cmdargs,
-		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
-		break;
-	case AMD_IOMMU_CMD_INVAL_IOTLB_PAGES:
-		error = create_inval_iotlb_pages_cmd(iommu, cmdargs,
-		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
-		break;
-	case AMD_IOMMU_CMD_INVAL_INTR_TABLE:
-		error = create_inval_intr_table_cmd(iommu, cmdargs,
-		    flags & ~AMD_IOMMU_CMD_FLAGS_COMPL_WAIT, cmdptr);
-		break;
-	default:
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: Unsupported cmd: %d",
-		    f, driver, instance, iommu->aiomt_idx, cmd);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (error != DDI_SUCCESS) {
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_CMDBUF_ENABLE, 1);
-
-	ASSERT(iommu->aiomt_cmd_tail != NULL);
-
-	for (i = 0; i < 4; i++) {
-		iommu->aiomt_cmd_tail[i] = cmdptr[i];
-	}
-
-wait_for_drain:
-	cmdhead_off = AMD_IOMMU_REG_GET64(
-	    REGADDR64(iommu->aiomt_reg_cmdbuf_head_va),
-	    AMD_IOMMU_CMDHEADPTR);
-
-	cmdhead_off = CMD2OFF(cmdhead_off);
-
-	ASSERT(cmdhead_off < iommu->aiomt_cmdbuf_sz);
-
-	/* check for overflow */
-	if ((caddr_t)iommu->aiomt_cmd_tail <
-	    (cmdhead_off + iommu->aiomt_cmdbuf)) {
-		if ((caddr_t)iommu->aiomt_cmd_tail + 16 >=
-		    (cmdhead_off + iommu->aiomt_cmdbuf))
-#ifdef DEBUG
-			cmn_err(CE_WARN, "cmdbuffer overflow: waiting for "
-			    "drain");
-#endif
-			goto wait_for_drain;
-	}
-
-	SYNC_FORDEV(iommu->aiomt_dmahdl);
-
-	/*
-	 * Update the tail pointer in soft state
-	 * and the tail pointer register
-	 */
-	iommu->aiomt_cmd_tail += 4;
-	if ((caddr_t)iommu->aiomt_cmd_tail >= (iommu->aiomt_cmdbuf
-	    + iommu->aiomt_cmdbuf_sz)) {
-		/* wraparound */
-		/*LINTED*/
-		iommu->aiomt_cmd_tail = (uint32_t *)iommu->aiomt_cmdbuf;
-		cmdtail_off = 0;
-	} else {
-		cmdtail_off = (caddr_t)iommu->aiomt_cmd_tail
-		/*LINTED*/
-		    - iommu->aiomt_cmdbuf;
-	}
-
-	ASSERT(cmdtail_off < iommu->aiomt_cmdbuf_sz);
-
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_tail_va),
-	    AMD_IOMMU_CMDTAILPTR, OFF2CMD(cmdtail_off));
-
-	if (cmd == AMD_IOMMU_CMD_COMPL_WAIT) {
-		amd_iommu_wait_for_completion(iommu);
-	} else if (flags & AMD_IOMMU_CMD_FLAGS_COMPL_WAIT) {
-		error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_COMPL_WAIT,
-		    NULL, 0, 1);
-	}
-
-out:
-	if (!lock_held)
-		mutex_exit(&iommu->aiomt_cmdlock);
-	return (error);
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_impl.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1880 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/sunddi.h>
-#include <sys/iommulib.h>
-#include <sys/amd_iommu.h>
-#include <sys/pci_cap.h>
-#include <sys/bootconf.h>
-#include <sys/ddidmareq.h>
-
-#include "amd_iommu_impl.h"
-#include "amd_iommu_acpi.h"
-#include "amd_iommu_page_tables.h"
-
-static int amd_iommu_fini(amd_iommu_t *iommu);
-static void amd_iommu_teardown_interrupts(amd_iommu_t *iommu);
-static void amd_iommu_stop(amd_iommu_t *iommu);
-
-static int amd_iommu_probe(iommulib_handle_t handle, dev_info_t *rdip);
-static int amd_iommu_allochdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
-    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *dma_handlep);
-static int amd_iommu_freehdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle);
-static int amd_iommu_bindhdl(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle,
-    struct ddi_dma_req *dmareq, ddi_dma_cookie_t *cookiep,
-    uint_t *ccountp);
-static int amd_iommu_unbindhdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle);
-static int amd_iommu_sync(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle, off_t off,
-    size_t len, uint_t cache_flags);
-static int amd_iommu_win(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle, uint_t win,
-    off_t *offp, size_t *lenp, ddi_dma_cookie_t *cookiep,
-    uint_t *ccountp);
-static int amd_iommu_map(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, struct ddi_dma_req *dmareq,
-    ddi_dma_handle_t *dma_handle);
-static int amd_iommu_mctl(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle,
-    enum ddi_dma_ctlops request, off_t *offp, size_t *lenp,
-    caddr_t *objpp, uint_t cache_flags);
-
-static int unmap_current_window(amd_iommu_t *iommu, dev_info_t *rdip,
-    ddi_dma_cookie_t *cookie_array, uint_t ccount, int ncookies, int locked);
-
-extern void *device_arena_alloc(size_t size, int vm_flag);
-extern void device_arena_free(void * vaddr, size_t size);
-
-ddi_dma_attr_t amd_iommu_dma_attr = {
-	DMA_ATTR_V0,
-	0U,				/* dma_attr_addr_lo */
-	0xffffffffffffffffULL,		/* dma_attr_addr_hi */
-	0xffffffffU,			/* dma_attr_count_max */
-	(uint64_t)4096,			/* dma_attr_align */
-	1,				/* dma_attr_burstsizes */
-	64,				/* dma_attr_minxfer */
-	0xffffffffU,			/* dma_attr_maxxfer */
-	0xffffffffU,			/* dma_attr_seg */
-	1,				/* dma_attr_sgllen, variable */
-	64,				/* dma_attr_granular */
-	0				/* dma_attr_flags */
-};
-
-ddi_device_acc_attr_t amd_iommu_devacc = {
-	DDI_DEVICE_ATTR_V0,
-	DDI_NEVERSWAP_ACC,
-	DDI_STRICTORDER_ACC
-};
-
-struct iommulib_ops amd_iommulib_ops = {
-	IOMMU_OPS_VERSION,
-	AMD_IOMMU,
-	"AMD IOMMU Vers. 1",
-	NULL,
-	amd_iommu_probe,
-	amd_iommu_allochdl,
-	amd_iommu_freehdl,
-	amd_iommu_bindhdl,
-	amd_iommu_unbindhdl,
-	amd_iommu_sync,
-	amd_iommu_win,
-	amd_iommu_map,
-	amd_iommu_mctl
-};
-
-static kmutex_t amd_iommu_pgtable_lock;
-
-static int
-amd_iommu_register(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	const char *driver = ddi_driver_name(dip);
-	int instance = ddi_get_instance(dip);
-	iommulib_ops_t *iommulib_ops;
-	iommulib_handle_t handle;
-	const char *f = "amd_iommu_register";
-
-	iommulib_ops = kmem_zalloc(sizeof (iommulib_ops_t), KM_SLEEP);
-
-	*iommulib_ops = amd_iommulib_ops;
-
-	iommulib_ops->ilops_data = (void *)iommu;
-	iommu->aiomt_iommulib_ops = iommulib_ops;
-
-	if (iommulib_iommu_register(dip, iommulib_ops, &handle)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Register with iommulib "
-		    "failed idx=%d", f, driver, instance, iommu->aiomt_idx);
-		kmem_free(iommulib_ops, sizeof (iommulib_ops_t));
-		return (DDI_FAILURE);
-	}
-
-	iommu->aiomt_iommulib_handle = handle;
-
-	return (DDI_SUCCESS);
-}
-
-static int
-amd_iommu_unregister(amd_iommu_t *iommu)
-{
-	if (iommu->aiomt_iommulib_handle == NULL) {
-		/* we never registered */
-		return (DDI_SUCCESS);
-	}
-
-	if (iommulib_iommu_unregister(iommu->aiomt_iommulib_handle)
-	    != DDI_SUCCESS) {
-		return (DDI_FAILURE);
-	}
-
-	kmem_free(iommu->aiomt_iommulib_ops, sizeof (iommulib_ops_t));
-	iommu->aiomt_iommulib_ops = NULL;
-	iommu->aiomt_iommulib_handle = NULL;
-
-	return (DDI_SUCCESS);
-}
-
-static int
-amd_iommu_setup_passthru(amd_iommu_t *iommu)
-{
-	gfx_entry_t *gfxp;
-	dev_info_t *dip;
-
-	/*
-	 * Setup passthru mapping for "special" devices
-	 */
-	amd_iommu_set_passthru(iommu, NULL);
-
-	for (gfxp = gfx_devinfo_list; gfxp; gfxp = gfxp->g_next) {
-		gfxp->g_ref++;
-		dip = gfxp->g_dip;
-		if (dip) {
-			amd_iommu_set_passthru(iommu, dip);
-		}
-		gfxp->g_ref--;
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static int
-amd_iommu_start(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	amd_iommu_acpi_ivhd_t *hinfop;
-	const char *f = "amd_iommu_start";
-
-	hinfop = amd_iommu_lookup_all_ivhd();
-
-	/*
-	 * Disable HT tunnel translation.
-	 * XXX use ACPI
-	 */
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_HT_TUN_ENABLE, 0);
-
-	if (hinfop) {
-		if (amd_iommu_debug) {
-			cmn_err(CE_NOTE,
-			    "amd_iommu: using ACPI for CTRL registers");
-		}
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-		    AMD_IOMMU_ISOC, hinfop->ach_Isoc);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-		    AMD_IOMMU_RESPASSPW, hinfop->ach_ResPassPW);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-		    AMD_IOMMU_PASSPW, hinfop->ach_PassPW);
-	}
-
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_INVTO, 5);
-
-
-	/*
-	 * The Device table entry bit 0 (V) controls whether the device
-	 * table entry is valid for address translation and Device table
-	 * entry bit 128 (IV) controls whether interrupt remapping is valid.
-	 * By setting both to zero we are essentially doing pass-thru. Since
-	 * this table is zeroed on allocation, essentially we will have
-	 * pass-thru when IOMMU is enabled.
-	 */
-
-	/* Finally enable the IOMMU ... */
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_ENABLE, 1);
-
-	if (amd_iommu_debug) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "Successfully started AMD IOMMU", f, driver, instance,
-		    iommu->aiomt_idx);
-	}
-	cmn_err(CE_NOTE, "AMD IOMMU (%d,%d) enabled",
-	    instance, iommu->aiomt_idx);
-
-	return (DDI_SUCCESS);
-}
-
-static void
-amd_iommu_stop(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	const char *f = "amd_iommu_stop";
-
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_ENABLE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_EVENTINT_ENABLE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_COMWAITINT_ENABLE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_EVENTLOG_ENABLE, 0);
-
-	/*
-	 * Disable translation on HT tunnel traffic
-	 */
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_HT_TUN_ENABLE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_CMDBUF_ENABLE, 0);
-
-	cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMYU idx=%d. "
-	    "Successfully stopped AMD IOMMU", f, driver, instance,
-	    iommu->aiomt_idx);
-}
-
-static int
-amd_iommu_setup_tables_and_buffers(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	uint32_t dma_bufsz;
-	caddr_t addr;
-	uint32_t sz;
-	uint32_t p2sz;
-	int i;
-	uint64_t *dentry;
-	int err;
-	const char *f = "amd_iommu_setup_tables_and_buffers";
-
-	/*
-	 * We will put the Device Table, Command Buffer and
-	 * Event Log in contiguous memory. Allocate the maximum
-	 * size allowed for such structures
-	 * Device Table:  256b * 64K = 32B * 64K
-	 * Command Buffer: 128b * 32K = 16B * 32K
-	 * Event Log:  128b * 32K = 16B * 32K
-	 */
-	iommu->aiomt_devtbl_sz = (1<<AMD_IOMMU_DEVTBL_SZ) * AMD_IOMMU_DEVENT_SZ;
-	iommu->aiomt_cmdbuf_sz = (1<<AMD_IOMMU_CMDBUF_SZ) * AMD_IOMMU_CMD_SZ;
-	iommu->aiomt_eventlog_sz =
-	    (1<<AMD_IOMMU_EVENTLOG_SZ) * AMD_IOMMU_EVENT_SZ;
-
-	dma_bufsz = iommu->aiomt_devtbl_sz + iommu->aiomt_cmdbuf_sz
-	    + iommu->aiomt_eventlog_sz;
-
-	/*
-	 * Alloc a DMA handle.
-	 */
-	err = ddi_dma_alloc_handle(dip, &amd_iommu_dma_attr,
-	    DDI_DMA_SLEEP, NULL, &iommu->aiomt_dmahdl);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot alloc DMA handle for "
-		    "AMD IOMMU tables and buffers", f, driver, instance);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Alloc memory for tables and buffers
-	 * XXX remove cast to size_t
-	 */
-	err = ddi_dma_mem_alloc(iommu->aiomt_dmahdl, dma_bufsz,
-	    &amd_iommu_devacc, DDI_DMA_CONSISTENT|IOMEM_DATA_UNCACHED,
-	    DDI_DMA_SLEEP,  NULL, (caddr_t *)&iommu->aiomt_dma_bufva,
-	    (size_t *)&iommu->aiomt_dma_mem_realsz, &iommu->aiomt_dma_mem_hdl);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot alloc memory for DMA "
-		    "to AMD IOMMU tables and buffers", f, driver, instance);
-		iommu->aiomt_dma_bufva = NULL;
-		iommu->aiomt_dma_mem_realsz = 0;
-		ddi_dma_free_handle(&iommu->aiomt_dmahdl);
-		iommu->aiomt_dmahdl = NULL;
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * The VA must be 4K aligned and >= table size
-	 */
-	ASSERT(((uintptr_t)iommu->aiomt_dma_bufva &
-	    AMD_IOMMU_TABLE_ALIGN) == 0);
-	ASSERT(iommu->aiomt_dma_mem_realsz >= dma_bufsz);
-
-	/*
-	 * Now bind the handle
-	 */
-	err = ddi_dma_addr_bind_handle(iommu->aiomt_dmahdl, NULL,
-	    iommu->aiomt_dma_bufva, iommu->aiomt_dma_mem_realsz,
-	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
-	    NULL, &iommu->aiomt_buf_dma_cookie, &iommu->aiomt_buf_dma_ncookie);
-	if (err != DDI_DMA_MAPPED) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot bind memory for DMA "
-		    "to AMD IOMMU tables and buffers. bufrealsz=%p",
-		    f, driver, instance,
-		    (void *)(uintptr_t)iommu->aiomt_dma_mem_realsz);
-		iommu->aiomt_buf_dma_cookie.dmac_laddress = 0;
-		iommu->aiomt_buf_dma_cookie.dmac_size = 0;
-		iommu->aiomt_buf_dma_cookie.dmac_type = 0;
-		iommu->aiomt_buf_dma_ncookie = 0;
-		ddi_dma_mem_free(&iommu->aiomt_dma_mem_hdl);
-		iommu->aiomt_dma_mem_hdl = NULL;
-		iommu->aiomt_dma_bufva = NULL;
-		iommu->aiomt_dma_mem_realsz = 0;
-		ddi_dma_free_handle(&iommu->aiomt_dmahdl);
-		iommu->aiomt_dmahdl = NULL;
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * We assume the DMA engine on the IOMMU is capable of handling the
-	 * whole table buffer in a single cookie. If not and multiple cookies
-	 * are needed we fail.
-	 */
-	if (iommu->aiomt_buf_dma_ncookie != 1) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot handle multiple "
-		    "cookies for DMA to AMD IOMMU tables and buffers. "
-		    "#cookies=%u", f, driver, instance,
-		    iommu->aiomt_buf_dma_ncookie);
-		(void) ddi_dma_unbind_handle(iommu->aiomt_dmahdl);
-		iommu->aiomt_buf_dma_cookie.dmac_laddress = 0;
-		iommu->aiomt_buf_dma_cookie.dmac_size = 0;
-		iommu->aiomt_buf_dma_cookie.dmac_type = 0;
-		iommu->aiomt_buf_dma_ncookie = 0;
-		ddi_dma_mem_free(&iommu->aiomt_dma_mem_hdl);
-		iommu->aiomt_dma_mem_hdl = NULL;
-		iommu->aiomt_dma_bufva = NULL;
-		iommu->aiomt_dma_mem_realsz = 0;
-		ddi_dma_free_handle(&iommu->aiomt_dmahdl);
-		iommu->aiomt_dmahdl = NULL;
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * The address in the cookie must be 4K aligned and >= table size
-	 */
-	ASSERT((iommu->aiomt_buf_dma_cookie.dmac_cookie_addr
-	    & AMD_IOMMU_TABLE_ALIGN) == 0);
-	ASSERT(iommu->aiomt_buf_dma_cookie.dmac_size
-	    <= iommu->aiomt_dma_mem_realsz);
-	ASSERT(iommu->aiomt_buf_dma_cookie.dmac_size >= dma_bufsz);
-
-	/*
-	 * Setup the device table pointers in the iommu struct as
-	 * well as the IOMMU device table register
-	 */
-	iommu->aiomt_devtbl = iommu->aiomt_dma_bufva;
-	bzero(iommu->aiomt_devtbl, iommu->aiomt_devtbl_sz);
-
-	/*
-	 * Set V=1 and TV = 0, so any inadvertant pass-thrus cause
-	 * page faults. Also set SE bit so we aren't swamped with
-	 * page fault messages
-	 */
-	for (i = 0; i <= AMD_IOMMU_MAX_DEVICEID; i++) {
-		/*LINTED*/
-		dentry = (uint64_t *)&iommu->aiomt_devtbl
-		    [i * AMD_IOMMU_DEVTBL_ENTRY_SZ];
-		AMD_IOMMU_REG_SET64(dentry, AMD_IOMMU_DEVTBL_V, 1);
-		AMD_IOMMU_REG_SET64(&(dentry[1]), AMD_IOMMU_DEVTBL_SE, 1);
-	}
-
-	addr = (caddr_t)(uintptr_t)iommu->aiomt_buf_dma_cookie.dmac_cookie_addr;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
-	    AMD_IOMMU_DEVTABBASE, ((uint64_t)(uintptr_t)addr) >> 12);
-	sz = (iommu->aiomt_devtbl_sz >> 12) - 1;
-	ASSERT(sz <= ((1 << 9) - 1));
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
-	    AMD_IOMMU_DEVTABSIZE, sz);
-
-	/*
-	 * Setup the command buffer pointers
-	 */
-	iommu->aiomt_cmdbuf = iommu->aiomt_devtbl +
-	    iommu->aiomt_devtbl_sz;
-	bzero(iommu->aiomt_cmdbuf, iommu->aiomt_cmdbuf_sz);
-	addr += iommu->aiomt_devtbl_sz;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
-	    AMD_IOMMU_COMBASE, ((uint64_t)(uintptr_t)addr) >> 12);
-
-	p2sz = AMD_IOMMU_CMDBUF_SZ;
-	ASSERT(p2sz >= AMD_IOMMU_CMDBUF_MINSZ &&
-	    p2sz <= AMD_IOMMU_CMDBUF_MAXSZ);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
-	    AMD_IOMMU_COMLEN, p2sz);
-	/*LINTED*/
-	iommu->aiomt_cmd_tail = (uint32_t *)iommu->aiomt_cmdbuf;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_head_va),
-	    AMD_IOMMU_CMDHEADPTR, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_tail_va),
-	    AMD_IOMMU_CMDTAILPTR, 0);
-
-	/*
-	 * Setup the event log pointers
-	 */
-	iommu->aiomt_eventlog = iommu->aiomt_cmdbuf +
-	    iommu->aiomt_eventlog_sz;
-	bzero(iommu->aiomt_eventlog, iommu->aiomt_eventlog_sz);
-	addr += iommu->aiomt_cmdbuf_sz;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_va),
-	    AMD_IOMMU_EVENTBASE, ((uint64_t)(uintptr_t)addr) >> 12);
-	p2sz = AMD_IOMMU_EVENTLOG_SZ;
-	ASSERT(p2sz >= AMD_IOMMU_EVENTLOG_MINSZ &&
-	    p2sz <= AMD_IOMMU_EVENTLOG_MAXSZ);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_va),
-	    AMD_IOMMU_EVENTLEN, sz);
-	/*LINTED*/
-	iommu->aiomt_event_head = (uint32_t *)iommu->aiomt_eventlog;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_head_va),
-	    AMD_IOMMU_EVENTHEADPTR, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_tail_va),
-	    AMD_IOMMU_EVENTTAILPTR, 0);
-
-	/* dma sync so device sees this init */
-	SYNC_FORDEV(iommu->aiomt_dmahdl);
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_TABLES) {
-		cmn_err(CE_NOTE, "%s: %s%d: successfully setup AMD IOMMU "
-		    "tables, idx=%d", f, driver, instance, iommu->aiomt_idx);
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static void
-amd_iommu_teardown_tables_and_buffers(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	const char *f = "amd_iommu_teardown_tables_and_buffers";
-
-	iommu->aiomt_eventlog = NULL;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_va),
-	    AMD_IOMMU_EVENTBASE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_eventlog_va),
-	    AMD_IOMMU_EVENTLEN, 0);
-
-	iommu->aiomt_cmdbuf = NULL;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
-	    AMD_IOMMU_COMBASE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_cmdbuf_va),
-	    AMD_IOMMU_COMLEN, 0);
-
-	iommu->aiomt_devtbl = NULL;
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
-	    AMD_IOMMU_DEVTABBASE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_devtbl_va),
-	    AMD_IOMMU_DEVTABSIZE, 0);
-
-	if (iommu->aiomt_dmahdl == NULL)
-		return;
-
-	/* Unbind the handle */
-	if (ddi_dma_unbind_handle(iommu->aiomt_dmahdl) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: failed to unbind handle: "
-		    "%p for IOMMU idx=%d", f, driver, instance,
-		    (void *)iommu->aiomt_dmahdl, iommu->aiomt_idx);
-	}
-	iommu->aiomt_buf_dma_cookie.dmac_laddress = 0;
-	iommu->aiomt_buf_dma_cookie.dmac_size = 0;
-	iommu->aiomt_buf_dma_cookie.dmac_type = 0;
-	iommu->aiomt_buf_dma_ncookie = 0;
-
-	/* Free the table memory allocated for DMA */
-	ddi_dma_mem_free(&iommu->aiomt_dma_mem_hdl);
-	iommu->aiomt_dma_mem_hdl = NULL;
-	iommu->aiomt_dma_bufva = NULL;
-	iommu->aiomt_dma_mem_realsz = 0;
-
-	/* Free the DMA handle */
-	ddi_dma_free_handle(&iommu->aiomt_dmahdl);
-	iommu->aiomt_dmahdl = NULL;
-}
-
-static void
-amd_iommu_enable_interrupts(amd_iommu_t *iommu)
-{
-	ASSERT(AMD_IOMMU_REG_GET64(REGADDR64(iommu->aiomt_reg_status_va),
-	    AMD_IOMMU_CMDBUF_RUN) == 0);
-	ASSERT(AMD_IOMMU_REG_GET64(REGADDR64(iommu->aiomt_reg_status_va),
-	    AMD_IOMMU_EVENT_LOG_RUN) == 0);
-
-	/* Must be set prior to enabling command buffer */
-	/* Must be set prior to enabling event logging */
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_CMDBUF_ENABLE, 1);
-	/* No interrupts for completion wait  - too heavy weight. use polling */
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_COMWAITINT_ENABLE, 0);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_EVENTLOG_ENABLE, 1);
-	AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_ctrl_va),
-	    AMD_IOMMU_EVENTINT_ENABLE, 1);
-}
-
-static int
-amd_iommu_setup_exclusion(amd_iommu_t *iommu)
-{
-	amd_iommu_acpi_ivmd_t *minfop;
-
-	minfop = amd_iommu_lookup_all_ivmd();
-
-	if (minfop && minfop->acm_ExclRange == 1) {
-		cmn_err(CE_NOTE, "Programming exclusion range");
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_ADDR,
-		    minfop->acm_ivmd_phys_start >> 12);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_ALLOW, 1);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_EXEN, 1);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_lim_va),
-		    AMD_IOMMU_EXCL_LIM, (minfop->acm_ivmd_phys_start +
-		    minfop->acm_ivmd_phys_len) >> 12);
-	} else {
-		if (amd_iommu_debug) {
-			cmn_err(CE_NOTE, "Skipping exclusion range");
-		}
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_ADDR, 0);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_ALLOW, 1);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_base_va),
-		    AMD_IOMMU_EXCL_BASE_EXEN, 0);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_excl_lim_va),
-		    AMD_IOMMU_EXCL_LIM, 0);
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static void
-amd_iommu_teardown_exclusion(amd_iommu_t *iommu)
-{
-	(void) amd_iommu_setup_exclusion(iommu);
-}
-
-static uint_t
-amd_iommu_intr_handler(caddr_t arg1, caddr_t arg2)
-{
-	/*LINTED*/
-	amd_iommu_t *iommu = (amd_iommu_t *)arg1;
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	const char *f = "amd_iommu_intr_handler";
-
-	ASSERT(arg1);
-	ASSERT(arg2 == NULL);
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: IOMMU unit idx=%d. In INTR handler",
-		    f, driver, instance, iommu->aiomt_idx);
-	}
-
-	if (AMD_IOMMU_REG_GET64(REGADDR64(iommu->aiomt_reg_status_va),
-	    AMD_IOMMU_EVENT_LOG_INT) == 1) {
-		if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-			cmn_err(CE_NOTE, "%s: %s%d: IOMMU unit idx=%d "
-			    "Event Log Interrupt", f, driver, instance,
-			    iommu->aiomt_idx);
-		}
-		(void) amd_iommu_read_log(iommu, AMD_IOMMU_LOG_DISPLAY);
-		WAIT_SEC(1);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_status_va),
-		    AMD_IOMMU_EVENT_LOG_INT, 1);
-		return (DDI_INTR_CLAIMED);
-	}
-
-	if (AMD_IOMMU_REG_GET64(REGADDR64(iommu->aiomt_reg_status_va),
-	    AMD_IOMMU_EVENT_OVERFLOW_INT) == 1) {
-		cmn_err(CE_NOTE, "!%s: %s%d: IOMMU unit idx=%d "
-		    "Event Overflow Interrupt", f, driver, instance,
-		    iommu->aiomt_idx);
-		(void) amd_iommu_read_log(iommu, AMD_IOMMU_LOG_DISCARD);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_status_va),
-		    AMD_IOMMU_EVENT_LOG_INT, 1);
-		AMD_IOMMU_REG_SET64(REGADDR64(iommu->aiomt_reg_status_va),
-		    AMD_IOMMU_EVENT_OVERFLOW_INT, 1);
-		return (DDI_INTR_CLAIMED);
-	}
-
-	return (DDI_INTR_UNCLAIMED);
-}
-
-
-static int
-amd_iommu_setup_interrupts(amd_iommu_t *iommu)
-{
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	int intrcap0;
-	int intrcapN;
-	int type;
-	int err;
-	int req;
-	int avail;
-	int p2req;
-	int actual;
-	int i;
-	int j;
-	const char *f = "amd_iommu_setup_interrupts";
-
-	if (ddi_intr_get_supported_types(dip, &type) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: ddi_intr_get_supported_types "
-		    "failed: idx=%d", f, driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "Interrupt types supported = 0x%x", f, driver, instance,
-		    iommu->aiomt_idx, type);
-	}
-
-	/*
-	 * for now we only support MSI
-	 */
-	if ((type & DDI_INTR_TYPE_MSI) == 0) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "MSI interrupts not supported. Failing init.",
-		    f, driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. MSI supported",
-		    f, driver, instance, iommu->aiomt_idx);
-	}
-
-	err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_MSI, &req);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "ddi_intr_get_nintrs failed err = %d",
-		    f, driver, instance, iommu->aiomt_idx, err);
-		return (DDI_FAILURE);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "MSI number of interrupts requested: %d",
-		    f, driver, instance, iommu->aiomt_idx, req);
-	}
-
-	if (req == 0) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: 0 MSI "
-		    "interrupts requested. Failing init", f,
-		    driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	err = ddi_intr_get_navail(dip, DDI_INTR_TYPE_MSI, &avail);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d "
-		    "ddi_intr_get_navail failed err = %d", f,
-		    driver, instance, iommu->aiomt_idx, err);
-		return (DDI_FAILURE);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "MSI number of interrupts available: %d",
-		    f, driver, instance, iommu->aiomt_idx, avail);
-	}
-
-	if (avail == 0) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: 0 MSI "
-		    "interrupts available. Failing init", f,
-		    driver, instance, iommu->aiomt_idx);
-		return (DDI_FAILURE);
-	}
-
-	if (avail < req) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: MSI "
-		    "interrupts: requested (%d) > available (%d). "
-		    "Failing init", f, driver, instance, iommu->aiomt_idx,
-		    req, avail);
-		return (DDI_FAILURE);
-	}
-
-	/* Allocate memory for DDI interrupt handles */
-	iommu->aiomt_intr_htable_sz = req * sizeof (ddi_intr_handle_t);
-	iommu->aiomt_intr_htable = kmem_zalloc(iommu->aiomt_intr_htable_sz,
-	    KM_SLEEP);
-
-	iommu->aiomt_intr_state = AMD_IOMMU_INTR_TABLE;
-
-	/* Convert req to a power of two as required by ddi_intr_alloc */
-	p2req = 0;
-	while (1<<p2req <= req)
-		p2req++;
-	p2req--;
-	req = 1<<p2req;
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "MSI power of 2 number of interrupts: %d,%d",
-		    f, driver, instance, iommu->aiomt_idx, p2req, req);
-	}
-
-	err = ddi_intr_alloc(iommu->aiomt_dip, iommu->aiomt_intr_htable,
-	    DDI_INTR_TYPE_MSI, 0, req, &actual, DDI_INTR_ALLOC_STRICT);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-		    "ddi_intr_alloc failed: err = %d",
-		    f, driver, instance, iommu->aiomt_idx, err);
-		amd_iommu_teardown_interrupts(iommu);
-		return (DDI_FAILURE);
-	}
-
-	iommu->aiomt_actual_intrs = actual;
-	iommu->aiomt_intr_state = AMD_IOMMU_INTR_ALLOCED;
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d. "
-		    "number of interrupts actually allocated %d",
-		    f, driver, instance, iommu->aiomt_idx, actual);
-	}
-
-	if (iommu->aiomt_actual_intrs < req) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-		    "ddi_intr_alloc failed: actual (%d) < req (%d)",
-		    f, driver, instance, iommu->aiomt_idx,
-		    iommu->aiomt_actual_intrs, req);
-		amd_iommu_teardown_interrupts(iommu);
-		return (DDI_FAILURE);
-	}
-
-	for (i = 0; i < iommu->aiomt_actual_intrs; i++) {
-		if (ddi_intr_add_handler(iommu->aiomt_intr_htable[i],
-		    amd_iommu_intr_handler, (void *)iommu, NULL)
-		    != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-			    "ddi_intr_add_handler failed: intr = %d, err = %d",
-			    f, driver, instance, iommu->aiomt_idx, i, err);
-			for (j = 0; j < i; j++) {
-				(void) ddi_intr_remove_handler(
-				    iommu->aiomt_intr_htable[j]);
-			}
-			amd_iommu_teardown_interrupts(iommu);
-			return (DDI_FAILURE);
-		}
-	}
-	iommu->aiomt_intr_state = AMD_IOMMU_INTR_HANDLER;
-
-	intrcap0 = intrcapN = -1;
-	if (ddi_intr_get_cap(iommu->aiomt_intr_htable[0], &intrcap0)
-	    != DDI_SUCCESS ||
-	    ddi_intr_get_cap(
-	    iommu->aiomt_intr_htable[iommu->aiomt_actual_intrs - 1], &intrcapN)
-	    != DDI_SUCCESS || intrcap0 != intrcapN) {
-		cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-		    "ddi_intr_get_cap failed or inconsistent cap among "
-		    "interrupts: intrcap0 (%d) < intrcapN (%d)",
-		    f, driver, instance, iommu->aiomt_idx, intrcap0, intrcapN);
-		amd_iommu_teardown_interrupts(iommu);
-		return (DDI_FAILURE);
-	}
-	iommu->aiomt_intr_cap = intrcap0;
-
-	if (intrcap0 & DDI_INTR_FLAG_BLOCK) {
-		/* Need to call block enable */
-		if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-			cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d: "
-			    "Need to call block enable",
-			    f, driver, instance, iommu->aiomt_idx);
-		}
-		if (ddi_intr_block_enable(iommu->aiomt_intr_htable,
-		    iommu->aiomt_actual_intrs) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-			    "ddi_intr_block enable failed ", f, driver,
-			    instance, iommu->aiomt_idx);
-			(void) ddi_intr_block_disable(iommu->aiomt_intr_htable,
-			    iommu->aiomt_actual_intrs);
-			amd_iommu_teardown_interrupts(iommu);
-			return (DDI_FAILURE);
-		}
-	} else {
-		if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-			cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d: "
-			    "Need to call individual enable",
-			    f, driver, instance, iommu->aiomt_idx);
-		}
-		for (i = 0; i < iommu->aiomt_actual_intrs; i++) {
-			if (ddi_intr_enable(iommu->aiomt_intr_htable[i])
-			    != DDI_SUCCESS) {
-				cmn_err(CE_WARN, "%s: %s%d: AMD IOMMU idx=%d: "
-				    "ddi_intr_enable failed: intr = %d", f,
-				    driver, instance, iommu->aiomt_idx, i);
-				for (j = 0; j < i; j++) {
-					(void) ddi_intr_disable(
-					    iommu->aiomt_intr_htable[j]);
-				}
-				amd_iommu_teardown_interrupts(iommu);
-				return (DDI_FAILURE);
-			}
-		}
-	}
-	iommu->aiomt_intr_state = AMD_IOMMU_INTR_ENABLED;
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_INTR) {
-		cmn_err(CE_NOTE, "%s: %s%d: AMD IOMMU idx=%d: "
-		    "Interrupts successfully %s enabled. # of interrupts = %d",
-		    f, driver, instance, iommu->aiomt_idx,
-		    (intrcap0 & DDI_INTR_FLAG_BLOCK) ? "(block)" :
-		    "(individually)", iommu->aiomt_actual_intrs);
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static void
-amd_iommu_teardown_interrupts(amd_iommu_t *iommu)
-{
-	int i;
-
-	if (iommu->aiomt_intr_state & AMD_IOMMU_INTR_ENABLED) {
-		if (iommu->aiomt_intr_cap & DDI_INTR_FLAG_BLOCK) {
-			(void) ddi_intr_block_disable(iommu->aiomt_intr_htable,
-			    iommu->aiomt_actual_intrs);
-		} else {
-			for (i = 0; i < iommu->aiomt_actual_intrs; i++) {
-				(void) ddi_intr_disable(
-				    iommu->aiomt_intr_htable[i]);
-			}
-		}
-	}
-
-	if (iommu->aiomt_intr_state & AMD_IOMMU_INTR_HANDLER) {
-		for (i = 0; i < iommu->aiomt_actual_intrs; i++) {
-			(void) ddi_intr_remove_handler(
-			    iommu->aiomt_intr_htable[i]);
-		}
-	}
-
-	if (iommu->aiomt_intr_state & AMD_IOMMU_INTR_ALLOCED) {
-		for (i = 0; i < iommu->aiomt_actual_intrs; i++) {
-			(void) ddi_intr_free(iommu->aiomt_intr_htable[i]);
-		}
-	}
-	if (iommu->aiomt_intr_state & AMD_IOMMU_INTR_TABLE) {
-		kmem_free(iommu->aiomt_intr_htable,
-		    iommu->aiomt_intr_htable_sz);
-	}
-	iommu->aiomt_intr_htable = NULL;
-	iommu->aiomt_intr_htable_sz = 0;
-	iommu->aiomt_intr_state = AMD_IOMMU_INTR_INVALID;
-}
-
-static amd_iommu_t *
-amd_iommu_init(dev_info_t *dip, ddi_acc_handle_t handle, int idx,
-    uint16_t cap_base)
-{
-	amd_iommu_t *iommu;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	uint32_t caphdr;
-	uint32_t low_addr32;
-	uint32_t hi_addr32;
-	uint32_t range;
-	uint32_t misc;
-	uint64_t pgoffset;
-	amd_iommu_acpi_global_t *global;
-	amd_iommu_acpi_ivhd_t *hinfop;
-	const char *f = "amd_iommu_init";
-
-	global = amd_iommu_lookup_acpi_global();
-	hinfop = amd_iommu_lookup_any_ivhd();
-
-	low_addr32 = PCI_CAP_GET32(handle, 0, cap_base,
-	    AMD_IOMMU_CAP_ADDR_LOW_OFF);
-	if (!(low_addr32 & AMD_IOMMU_REG_ADDR_LOCKED)) {
-		cmn_err(CE_WARN, "%s: %s%d: capability registers not locked. "
-		    "Unable to use IOMMU unit idx=%d - skipping ...", f, driver,
-		    instance, idx);
-		return (NULL);
-	}
-
-	iommu = kmem_zalloc(sizeof (amd_iommu_t), KM_SLEEP);
-	mutex_init(&iommu->aiomt_mutex, NULL, MUTEX_DRIVER, NULL);
-	mutex_enter(&iommu->aiomt_mutex);
-
-	mutex_init(&iommu->aiomt_cmdlock, NULL, MUTEX_DRIVER, NULL);
-	mutex_init(&iommu->aiomt_eventlock, NULL, MUTEX_DRIVER, NULL);
-
-	iommu->aiomt_dip = dip;
-	iommu->aiomt_idx = idx;
-
-	/*
-	 * Since everything in the capability block is locked and RO at this
-	 * point, copy everything into the IOMMU struct
-	 */
-
-	/* Get cap header */
-	caphdr = PCI_CAP_GET32(handle, 0, cap_base, AMD_IOMMU_CAP_HDR_OFF);
-	iommu->aiomt_cap_hdr = caphdr;
-	iommu->aiomt_npcache = AMD_IOMMU_REG_GET32(&caphdr,
-	    AMD_IOMMU_CAP_NPCACHE);
-	iommu->aiomt_httun = AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_HTTUN);
-
-	if (hinfop)
-		iommu->aiomt_iotlb = hinfop->ach_IotlbSup;
-	else
-		iommu->aiomt_iotlb =
-		    AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_IOTLB);
-
-	iommu->aiomt_captype = AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_TYPE);
-	iommu->aiomt_capid = AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_ID);
-
-	/*
-	 * Get address of IOMMU control registers
-	 */
-	hi_addr32 = PCI_CAP_GET32(handle, 0, cap_base,
-	    AMD_IOMMU_CAP_ADDR_HI_OFF);
-	iommu->aiomt_low_addr32 = low_addr32;
-	iommu->aiomt_hi_addr32 = hi_addr32;
-	low_addr32 &= ~AMD_IOMMU_REG_ADDR_LOCKED;
-
-	if (hinfop) {
-		iommu->aiomt_reg_pa =  hinfop->ach_IOMMU_reg_base;
-		ASSERT(hinfop->ach_IOMMU_pci_seg == 0);
-	} else {
-		iommu->aiomt_reg_pa =  ((uint64_t)hi_addr32 << 32 | low_addr32);
-	}
-
-	/*
-	 * Get cap range reg
-	 */
-	range = PCI_CAP_GET32(handle, 0, cap_base, AMD_IOMMU_CAP_RANGE_OFF);
-	iommu->aiomt_range = range;
-	iommu->aiomt_rng_valid = AMD_IOMMU_REG_GET32(&range,
-	    AMD_IOMMU_RNG_VALID);
-	if (iommu->aiomt_rng_valid) {
-		iommu->aiomt_rng_bus = AMD_IOMMU_REG_GET32(&range,
-		    AMD_IOMMU_RNG_BUS);
-		iommu->aiomt_first_devfn = AMD_IOMMU_REG_GET32(&range,
-		    AMD_IOMMU_FIRST_DEVFN);
-		iommu->aiomt_last_devfn = AMD_IOMMU_REG_GET32(&range,
-		    AMD_IOMMU_LAST_DEVFN);
-	} else {
-		iommu->aiomt_rng_bus = 0;
-		iommu->aiomt_first_devfn = 0;
-		iommu->aiomt_last_devfn = 0;
-	}
-
-	if (hinfop)
-		iommu->aiomt_ht_unitid = hinfop->ach_IOMMU_UnitID;
-	else
-		iommu->aiomt_ht_unitid = AMD_IOMMU_REG_GET32(&range,
-		    AMD_IOMMU_HT_UNITID);
-
-	/*
-	 * Get cap misc reg
-	 */
-	misc = PCI_CAP_GET32(handle, 0, cap_base, AMD_IOMMU_CAP_MISC_OFF);
-	iommu->aiomt_misc = misc;
-
-	if (global) {
-		iommu->aiomt_htatsresv = global->acg_HtAtsResv;
-		iommu->aiomt_vasize = global->acg_VAsize;
-		iommu->aiomt_pasize = global->acg_PAsize;
-	} else {
-		iommu->aiomt_htatsresv = AMD_IOMMU_REG_GET32(&misc,
-		    AMD_IOMMU_HT_ATSRSV);
-		iommu->aiomt_vasize = AMD_IOMMU_REG_GET32(&misc,
-		    AMD_IOMMU_VA_SIZE);
-		iommu->aiomt_pasize = AMD_IOMMU_REG_GET32(&misc,
-		    AMD_IOMMU_PA_SIZE);
-	}
-
-	if (hinfop) {
-		iommu->aiomt_msinum = hinfop->ach_IOMMU_MSInum;
-	} else {
-		iommu->aiomt_msinum =
-		    AMD_IOMMU_REG_GET32(&misc, AMD_IOMMU_MSINUM);
-	}
-
-	/*
-	 * Set up mapping between control registers PA and VA
-	 */
-	pgoffset = iommu->aiomt_reg_pa & MMU_PAGEOFFSET;
-	ASSERT(pgoffset == 0);
-	iommu->aiomt_reg_pages = mmu_btopr(AMD_IOMMU_REG_SIZE + pgoffset);
-	iommu->aiomt_reg_size = mmu_ptob(iommu->aiomt_reg_pages);
-
-	iommu->aiomt_va = (uintptr_t)device_arena_alloc(
-	    ptob(iommu->aiomt_reg_pages), VM_SLEEP);
-	if (iommu->aiomt_va == 0) {
-		cmn_err(CE_WARN, "%s: %s%d: Failed to alloc VA for IOMMU "
-		    "control regs. Skipping IOMMU idx=%d", f, driver,
-		    instance, idx);
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	hat_devload(kas.a_hat, (void *)(uintptr_t)iommu->aiomt_va,
-	    iommu->aiomt_reg_size,
-	    mmu_btop(iommu->aiomt_reg_pa), PROT_READ | PROT_WRITE
-	    | HAT_STRICTORDER, HAT_LOAD_LOCK);
-
-	iommu->aiomt_reg_va = iommu->aiomt_va + pgoffset;
-
-	/*
-	 * Setup the various control register's VA
-	 */
-	iommu->aiomt_reg_devtbl_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_DEVTBL_REG_OFF;
-	iommu->aiomt_reg_cmdbuf_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_CMDBUF_REG_OFF;
-	iommu->aiomt_reg_eventlog_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_EVENTLOG_REG_OFF;
-	iommu->aiomt_reg_ctrl_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_CTRL_REG_OFF;
-	iommu->aiomt_reg_excl_base_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_EXCL_BASE_REG_OFF;
-	iommu->aiomt_reg_excl_lim_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_EXCL_LIM_REG_OFF;
-	iommu->aiomt_reg_cmdbuf_head_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_CMDBUF_HEAD_REG_OFF;
-	iommu->aiomt_reg_cmdbuf_tail_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_CMDBUF_TAIL_REG_OFF;
-	iommu->aiomt_reg_eventlog_head_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_EVENTLOG_HEAD_REG_OFF;
-	iommu->aiomt_reg_eventlog_tail_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_EVENTLOG_TAIL_REG_OFF;
-	iommu->aiomt_reg_status_va = iommu->aiomt_reg_va +
-	    AMD_IOMMU_STATUS_REG_OFF;
-
-
-	/*
-	 * Setup the DEVICE table, CMD buffer, and LOG buffer in
-	 * memory and setup DMA access to this memory location
-	 */
-	if (amd_iommu_setup_tables_and_buffers(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	if (amd_iommu_setup_exclusion(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	amd_iommu_enable_interrupts(iommu);
-
-	if (amd_iommu_setup_interrupts(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	/*
-	 * need to setup domain table before gfx bypass
-	 */
-	amd_iommu_init_page_tables(iommu);
-
-	/*
-	 * Set pass-thru for special devices like IOAPIC and HPET
-	 *
-	 * Also, gfx devices don't use DDI for DMA. No need to register
-	 * before setting up gfx passthru
-	 */
-	if (amd_iommu_setup_passthru(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	if (amd_iommu_start(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	/* xxx register/start race  */
-	if (amd_iommu_register(iommu) != DDI_SUCCESS) {
-		mutex_exit(&iommu->aiomt_mutex);
-		(void) amd_iommu_fini(iommu);
-		return (NULL);
-	}
-
-	if (amd_iommu_debug) {
-		cmn_err(CE_NOTE, "%s: %s%d: IOMMU idx=%d inited.", f, driver,
-		    instance, idx);
-	}
-
-	return (iommu);
-}
-
-static int
-amd_iommu_fini(amd_iommu_t *iommu)
-{
-	int idx = iommu->aiomt_idx;
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	const char *f = "amd_iommu_fini";
-
-	mutex_enter(&iommu->aiomt_mutex);
-	if (amd_iommu_unregister(iommu) != DDI_SUCCESS) {
-		cmn_err(CE_NOTE, "%s: %s%d: Fini of IOMMU unit failed. "
-		    "idx = %d", f, driver, instance, idx);
-		return (DDI_FAILURE);
-	}
-	amd_iommu_stop(iommu);
-	amd_iommu_fini_page_tables(iommu);
-	amd_iommu_teardown_interrupts(iommu);
-	amd_iommu_teardown_exclusion(iommu);
-	amd_iommu_teardown_tables_and_buffers(iommu);
-	if (iommu->aiomt_va != NULL) {
-		hat_unload(kas.a_hat, (void *)(uintptr_t)iommu->aiomt_va,
-		    iommu->aiomt_reg_size, HAT_UNLOAD_UNLOCK);
-		device_arena_free((void *)(uintptr_t)iommu->aiomt_va,
-		    ptob(iommu->aiomt_reg_pages));
-		iommu->aiomt_va = NULL;
-		iommu->aiomt_reg_va = NULL;
-	}
-	mutex_destroy(&iommu->aiomt_eventlock);
-	mutex_destroy(&iommu->aiomt_cmdlock);
-	mutex_exit(&iommu->aiomt_mutex);
-	mutex_destroy(&iommu->aiomt_mutex);
-	kmem_free(iommu, sizeof (amd_iommu_t));
-
-	cmn_err(CE_NOTE, "%s: %s%d: Fini of IOMMU unit complete. idx = %d",
-	    f, driver, instance, idx);
-
-	return (DDI_SUCCESS);
-}
-
-int
-amd_iommu_setup(dev_info_t *dip, amd_iommu_state_t *statep)
-{
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	ddi_acc_handle_t handle;
-	uint8_t base_class;
-	uint8_t sub_class;
-	uint8_t prog_class;
-	int idx;
-	uint32_t id;
-	uint16_t cap_base;
-	uint32_t caphdr;
-	uint8_t cap_type;
-	uint8_t cap_id;
-	amd_iommu_t *iommu;
-	const char *f = "amd_iommu_setup";
-
-	ASSERT(instance >= 0);
-	ASSERT(driver);
-
-	/* First setup PCI access to config space */
-
-	if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: PCI config setup failed: %s%d",
-		    f, driver, instance);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * The AMD IOMMU is part of an independent PCI function. There may be
-	 * more than one IOMMU in that PCI function
-	 */
-	base_class = pci_config_get8(handle, PCI_CONF_BASCLASS);
-	sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS);
-	prog_class = pci_config_get8(handle, PCI_CONF_PROGCLASS);
-
-	if (base_class != PCI_CLASS_PERIPH || sub_class != PCI_PERIPH_IOMMU ||
-	    prog_class != AMD_IOMMU_PCI_PROG_IF) {
-		cmn_err(CE_WARN, "%s: %s%d: invalid PCI class(0x%x)/"
-		    "subclass(0x%x)/programming interface(0x%x)", f, driver,
-		    instance, base_class, sub_class, prog_class);
-		pci_config_teardown(&handle);
-		return (DDI_FAILURE);
-	}
-
-	/*
-	 * Find and initialize all IOMMU units in this function
-	 */
-	for (idx = 0; ; idx++) {
-		if (pci_cap_probe(handle, idx, &id, &cap_base) != DDI_SUCCESS)
-			break;
-
-		/* check if cap ID is secure device cap id */
-		if (id != PCI_CAP_ID_SECURE_DEV) {
-			if (amd_iommu_debug) {
-				cmn_err(CE_WARN,
-				    "%s: %s%d: skipping IOMMU: idx(0x%x) "
-				    "cap ID (0x%x) != secure dev capid (0x%x)",
-				    f, driver, instance, idx, id,
-				    PCI_CAP_ID_SECURE_DEV);
-			}
-			continue;
-		}
-
-		/* check if cap type is IOMMU cap type */
-		caphdr = PCI_CAP_GET32(handle, 0, cap_base,
-		    AMD_IOMMU_CAP_HDR_OFF);
-		cap_type = AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_TYPE);
-		cap_id = AMD_IOMMU_REG_GET32(&caphdr, AMD_IOMMU_CAP_ID);
-
-		if (cap_type != AMD_IOMMU_CAP) {
-			cmn_err(CE_WARN, "%s: %s%d: skipping IOMMU: idx(0x%x) "
-			    "cap type (0x%x) != AMD IOMMU CAP (0x%x)", f,
-			    driver, instance, idx, cap_type, AMD_IOMMU_CAP);
-			continue;
-		}
-		ASSERT(cap_id == PCI_CAP_ID_SECURE_DEV);
-		ASSERT(cap_id == id);
-
-		iommu = amd_iommu_init(dip, handle, idx, cap_base);
-		if (iommu == NULL) {
-			cmn_err(CE_WARN, "%s: %s%d: skipping IOMMU: idx(0x%x) "
-			    "failed to init IOMMU", f,
-			    driver, instance, idx);
-			continue;
-		}
-
-		if (statep->aioms_iommu_start == NULL) {
-			statep->aioms_iommu_start = iommu;
-		} else {
-			statep->aioms_iommu_end->aiomt_next = iommu;
-		}
-		statep->aioms_iommu_end = iommu;
-
-		statep->aioms_nunits++;
-	}
-
-	pci_config_teardown(&handle);
-
-	if (amd_iommu_debug) {
-		cmn_err(CE_NOTE, "%s: %s%d: state=%p: setup %d IOMMU units",
-		    f, driver, instance, (void *)statep, statep->aioms_nunits);
-	}
-
-	return (DDI_SUCCESS);
-}
-
-int
-amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep)
-{
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	amd_iommu_t *iommu;
-	int teardown;
-	int error = DDI_SUCCESS;
-	const char *f = "amd_iommu_teardown";
-
-	teardown = 0;
-	for (iommu = statep->aioms_iommu_start; iommu;
-	    iommu = iommu->aiomt_next) {
-		ASSERT(statep->aioms_nunits > 0);
-		if (amd_iommu_fini(iommu) != DDI_SUCCESS) {
-			error = DDI_FAILURE;
-			continue;
-		}
-		statep->aioms_nunits--;
-		teardown++;
-	}
-
-	cmn_err(CE_NOTE, "%s: %s%d: state=%p: toredown %d units. "
-	    "%d units left", f, driver, instance, (void *)statep,
-	    teardown, statep->aioms_nunits);
-
-	return (error);
-}
-
-/* Interface with IOMMULIB */
-/*ARGSUSED*/
-static int
-amd_iommu_probe(iommulib_handle_t handle, dev_info_t *rdip)
-{
-	const char *driver = ddi_driver_name(rdip);
-	char *s;
-	amd_iommu_t *iommu = iommulib_iommu_getdata(handle);
-
-	if (amd_iommu_disable_list) {
-		s = strstr(amd_iommu_disable_list, driver);
-		if (s == NULL)
-			return (DDI_SUCCESS);
-		if (s == amd_iommu_disable_list || *(s - 1) == ':') {
-			s += strlen(driver);
-			if (*s == '\0' || *s == ':') {
-				amd_iommu_set_passthru(iommu, rdip);
-				return (DDI_FAILURE);
-			}
-		}
-	}
-
-	return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_allochdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
-    int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *dma_handlep)
-{
-	return (iommulib_iommu_dma_allochdl(dip, rdip, attr, waitfp,
-	    arg, dma_handlep));
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_freehdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle)
-{
-	return (iommulib_iommu_dma_freehdl(dip, rdip, dma_handle));
-}
-
-/*ARGSUSED*/
-static int
-map_current_window(amd_iommu_t *iommu, dev_info_t *rdip, ddi_dma_attr_t *attrp,
-    struct ddi_dma_req *dmareq, ddi_dma_cookie_t *cookie_array, uint_t ccount,
-    int km_flags)
-{
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	int idx = iommu->aiomt_idx;
-	int i;
-	uint64_t start_va;
-	char *path;
-	int error = DDI_FAILURE;
-	const char *f = "map_current_window";
-
-	path = kmem_alloc(MAXPATHLEN, km_flags);
-	if (path == NULL) {
-		return (DDI_DMA_NORESOURCES);
-	}
-
-	(void) ddi_pathname(rdip, path);
-	mutex_enter(&amd_iommu_pgtable_lock);
-
-	if (amd_iommu_debug == AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d Attempting to get cookies "
-		    "from handle for device %s",
-		    f, driver, instance, idx, path);
-	}
-
-	start_va = 0;
-	for (i = 0; i < ccount; i++) {
-		if ((error = amd_iommu_map_pa2va(iommu, rdip, attrp, dmareq,
-		    cookie_array[i].dmac_cookie_addr,
-		    cookie_array[i].dmac_size,
-		    AMD_IOMMU_VMEM_MAP, &start_va, km_flags)) != DDI_SUCCESS) {
-			break;
-		}
-		cookie_array[i].dmac_cookie_addr = (uintptr_t)start_va;
-		cookie_array[i].dmac_type = 0;
-	}
-
-	if (i != ccount) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d Cannot map cookie# %d "
-		    "for device %s", f, driver, instance, idx, i, path);
-		(void) unmap_current_window(iommu, rdip, cookie_array,
-		    ccount, i, 1);
-		goto out;
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_NOTE, "%s: return SUCCESS", f);
-	}
-
-	error = DDI_DMA_MAPPED;
-out:
-	mutex_exit(&amd_iommu_pgtable_lock);
-	kmem_free(path, MAXPATHLEN);
-	return (error);
-}
-
-/*ARGSUSED*/
-static int
-unmap_current_window(amd_iommu_t *iommu, dev_info_t *rdip,
-    ddi_dma_cookie_t *cookie_array, uint_t ccount, int ncookies, int locked)
-{
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	int idx = iommu->aiomt_idx;
-	int i;
-	int error = DDI_FAILURE;
-	char *path;
-	int pathfree;
-	const char *f = "unmap_current_window";
-
-	if (!locked)
-		mutex_enter(&amd_iommu_pgtable_lock);
-
-	path = kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
-	if (path) {
-		(void) ddi_pathname(rdip, path);
-		pathfree = 1;
-	} else {
-		path = "<path-mem-alloc-failed>";
-		pathfree = 0;
-	}
-
-	if (ncookies == -1)
-		ncookies = ccount;
-
-	for (i = 0; i < ncookies; i++) {
-		if (amd_iommu_unmap_va(iommu, rdip,
-		    cookie_array[i].dmac_cookie_addr,
-		    cookie_array[i].dmac_size,
-		    AMD_IOMMU_VMEM_MAP) != DDI_SUCCESS) {
-			break;
-		}
-	}
-
-	if (amd_iommu_cmd(iommu, AMD_IOMMU_CMD_COMPL_WAIT, NULL, 0, 0)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: AMD IOMMU completion wait failed for: %s",
-		    f, path);
-	}
-
-	if (i != ncookies) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d Cannot unmap cookie# %d "
-		    "for device %s", f, driver, instance, idx, i, path);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	error = DDI_SUCCESS;
-
-out:
-	if (pathfree)
-		kmem_free(path, MAXPATHLEN);
-	if (!locked)
-		mutex_exit(&amd_iommu_pgtable_lock);
-	return (error);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_bindhdl(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle,
-    struct ddi_dma_req *dmareq, ddi_dma_cookie_t *cookiep,
-    uint_t *ccountp)
-{
-	int dma_error = DDI_DMA_NOMAPPING;
-	int error;
-	char *path;
-	ddi_dma_cookie_t *cookie_array = NULL;
-	uint_t ccount = 0;
-	ddi_dma_impl_t *hp;
-	ddi_dma_attr_t *attrp;
-	int km_flags;
-	amd_iommu_t *iommu = iommulib_iommu_getdata(handle);
-	int instance = ddi_get_instance(rdip);
-	const char *driver = ddi_driver_name(rdip);
-	const char *f = "amd_iommu_bindhdl";
-
-	dma_error = iommulib_iommu_dma_bindhdl(dip, rdip, dma_handle,
-	    dmareq, cookiep, ccountp);
-
-	if (dma_error != DDI_DMA_MAPPED && dma_error != DDI_DMA_PARTIAL_MAP)
-		return (dma_error);
-
-	km_flags = iommulib_iommu_dma_get_sleep_flags(dip, dma_handle);
-
-	path = kmem_alloc(MAXPATHLEN, km_flags);
-	if (path) {
-		(void) ddi_pathname(rdip, path);
-	} else {
-		dma_error = DDI_DMA_NORESOURCES;
-		goto unbind;
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_BIND) {
-		cmn_err(CE_NOTE, "%s: %s got cookie (%p), #cookies: %d",
-		    f, path,
-		    (void *)cookiep->dmac_cookie_addr,
-		    *ccountp);
-	}
-
-	cookie_array = NULL;
-	ccount = 0;
-	if ((error = iommulib_iommu_dma_get_cookies(dip, dma_handle,
-	    &cookie_array, &ccount)) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot get cookies "
-		    "for device %s", f, driver, instance, path);
-		dma_error = error;
-		goto unbind;
-	}
-
-	hp = (ddi_dma_impl_t *)dma_handle;
-	attrp = &hp->dmai_attr;
-
-	error = map_current_window(iommu, rdip, attrp, dmareq,
-	    cookie_array, ccount, km_flags);
-	if (error != DDI_SUCCESS) {
-		dma_error = error;
-		goto unbind;
-	}
-
-	if ((error = iommulib_iommu_dma_set_cookies(dip, dma_handle,
-	    cookie_array, ccount)) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot set cookies "
-		    "for device %s", f, driver, instance, path);
-		dma_error = error;
-		goto unbind;
-	}
-
-	*cookiep = cookie_array[0];
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_BIND) {
-		cmn_err(CE_NOTE, "%s: %s remapped cookie (%p), #cookies: %d",
-		    f, path,
-		    (void *)(uintptr_t)cookiep->dmac_cookie_addr,
-		    *ccountp);
-	}
-
-	kmem_free(path, MAXPATHLEN);
-	ASSERT(dma_error == DDI_DMA_MAPPED || dma_error == DDI_DMA_PARTIAL_MAP);
-	return (dma_error);
-unbind:
-	kmem_free(path, MAXPATHLEN);
-	(void) iommulib_iommu_dma_unbindhdl(dip, rdip, dma_handle);
-	return (dma_error);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_unbindhdl(iommulib_handle_t handle,
-    dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t dma_handle)
-{
-	amd_iommu_t *iommu = iommulib_iommu_getdata(handle);
-	ddi_dma_cookie_t *cookie_array = NULL;
-	uint_t ccount = 0;
-	int error = DDI_FAILURE;
-	int instance = ddi_get_instance(rdip);
-	const char *driver = ddi_driver_name(rdip);
-	const char *f = "amd_iommu_unbindhdl";
-
-	cookie_array = NULL;
-	ccount = 0;
-	if (iommulib_iommu_dma_get_cookies(dip, dma_handle, &cookie_array,
-	    &ccount) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot get cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (iommulib_iommu_dma_clear_cookies(dip, dma_handle) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot clear cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (iommulib_iommu_dma_unbindhdl(dip, rdip, dma_handle)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: failed to unbindhdl for dip=%p",
-		    f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (unmap_current_window(iommu, rdip, cookie_array, ccount, -1, 0)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: failed to unmap current window "
-		    "for dip=%p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-	} else {
-		error = DDI_SUCCESS;
-	}
-out:
-	if (cookie_array)
-		kmem_free(cookie_array, sizeof (ddi_dma_cookie_t) * ccount);
-	return (error);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_sync(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle, off_t off,
-    size_t len, uint_t cache_flags)
-{
-	ddi_dma_cookie_t *cookie_array = NULL;
-	uint_t ccount = 0;
-	int error;
-	const char *f = "amd_iommu_sync";
-
-	cookie_array = NULL;
-	ccount = 0;
-	if (iommulib_iommu_dma_get_cookies(dip, dma_handle, &cookie_array,
-	    &ccount) != DDI_SUCCESS) {
-		ASSERT(cookie_array == NULL);
-		cmn_err(CE_WARN, "%s: Cannot get cookies "
-		    "for device %p", f, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (iommulib_iommu_dma_clear_cookies(dip, dma_handle) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: Cannot clear cookies "
-		    "for device %p", f, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	error = iommulib_iommu_dma_sync(dip, rdip, dma_handle, off,
-	    len, cache_flags);
-
-	if (iommulib_iommu_dma_set_cookies(dip, dma_handle, cookie_array,
-	    ccount) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: Cannot set cookies "
-		    "for device %p", f, (void *)rdip);
-		error = DDI_FAILURE;
-	} else {
-		cookie_array = NULL;
-		ccount = 0;
-	}
-
-out:
-	if (cookie_array)
-		kmem_free(cookie_array, sizeof (ddi_dma_cookie_t) * ccount);
-	return (error);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_win(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle, uint_t win,
-    off_t *offp, size_t *lenp, ddi_dma_cookie_t *cookiep,
-    uint_t *ccountp)
-{
-	int error = DDI_FAILURE;
-	amd_iommu_t *iommu = iommulib_iommu_getdata(handle);
-	ddi_dma_cookie_t *cookie_array = NULL;
-	uint_t ccount = 0;
-	int km_flags;
-	ddi_dma_impl_t *hp;
-	ddi_dma_attr_t *attrp;
-	struct ddi_dma_req sdmareq = {0};
-	int instance = ddi_get_instance(rdip);
-	const char *driver = ddi_driver_name(rdip);
-	const char *f = "amd_iommu_win";
-
-	km_flags = iommulib_iommu_dma_get_sleep_flags(dip, dma_handle);
-
-	cookie_array = NULL;
-	ccount = 0;
-	if (iommulib_iommu_dma_get_cookies(dip, dma_handle, &cookie_array,
-	    &ccount) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot get cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (iommulib_iommu_dma_clear_cookies(dip, dma_handle) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot clear cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	if (iommulib_iommu_dma_win(dip, rdip, dma_handle, win,
-	    offp, lenp, cookiep, ccountp) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: failed switch windows for dip=%p",
-		    f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	(void) unmap_current_window(iommu, rdip, cookie_array, ccount, -1, 0);
-
-	if (cookie_array) {
-		kmem_free(cookie_array, sizeof (ddi_dma_cookie_t) * ccount);
-		cookie_array = NULL;
-		ccount = 0;
-	}
-
-	cookie_array = NULL;
-	ccount = 0;
-	if (iommulib_iommu_dma_get_cookies(dip, dma_handle, &cookie_array,
-	    &ccount) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot get cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	hp = (ddi_dma_impl_t *)dma_handle;
-	attrp = &hp->dmai_attr;
-
-	sdmareq.dmar_flags = DDI_DMA_RDWR;
-	error = map_current_window(iommu, rdip, attrp, &sdmareq,
-	    cookie_array, ccount, km_flags);
-
-	if (iommulib_iommu_dma_set_cookies(dip, dma_handle, cookie_array,
-	    ccount) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: Cannot set cookies "
-		    "for device %p", f, driver, instance, (void *)rdip);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	*cookiep = cookie_array[0];
-
-	return (error == DDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
-out:
-	if (cookie_array)
-		kmem_free(cookie_array, sizeof (ddi_dma_cookie_t) * ccount);
-
-	return (error);
-}
-
-/* Obsoleted DMA routines */
-
-/*ARGSUSED*/
-static int
-amd_iommu_map(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, struct ddi_dma_req *dmareq,
-    ddi_dma_handle_t *dma_handle)
-{
-	ASSERT(0);
-	return (iommulib_iommu_dma_map(dip, rdip, dmareq, dma_handle));
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_mctl(iommulib_handle_t handle, dev_info_t *dip,
-    dev_info_t *rdip, ddi_dma_handle_t dma_handle,
-    enum ddi_dma_ctlops request, off_t *offp, size_t *lenp,
-    caddr_t *objpp, uint_t cache_flags)
-{
-	ASSERT(0);
-	return (iommulib_iommu_dma_mctl(dip, rdip, dma_handle,
-	    request, offp, lenp, objpp, cache_flags));
-}
-
-uint64_t
-amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits)
-{
-	split_t s;
-	uint32_t *ptr32 = (uint32_t *)regp;
-	uint64_t *s64p = &(s.u64);
-
-	s.u32[0] = ptr32[0];
-	s.u32[1] = ptr32[1];
-
-	return (AMD_IOMMU_REG_GET64_IMPL(s64p, bits));
-}
-
-uint64_t
-amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits, uint64_t value)
-{
-	split_t s;
-	uint32_t *ptr32 = (uint32_t *)regp;
-	uint64_t *s64p = &(s.u64);
-
-	s.u32[0] = ptr32[0];
-	s.u32[1] = ptr32[1];
-
-	AMD_IOMMU_REG_SET64_IMPL(s64p, bits, value);
-
-	*regp = s.u64;
-
-	return (s.u64);
-}
-
-void
-amd_iommu_read_boot_props(void)
-{
-	char *propval;
-
-	/*
-	 * if "amd-iommu = no/false" boot property is set,
-	 * ignore AMD iommu
-	 */
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
-	    DDI_PROP_DONTPASS, "amd-iommu", &propval) == DDI_SUCCESS) {
-		if (strcmp(propval, "no") == 0 ||
-		    strcmp(propval, "false") == 0) {
-			amd_iommu_disable = 1;
-		}
-		ddi_prop_free(propval);
-	}
-
-	/*
-	 * Copy the list of drivers for which IOMMU is disabled by user.
-	 */
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
-	    DDI_PROP_DONTPASS, "amd-iommu-disable-list", &propval)
-	    == DDI_SUCCESS) {
-		amd_iommu_disable_list = kmem_alloc(strlen(propval) + 1,
-		    KM_SLEEP);
-		(void) strcpy(amd_iommu_disable_list, propval);
-		ddi_prop_free(propval);
-	}
-
-}
-
-void
-amd_iommu_lookup_conf_props(dev_info_t *dip)
-{
-	char *disable;
-
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS|DDI_PROP_NOTPROM, "amd-iommu", &disable)
-	    == DDI_PROP_SUCCESS) {
-		if (strcmp(disable, "no") == 0) {
-			amd_iommu_disable = 1;
-		}
-		ddi_prop_free(disable);
-	}
-
-	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
-	    DDI_PROP_DONTPASS|DDI_PROP_NOTPROM, "amd-iommu-disable-list",
-	    &disable) == DDI_PROP_SUCCESS) {
-		amd_iommu_disable_list = kmem_alloc(strlen(disable) + 1,
-		    KM_SLEEP);
-		(void) strcpy(amd_iommu_disable_list, disable);
-		ddi_prop_free(disable);
-	}
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_impl.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,494 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_AMD_IOMMU_IMPL_H
-#define	_AMD_IOMMU_IMPL_H
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#include <sys/pci.h>
-
-#ifdef	_KERNEL
-
-#define	AMD_IOMMU_PCI_PROG_IF	(0x0)
-
-#define	AMD_IOMMU_CAP		(0x3)
-
-#define	AMD_IOMMU_REG_SIZE	(0x2028)
-#define	AMD_IOMMU_DEVTBL_SZ	(16)
-#define	AMD_IOMMU_CMDBUF_SZ	(15)
-#define	AMD_IOMMU_EVENTLOG_SZ	(15)
-#define	AMD_IOMMU_DEVENT_SZ	(32)
-#define	AMD_IOMMU_CMD_SZ	(16)
-#define	AMD_IOMMU_EVENT_SZ	(16)
-
-/* Capability Register offsets */
-#define	AMD_IOMMU_CAP_HDR_OFF		(0x00)
-#define	AMD_IOMMU_CAP_ADDR_LOW_OFF	(0x04)
-#define	AMD_IOMMU_CAP_ADDR_HI_OFF	(0x08)
-#define	AMD_IOMMU_CAP_RANGE_OFF		(0x0C)
-#define	AMD_IOMMU_CAP_MISC_OFF		(0x10)
-
-/* ControL Registers offsets */
-#define	AMD_IOMMU_DEVTBL_REG_OFF	(0x00)
-#define	AMD_IOMMU_CMDBUF_REG_OFF	(0x08)
-#define	AMD_IOMMU_EVENTLOG_REG_OFF	(0x10)
-#define	AMD_IOMMU_CTRL_REG_OFF		(0x18)
-#define	AMD_IOMMU_EXCL_BASE_REG_OFF	(0x20)
-#define	AMD_IOMMU_EXCL_LIM_REG_OFF	(0x28)
-#define	AMD_IOMMU_CMDBUF_HEAD_REG_OFF	(0x2000)
-#define	AMD_IOMMU_CMDBUF_TAIL_REG_OFF	(0x2008)
-#define	AMD_IOMMU_EVENTLOG_HEAD_REG_OFF	(0x2010)
-#define	AMD_IOMMU_EVENTLOG_TAIL_REG_OFF	(0x2018)
-#define	AMD_IOMMU_STATUS_REG_OFF	(0x2020)
-
-/* Capability Header Register Bits */
-#define	AMD_IOMMU_CAP_NPCACHE	(26 << 16 | 26)
-#define	AMD_IOMMU_CAP_HTTUN	(25 << 16 | 25)
-#define	AMD_IOMMU_CAP_IOTLB	(24 << 16 | 24)
-#define	AMD_IOMMU_CAP_TYPE	(18 << 16 | 16)
-#define	AMD_IOMMU_CAP_ID	(7 << 16 | 0)
-
-/* Capability Range Register bits */
-#define	AMD_IOMMU_LAST_DEVFN	(31 << 16 | 24)
-#define	AMD_IOMMU_FIRST_DEVFN	(23 << 16 | 16)
-#define	AMD_IOMMU_RNG_BUS	(15 << 16 | 8)
-#define	AMD_IOMMU_RNG_VALID	(7 << 16 | 7)
-#define	AMD_IOMMU_HT_UNITID	(4 << 16 | 0)
-
-
-/* Capability Misc Register bits */
-#define	AMD_IOMMU_HT_ATSRSV	(22 << 16 | 22)
-#define	AMD_IOMMU_VA_SIZE	(21 << 16 | 15)
-#define	AMD_IOMMU_PA_SIZE	(14 << 16 | 8)
-#define	AMD_IOMMU_MSINUM	(4 << 16 | 0)
-
-/* Device Table Base Address register bits */
-#define	AMD_IOMMU_DEVTABBASE	(51 << 16 | 12)
-#define	AMD_IOMMU_DEVTABSIZE	(8 << 16 | 0)
-
-/* Command Buffer Base Address register bits */
-#define	AMD_IOMMU_COMLEN	(59 << 16 | 56)
-#define	AMD_IOMMU_COMBASE	(51 << 16 | 12)
-
-#define	AMD_IOMMU_CMDBUF_MINSZ	(8)
-#define	AMD_IOMMU_CMDBUF_MAXSZ	(15)
-
-/* Event Log Base Address register bits */
-#define	AMD_IOMMU_EVENTLEN	(59 << 16 | 56)
-#define	AMD_IOMMU_EVENTBASE	(51 << 16 | 12)
-
-#define	AMD_IOMMU_EVENTLOG_MINSZ	(8)
-#define	AMD_IOMMU_EVENTLOG_MAXSZ	(15)
-
-/* Control register bits */
-#define	AMD_IOMMU_CMDBUF_ENABLE		(12 << 16 | 12)
-#define	AMD_IOMMU_ISOC			(11 << 16 | 11)
-#define	AMD_IOMMU_COHERENT		(10 << 16 | 10)
-#define	AMD_IOMMU_RESPASSPW		(9 << 16 | 9)
-#define	AMD_IOMMU_PASSPW		(8 << 16 | 8)
-#define	AMD_IOMMU_INVTO			(7 << 16 | 5)
-#define	AMD_IOMMU_COMWAITINT_ENABLE	(4 << 16 | 4)
-#define	AMD_IOMMU_EVENTINT_ENABLE	(3 << 16 | 3)
-#define	AMD_IOMMU_EVENTLOG_ENABLE	(2 << 16 | 2)
-#define	AMD_IOMMU_HT_TUN_ENABLE		(1 << 16 | 1)
-#define	AMD_IOMMU_ENABLE		(0 << 16 | 0)
-
-/* Exclusion Base Register bits */
-#define	AMD_IOMMU_EXCL_BASE_ADDR	(51 << 16 | 12)
-#define	AMD_IOMMU_EXCL_BASE_ALLOW	(1 << 16 | 1)
-#define	AMD_IOMMU_EXCL_BASE_EXEN	(0 << 16 | 0)
-
-/* Exclusion Limit Register bits */
-#define	AMD_IOMMU_EXCL_LIM		(51 << 16 | 12)
-
-/* Command Buffer Head Pointer Register bits */
-#define	AMD_IOMMU_CMDHEADPTR		(18 << 16 | 4)
-
-/* Command Buffer Tail Pointer Register bits */
-#define	AMD_IOMMU_CMDTAILPTR		(18 << 16 | 4)
-
-/* Event Log Head Pointer Register bits */
-#define	AMD_IOMMU_EVENTHEADPTR		(18 << 16 | 4)
-
-/* Event Log Tail Pointer Register bits */
-#define	AMD_IOMMU_EVENTTAILPTR		(18 << 16 | 4)
-
-/* Status Register bits */
-#define	AMD_IOMMU_CMDBUF_RUN		(4 << 16 | 4)
-#define	AMD_IOMMU_EVENT_LOG_RUN		(3 << 16 | 3)
-#define	AMD_IOMMU_COMWAIT_INT		(2 << 16 | 2)
-#define	AMD_IOMMU_EVENT_LOG_INT		(1 << 16 | 1)
-#define	AMD_IOMMU_EVENT_OVERFLOW_INT	(0 << 16 | 0)
-
-/* Device Table Bits */
-
-/* size in bytes of each device table entry */
-#define	AMD_IOMMU_DEVTBL_ENTRY_SZ	(32)
-
-/* Interrupt Remapping related Device Table bits */
-#define	AMD_IOMMU_DEVTBL_LINT1PASS	((191-128) << 16 | (191-128))
-#define	AMD_IOMMU_DEVTBL_LINT0PASS	((190-128) << 16 | (190-128))
-#define	AMD_IOMMU_DEVTBL_INTCTL		((189-128) << 16 | (188-128))
-#define	AMD_IOMMU_DEVTBL_NMIPASS	((186-128) << 16 | (186-128))
-#define	AMD_IOMMU_DEVTBL_EXTINTPAS	((185-128) << 16 | (185-128))
-#define	AMD_IOMMU_DEVTBL_INITPASS	((184-128) << 16 | (184-128))
-#define	AMD_IOMMU_DEVTBL_INTR_ROOT	((179-128) << 16 | (134-128))
-#define	AMD_IOMMU_DEVTBL_IG		((133-128) << 16 | (133-128))
-#define	AMD_IOMMU_DEVTBL_INTTABLEN	((132-128) << 16 | (129-128))
-#define	AMD_IOMMU_DEVTBL_IV		((128-128) << 16 | (128-128))
-
-/* DMA Remapping related Device Table Bits */
-#define	AMD_IOMMU_DEVTBL_SYSMGT		((105-64) << 16 | (104-64))
-#define	AMD_IOMMU_DEVTBL_EX		((103-64) << 16 | (103-64))
-#define	AMD_IOMMU_DEVTBL_SD		((102-64) << 16 | (102-64))
-#define	AMD_IOMMU_DEVTBL_CACHE		((101-64) << 16 | (101-64))
-#define	AMD_IOMMU_DEVTBL_IOCTL		((100-64) << 16 | (99-64))
-#define	AMD_IOMMU_DEVTBL_SA		((98-64) << 16 | (98-64))
-#define	AMD_IOMMU_DEVTBL_SE		((97-64) << 16 | (97-64))
-#define	AMD_IOMMU_DEVTBL_IOTLB		((96-64) << 16 | (96-64))
-#define	AMD_IOMMU_DEVTBL_DOMAINID	((79-64) << 16 | (64-64))
-#define	AMD_IOMMU_DEVTBL_IW		(62 << 16 | 62)
-#define	AMD_IOMMU_DEVTBL_IR		(61 << 16 | 61)
-#define	AMD_IOMMU_DEVTBL_ROOT_PGTBL	(51 << 16 | 12)
-#define	AMD_IOMMU_DEVTBL_PG_MODE	(11 << 16 | 9)
-#define	AMD_IOMMU_DEVTBL_TV		(1 << 16 | 1)
-#define	AMD_IOMMU_DEVTBL_V		(0 << 16 | 0)
-
-#define	BUS_DEVFN_TO_BDF(b, devfn)	(devfn)
-#define	AMD_IOMMU_ALIAS_HASH_SZ		(256)
-
-#define	AMD_IOMMU_REG_ADDR_LOCKED	(0x1)
-
-/*
- * IOMMU Command bits
- */
-
-typedef enum {
-	AMD_IOMMU_CMD_INVAL = 0,
-	AMD_IOMMU_CMD_COMPL_WAIT,
-	AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
-	AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
-	AMD_IOMMU_CMD_INVAL_IOTLB_PAGES,
-	AMD_IOMMU_CMD_INVAL_INTR_TABLE,
-} amd_iommu_cmd_t;
-
-typedef enum {
-	AMD_IOMMU_CMD_FLAGS_NONE = 0,
-	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT = 1,
-	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_F = 2,
-	AMD_IOMMU_CMD_FLAGS_COMPL_WAIT_S = 4,
-	AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL = 8,
-	AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S = 16,
-	AMD_IOMMU_CMD_FLAGS_IOTLB_INVAL_S = 32
-} amd_iommu_cmd_flags_t;
-
-/* Common command bits */
-#define	AMD_IOMMU_CMD_OPCODE		(31 << 16 | 28)
-
-/* Completion Wait command bits */
-#define	AMD_IOMMU_CMD_COMPL_WAIT_S		(0 << 16 | 0)
-#define	AMD_IOMMU_CMD_COMPL_WAIT_I		(1 << 16 | 1)
-#define	AMD_IOMMU_CMD_COMPL_WAIT_F		(2 << 16 | 2)
-#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_LO	(31 << 16 | 3)
-#define	AMD_IOMMU_CMD_COMPL_WAIT_STORE_ADDR_HI	(19 << 16 | 0)
-
-/* Invalidate Device Table entry command bits */
-#define	AMD_IOMMU_CMD_INVAL_DEVTAB_DEVICEID		(15 << 16 | 0)
-
-/* Invalidate IOMMU Pages command bits */
-#define	AMD_IOMMU_CMD_INVAL_PAGES_DOMAINID		(15 << 16 | 0)
-#define	AMD_IOMMU_CMD_INVAL_PAGES_S			(0 << 16 | 0)
-#define	AMD_IOMMU_CMD_INVAL_PAGES_PDE			(1 << 16 | 1)
-#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_LO		(31 << 16 | 12)
-#define	AMD_IOMMU_CMD_INVAL_PAGES_ADDR_HI		(63 << 16 | 32)
-
-
-/* Invalidate IOTLB command bits */
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_DEVICEID		(15 << 16 | 0)
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_MAXPEND		(31 << 16 | 24)
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_QUEUEID		(15 << 16 | 0)
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_S			(0 << 16 | 0)
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_LO		(31 << 16 | 12)
-#define	AMD_IOMMU_CMD_INVAL_IOTLB_ADDR_HI		(31 << 16 | 0)
-
-#define	AMD_IOMMU_DEFAULT_MAXPEND			(10)
-
-/* Invalidate Interrupt Table bits */
-#define	AMD_IOMMU_CMD_INVAL_INTR_DEVICEID		(15 << 16 | 0)
-
-#if defined(__amd64)
-#define	dmac_cookie_addr	dmac_laddress
-#else
-#define	dmac_cookie_addr	dmac_address
-#endif
-
-#define	AMD_IOMMU_TABLE_ALIGN	((1ULL << 12) - 1)
-
-#define	AMD_IOMMU_MAX_DEVICEID	(0xFFFF)
-
-/*
- * DMA sync macros
- * TODO: optimize sync only small ranges
- */
-#define	SYNC_FORDEV(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORDEV)
-#define	SYNC_FORKERN(h)	(void) ddi_dma_sync(h, 0, 0, DDI_DMA_SYNC_FORKERNEL)
-
-#define	WAIT_SEC(s)	drv_usecwait(1000000*(s))
-
-#define	CMD2OFF(c)	((c) << 4)
-#define	OFF2CMD(o)	((o) >> 4)
-
-typedef union split {
-	uint64_t u64;
-	uint32_t u32[2];
-} split_t;
-
-#define	BITPOS_START(b)	((b) >> 16)
-#define	BITPOS_END(b)	((b) & 0xFFFF)
-
-#define	START_MASK64(s)	(((s) == 63) ? ~((uint64_t)0) : \
-	(uint64_t)((1ULL << ((s)+1)) - 1))
-#define	START_MASK32(s)	(((s) == 31) ? ~((uint32_t)0) : \
-	(uint32_t)((1ULL << ((s)+1)) - 1))
-#define	START_MASK16(s)	(((s) == 15) ? ~((uint16_t)0) : \
-	(uint16_t)((1ULL << ((s)+1)) - 1))
-#define	START_MASK8(s)	(((s) == 7) ? ~((uint8_t)0) : \
-	(uint8_t)((1ULL << ((s)+1)) - 1))
-
-#define	END_MASK(e)	((1ULL << (e)) - 1)
-
-#define	BIT_MASK64(s, e)	(uint64_t)(START_MASK64(s) & ~END_MASK(e))
-#define	BIT_MASK32(s, e)	(uint32_t)(START_MASK32(s) & ~END_MASK(e))
-#define	BIT_MASK16(s, e)	(uint16_t)(START_MASK16(s) & ~END_MASK(e))
-#define	BIT_MASK8(s, e)		(uint8_t)(START_MASK8(s) & ~END_MASK(e))
-
-#define	AMD_IOMMU_REG_GET64_IMPL(rp, b) \
-	(((*(rp)) & (START_MASK64(BITPOS_START(b)))) >> BITPOS_END(b))
-#define	AMD_IOMMU_REG_GET64(rp, b) 					 \
-	((amd_iommu_64bit_bug) ? amd_iommu_reg_get64_workaround(rp, b) : \
-	AMD_IOMMU_REG_GET64_IMPL(rp, b))
-#define	AMD_IOMMU_REG_GET32(rp, b) \
-	(((*(rp)) & (START_MASK32(BITPOS_START(b)))) >> BITPOS_END(b))
-#define	AMD_IOMMU_REG_GET16(rp, b) \
-	(((*(rp)) & (START_MASK16(BITPOS_START(b)))) >> BITPOS_END(b))
-#define	AMD_IOMMU_REG_GET8(rp, b) \
-	(((*(rp)) & (START_MASK8(BITPOS_START(b)))) >> BITPOS_END(b))
-
-#define	AMD_IOMMU_REG_SET64_IMPL(rp, b, v) \
-	((*(rp)) = \
-	(((uint64_t)(*(rp)) & ~(BIT_MASK64(BITPOS_START(b), BITPOS_END(b)))) \
-	| ((uint64_t)(v) << BITPOS_END(b))))
-
-#define	AMD_IOMMU_REG_SET64(rp, b, v) 			\
-	(void) ((amd_iommu_64bit_bug) ?			\
-	amd_iommu_reg_set64_workaround(rp, b, v) : 	\
-	AMD_IOMMU_REG_SET64_IMPL(rp, b, v))
-
-#define	AMD_IOMMU_REG_SET32(rp, b, v) \
-	((*(rp)) = \
-	(((uint32_t)(*(rp)) & ~(BIT_MASK32(BITPOS_START(b), BITPOS_END(b)))) \
-	| ((uint32_t)(v) << BITPOS_END(b))))
-
-#define	AMD_IOMMU_REG_SET16(rp, b, v) \
-	((*(rp)) = \
-	(((uint16_t)(*(rp)) & ~(BIT_MASK16(BITPOS_START(b), BITPOS_END(b)))) \
-	| ((uint16_t)(v) << BITPOS_END(b))))
-
-#define	AMD_IOMMU_REG_SET8(rp, b, v) \
-	((*(rp)) = \
-	(((uint8_t)(*(rp)) & ~(BIT_MASK8(BITPOS_START(b), BITPOS_END(b)))) \
-	| ((uint8_t)(v) << BITPOS_END(b))))
-
-/*
- * Cast a 64 bit pointer to a uint64_t *
- */
-#define	REGADDR64(a)	((uint64_t *)(uintptr_t)(a))
-
-typedef enum {
-	AMD_IOMMU_INTR_INVALID = 0,
-	AMD_IOMMU_INTR_TABLE,
-	AMD_IOMMU_INTR_ALLOCED,
-	AMD_IOMMU_INTR_HANDLER,
-	AMD_IOMMU_INTR_ENABLED
-} amd_iommu_intr_state_t;
-
-
-typedef struct amd_iommu {
-	kmutex_t aiomt_mutex;
-	kmutex_t aiomt_eventlock;
-	kmutex_t aiomt_cmdlock;
-	dev_info_t *aiomt_dip;
-	int aiomt_idx;
-	iommulib_handle_t aiomt_iommulib_handle;
-	iommulib_ops_t *aiomt_iommulib_ops;
-	uint32_t aiomt_cap_hdr;
-	uint8_t aiomt_npcache;
-	uint8_t aiomt_httun;
-	uint8_t aiomt_iotlb;
-	uint8_t aiomt_captype;
-	uint8_t aiomt_capid;
-	uint32_t aiomt_low_addr32;
-	uint32_t aiomt_hi_addr32;
-	uint64_t aiomt_reg_pa;
-	uint64_t aiomt_va;
-	uint64_t aiomt_reg_va;
-	uint32_t aiomt_range;
-	uint8_t aiomt_rng_bus;
-	uint8_t aiomt_first_devfn;
-	uint8_t aiomt_last_devfn;
-	uint8_t aiomt_rng_valid;
-	uint8_t aiomt_ht_unitid;
-	uint32_t aiomt_misc;
-	uint8_t aiomt_htatsresv;
-	uint8_t aiomt_vasize;
-	uint8_t aiomt_pasize;
-	uint8_t aiomt_msinum;
-	uint8_t aiomt_reg_pages;
-	uint32_t aiomt_reg_size;
-	uint32_t aiomt_devtbl_sz;
-	uint32_t aiomt_cmdbuf_sz;
-	uint32_t aiomt_eventlog_sz;
-	caddr_t aiomt_devtbl;
-	caddr_t aiomt_cmdbuf;
-	caddr_t aiomt_eventlog;
-	uint32_t *aiomt_cmd_tail;
-	uint32_t *aiomt_event_head;
-	ddi_dma_handle_t aiomt_dmahdl;
-	void *aiomt_dma_bufva;
-	uint64_t aiomt_dma_mem_realsz;
-	ddi_acc_handle_t aiomt_dma_mem_hdl;
-	ddi_dma_cookie_t aiomt_buf_dma_cookie;
-	uint_t aiomt_buf_dma_ncookie;
-	amd_iommu_intr_state_t aiomt_intr_state;
-	ddi_intr_handle_t *aiomt_intr_htable;
-	uint32_t aiomt_intr_htable_sz;
-	uint32_t aiomt_actual_intrs;
-	uint32_t aiomt_intr_cap;
-	uint64_t aiomt_reg_devtbl_va;
-	uint64_t aiomt_reg_cmdbuf_va;
-	uint64_t aiomt_reg_eventlog_va;
-	uint64_t aiomt_reg_ctrl_va;
-	uint64_t aiomt_reg_excl_base_va;
-	uint64_t aiomt_reg_excl_lim_va;
-	uint64_t aiomt_reg_cmdbuf_head_va;
-	uint64_t aiomt_reg_cmdbuf_tail_va;
-	uint64_t aiomt_reg_eventlog_head_va;
-	uint64_t aiomt_reg_eventlog_tail_va;
-	uint64_t aiomt_reg_status_va;
-	struct amd_iommu *aiomt_next;
-} amd_iommu_t;
-
-typedef struct amd_iommu_dma_devtbl_ent {
-	uint16_t de_domainid;
-	uint8_t de_R;
-	uint8_t de_W;
-	caddr_t de_root_pgtbl;
-	uint8_t de_pgmode;
-} amd_iommu_dma_devtbl_entry_t;
-
-typedef struct amd_iommu_alias {
-	uint16_t al_bdf;
-	uint16_t al_src_bdf;
-	struct amd_iommu_alias *al_next;
-} amd_iommu_alias_t;
-
-typedef struct amd_iommu_cmdargs {
-	uint64_t ca_addr;
-	uint16_t ca_domainid;
-	uint16_t ca_deviceid;
-} amd_iommu_cmdargs_t;
-
-struct amd_iommu_page_table;
-
-typedef struct amd_iommu_page_table_hash {
-	kmutex_t ampt_lock;
-	struct amd_iommu_page_table **ampt_hash;
-} amd_iommu_page_table_hash_t;
-
-typedef enum {
-	AMD_IOMMU_LOG_INVALID_OP = 0,
-	AMD_IOMMU_LOG_DISPLAY,
-	AMD_IOMMU_LOG_DISCARD
-} amd_iommu_log_op_t;
-
-typedef enum {
-	AMD_IOMMU_DEBUG_NONE = 0,
-	AMD_IOMMU_DEBUG_ALLOCHDL = 0x1,
-	AMD_IOMMU_DEBUG_FREEHDL = 0x2,
-	AMD_IOMMU_DEBUG_BIND = 0x4,
-	AMD_IOMMU_DEBUG_UNBIND = 0x8,
-	AMD_IOMMU_DEBUG_WIN = 0x10,
-	AMD_IOMMU_DEBUG_PAGE_TABLES = 0x20,
-	AMD_IOMMU_DEBUG_DEVTBL = 0x40,
-	AMD_IOMMU_DEBUG_CMDBUF = 0x80,
-	AMD_IOMMU_DEBUG_EVENTLOG = 0x100,
-	AMD_IOMMU_DEBUG_ACPI = 0x200,
-	AMD_IOMMU_DEBUG_PA2VA = 0x400,
-	AMD_IOMMU_DEBUG_TABLES = 0x800,
-	AMD_IOMMU_DEBUG_EXCL = 0x1000,
-	AMD_IOMMU_DEBUG_INTR = 0x2000
-} amd_iommu_debug_t;
-
-extern const char *amd_iommu_modname;
-extern kmutex_t amd_iommu_global_lock;
-extern amd_iommu_alias_t **amd_iommu_alias;
-extern amd_iommu_page_table_hash_t amd_iommu_page_table_hash;
-extern ddi_device_acc_attr_t amd_iommu_devacc;
-extern amd_iommu_debug_t amd_iommu_debug;
-
-extern uint8_t amd_iommu_htatsresv;
-extern uint8_t amd_iommu_vasize;
-extern uint8_t amd_iommu_pasize;
-extern int amd_iommu_64bit_bug;
-extern int amd_iommu_unity_map;
-extern int amd_iommu_no_RW_perms;
-extern int amd_iommu_no_unmap;
-extern int amd_iommu_pageva_inval_all;
-extern int amd_iommu_disable;
-extern char *amd_iommu_disable_list;
-
-extern uint64_t amd_iommu_reg_get64_workaround(uint64_t *regp, uint32_t bits);
-extern uint64_t amd_iommu_reg_set64_workaround(uint64_t *regp, uint32_t bits,
-    uint64_t value);
-
-int amd_iommu_cmd(amd_iommu_t *iommu, amd_iommu_cmd_t cmd,
-    amd_iommu_cmdargs_t *cmdargs, amd_iommu_cmd_flags_t flags, int lock_held);
-int amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt);
-void amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt);
-
-int amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op);
-void amd_iommu_read_boot_props(void);
-void amd_iommu_lookup_conf_props(dev_info_t *dip);
-
-#endif	/* _KERNEL */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _AMD_IOMMU_IMPL_H */
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_log.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,582 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/sunddi.h>
-#include <sys/amd_iommu.h>
-#include "amd_iommu_impl.h"
-#include "amd_iommu_log.h"
-
-
-static const char *
-get_hw_error(uint8_t type)
-{
-	const char *hwerr;
-
-	switch (type) {
-	case 0:
-		hwerr = "Reserved";
-		break;
-	case 1:
-		hwerr = "Master Abort";
-		break;
-	case 2:
-		hwerr = "Target Abort";
-		break;
-	case 3:
-		hwerr = "Data Error";
-		break;
-	default:
-		hwerr = "Unknown";
-		break;
-	}
-
-	return (hwerr);
-}
-
-const char *
-get_illegal_req(uint8_t type, uint8_t TR)
-{
-	const char *illreq;
-
-	switch (type) {
-	case 0:
-		illreq = (TR == 1) ? "Translation I=0/V=0/V=1&&TV=0" :
-		    "Read or Non-posted Write in INTR Range";
-		break;
-	case 1:
-		illreq = (TR == 1) ? "Translation INTR/Port-IO/SysMgt; OR"
-		    "Translation when SysMgt=11b/Port-IO when IOCTL=10b "
-		    "while V=1 && TV=0" :
-		    "Pre-translated transaction from device with I=0 or V=0";
-		break;
-	case 2:
-		illreq = (TR == 1) ? "Reserved":
-		    "Port-IO transaction for device with IoCtl = 00b";
-		break;
-	case 3:
-		illreq = (TR == 1) ? "Reserved":
-		    "Posted write to SysMgt with device SysMgt=00b "
-		    "OR SysMgt=10b && message not INTx "
-		    "OR Posted write to addr transaltion range with "
-		    "HtAtsResv=1";
-		break;
-	case 4:
-		illreq = (TR == 1) ? "Reserved":
-		    "Read request or non-posted write in SysMgt with "
-		    "device SysMgt=10b or 0xb"
-		    "OR Read request or non-posted write in "
-		    "addr translation range with HtAtsResv=1";
-		break;
-	case 5:
-		illreq = (TR == 1) ? "Reserved":
-		    "Posted write to Interrupt/EOI Range "
-		    "for device that has IntCtl=00b";
-		break;
-	case 6:
-		illreq = (TR == 1) ? "Reserved":
-		    "Posted write to reserved Interrupt Address Range";
-		break;
-	case 7:
-		illreq = (TR == 1) ? "Reserved":
-		    "transaction to SysMgt when SysMgt=11b OR "
-		    "transaction to Port-IO when IoCtl=10b while "
-		    "while V=1 TV=0";
-		break;
-	default:
-		illreq = "Unknown error";
-		break;
-	}
-	return (illreq);
-}
-
-static void
-devtab_illegal_entry(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint8_t TR;
-	uint8_t RZ;
-	uint8_t RW;
-	uint8_t I;
-	uint32_t vaddr_lo;
-	uint32_t vaddr_hi;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "devtab_illegal_entry";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_DEVICEID);
-
-	TR = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_TR);
-
-	RZ = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_RZ);
-
-	RW = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_RW);
-
-	I = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_INTR);
-
-	vaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_DEVTAB_ILL_VADDR_LO);
-
-	vaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal device table entry "
-	    "deviceid=%u, %s request, %s %s transaction, %s request, "
-	    "virtual address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    deviceid,
-	    TR == 1 ? "Translation" : "Transaction",
-	    RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding",
-	    RW == 1 ? "Write" : "Read",
-	    I == 1 ? "Interrupt" : "Memory",
-	    (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo));
-}
-
-static void
-io_page_fault(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint16_t domainid;
-	uint8_t TR;
-	uint8_t RZ;
-	uint8_t RW;
-	uint8_t PE;
-	uint8_t PR;
-	uint8_t I;
-	uint32_t vaddr_lo;
-	uint32_t vaddr_hi;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "io_page_fault";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_IO_PAGE_FAULT);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_IO_PGFAULT_DEVICEID);
-
-	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_TR);
-
-	RZ = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RZ);
-
-	PE = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PE);
-
-	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_RW);
-
-	PR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_PR);
-
-	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_IO_PGFAULT_INTR);
-
-	domainid = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_IO_PGFAULT_DOMAINID);
-
-	vaddr_lo = event[2];
-
-	vaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. IO Page Fault. "
-	    "deviceid=%u, %s request, %s, %s permissions, %s transaction, "
-	    "%s, %s request, domainid=%u, virtual address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    deviceid,
-	    TR == 1 ? "Translation" : "Transaction",
-	    RZ == 1 ? "Non-zero reserved bit" : "Illegal Level encoding",
-	    PE == 1 ? "did not have" : "had",
-	    RW == 1 ? "Write" : "Read",
-	    PR == 1 ? "Page present or Interrupt Remapped" :
-	    "Page not present or Interrupt Blocked",
-	    I == 1 ? "Interrupt" : "Memory",
-	    domainid,
-	    (void *)(uintptr_t)(((uint64_t)vaddr_hi) << 32 | vaddr_lo));
-}
-
-static void
-devtab_hw_error(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint8_t type;
-	uint8_t TR;
-	uint8_t RW;
-	uint8_t I;
-	uint32_t physaddr_lo;
-	uint32_t physaddr_hi;
-	const char *hwerr;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "devtab_hw_error";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_DEVTAB_HW_ERROR);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_DEVTAB_HWERR_DEVICEID);
-
-	type = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE);
-
-	hwerr = get_hw_error(type);
-
-	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_TR);
-
-	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_RW);
-
-	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_DEVTAB_HWERR_INTR);
-
-	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_DEVTAB_HWERR_PHYSADDR_LO);
-
-	physaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Device Table HW Error. "
-	    "deviceid=%u, HW error type: %s, %s request, %s transaction, "
-	    "%s request, physical address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    deviceid, hwerr,
-	    TR == 1 ? "Translation" : "Transaction",
-	    RW == 1 ? "Write" : "Read",
-	    I == 1 ? "Interrupt" : "Memory",
-	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
-}
-
-
-static void
-pgtable_hw_error(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint16_t domainid;
-	uint8_t type;
-	uint8_t TR;
-	uint8_t RW;
-	uint8_t I;
-	uint32_t physaddr_lo;
-	uint32_t physaddr_hi;
-	const char *hwerr;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "pgtable_hw_error";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_PGTABLE_HW_ERROR);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_PGTABLE_HWERR_DEVICEID);
-
-	type = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE);
-
-	hwerr = get_hw_error(type);
-
-	TR = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_TR);
-
-	RW = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_RW);
-
-	I = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_PGTABLE_HWERR_INTR);
-
-	domainid = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_PGTABLE_HWERR_DOMAINID);
-
-	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_PGTABLE_HWERR_PHYSADDR_LO);
-
-	physaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Page Table HW Error. "
-	    "deviceid=%u, HW error type: %s, %s request, %s transaction, "
-	    "%s request, domainid=%u, physical address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    deviceid, hwerr,
-	    TR == 1 ? "Translation" : "Transaction",
-	    RW == 1 ? "Write" : "Read",
-	    I == 1 ? "Interrupt" : "Memory",
-	    domainid,
-	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
-}
-
-static void
-cmdbuf_illegal_cmd(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint32_t physaddr_lo;
-	uint32_t physaddr_hi;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "cmdbuf_illegal_cmd";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD);
-
-	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD_PHYS_LO);
-
-	physaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Illegal IOMMU command. "
-	    "command physical address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
-}
-
-static void
-cmdbuf_hw_error(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint32_t physaddr_lo;
-	uint32_t physaddr_hi;
-	uint8_t type;
-	const char *hwerr;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "cmdbuf_hw_error";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_CMDBUF_HW_ERROR);
-
-	type = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_CMDBUF_HWERR_TYPE);
-
-	hwerr = get_hw_error(type);
-
-	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_CMDBUF_HWERR_PHYS_LO);
-
-	physaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. Command Buffer HW error. "
-	    "HW error type = %s, command buffer physical address = %p",
-	    f, driver, instance, iommu->aiomt_idx,
-	    hwerr,
-	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
-}
-
-static void
-iotlb_inval_to(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint32_t physaddr_lo;
-	uint32_t physaddr_hi;
-	uint8_t type;
-	const char *hwerr;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "iotlb_inval_to";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_DEVICEID);
-
-	/*
-	 * XXX bug in spec. Is the type field available +04 26:25 or is
-	 * it reserved
-	 */
-	type = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_TYPE);
-	hwerr = get_hw_error(type);
-
-	physaddr_lo = AMD_IOMMU_REG_GET32(&event[2],
-	    AMD_IOMMU_EVENT_IOTLB_INVAL_TO_PHYS_LO);
-
-	physaddr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %u "
-	    "IOTLB invalidation Timeout. "
-	    "HW error type = %s, invalidation command physical address = %p",
-	    f, driver, instance, iommu->aiomt_idx, deviceid,
-	    hwerr,
-	    (void *)(uintptr_t)(((uint64_t)physaddr_hi) << 32 | physaddr_lo));
-}
-
-static void
-device_illegal_req(amd_iommu_t *iommu, uint32_t *event)
-{
-	uint16_t deviceid;
-	uint8_t TR;
-	uint32_t addr_lo;
-	uint32_t addr_hi;
-	uint8_t type;
-	const char *reqerr;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "device_illegal_req";
-
-	ASSERT(AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE) ==
-	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ);
-
-	deviceid = AMD_IOMMU_REG_GET32(&event[0],
-	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_DEVICEID);
-
-	TR = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TR);
-
-	type = AMD_IOMMU_REG_GET32(&event[1],
-	    AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TYPE);
-
-	reqerr = get_illegal_req(type, TR);
-
-
-	addr_lo = event[2];
-	addr_hi = event[3];
-
-	cmn_err(CE_WARN, "%s: %s%d: idx = %d. deviceid = %d "
-	    "Illegal Device Request. "
-	    "Illegal Request type = %s, %s request, address accessed = %p",
-	    f, driver, instance, iommu->aiomt_idx, deviceid,
-	    reqerr,
-	    TR == 1 ? "Translation" : "Transaction",
-	    (void *)(uintptr_t)(((uint64_t)addr_hi) << 32 | addr_lo));
-}
-
-static void
-amd_iommu_process_one_event(amd_iommu_t *iommu)
-{
-	uint32_t event[4];
-	amd_iommu_event_t event_type;
-	int i;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "amd_iommu_process_one_event";
-
-	ASSERT(MUTEX_HELD(&iommu->aiomt_eventlock));
-
-	SYNC_FORKERN(iommu->aiomt_dmahdl);
-	for (i = 0; i < 4; i++) {
-		event[i] =  iommu->aiomt_event_head[i];
-	}
-
-	event_type = AMD_IOMMU_REG_GET32(&event[1], AMD_IOMMU_EVENT_TYPE);
-
-	switch (event_type) {
-	case AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY:
-		devtab_illegal_entry(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_IO_PAGE_FAULT:
-		io_page_fault(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_DEVTAB_HW_ERROR:
-		devtab_hw_error(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_PGTABLE_HW_ERROR:
-		pgtable_hw_error(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_CMDBUF_HW_ERROR:
-		cmdbuf_hw_error(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD:
-		cmdbuf_illegal_cmd(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_IOTLB_INVAL_TO:
-		iotlb_inval_to(iommu, event);
-		break;
-	case AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ:
-		device_illegal_req(iommu, event);
-		break;
-	default:
-		cmn_err(CE_WARN, "%s: %s%d: idx = %d. Unknown event: %u",
-		    f, driver, instance, iommu->aiomt_idx, event_type);
-		break;
-	}
-}
-
-int
-amd_iommu_read_log(amd_iommu_t *iommu, amd_iommu_log_op_t op)
-{
-	caddr_t evtail;
-	uint64_t evtail_off;
-	uint64_t evhead_off;
-
-	ASSERT(op != AMD_IOMMU_LOG_INVALID_OP);
-
-	mutex_enter(&iommu->aiomt_eventlock);
-
-	ASSERT(iommu->aiomt_event_head != NULL);
-
-	/* XXX verify */
-	evtail_off = AMD_IOMMU_REG_GET64(
-	    REGADDR64(iommu->aiomt_reg_eventlog_tail_va),
-	    AMD_IOMMU_EVENTTAILPTR);
-
-	evtail_off = EV2OFF(evtail_off);
-
-	ASSERT(evtail_off <  iommu->aiomt_eventlog_sz);
-
-	evtail = iommu->aiomt_eventlog + evtail_off;
-
-	if (op == AMD_IOMMU_LOG_DISCARD) {
-		/*LINTED*/
-		iommu->aiomt_event_head = (uint32_t *)evtail;
-		AMD_IOMMU_REG_SET64(REGADDR64(
-		    iommu->aiomt_reg_eventlog_head_va),
-		    AMD_IOMMU_EVENTHEADPTR, OFF2EV(evtail_off));
-		cmn_err(CE_NOTE, "Discarded IOMMU event log");
-		mutex_exit(&iommu->aiomt_eventlock);
-		return (DDI_SUCCESS);
-	}
-
-	/*LINTED*/
-	while (1) {
-		if ((caddr_t)iommu->aiomt_event_head == evtail)
-			break;
-
-		cmn_err(CE_WARN, "evtail_off = %p, head = %p, tail = %p",
-		    (void *)(uintptr_t)evtail_off,
-		    (void *)iommu->aiomt_event_head,
-		    (void *)evtail);
-
-		amd_iommu_process_one_event(iommu);
-
-		/*
-		 * Update the head pointer in soft state
-		 * and the head pointer register
-		 */
-		iommu->aiomt_event_head += 4;
-		if ((caddr_t)iommu->aiomt_event_head >=
-		    iommu->aiomt_eventlog + iommu->aiomt_eventlog_sz) {
-			/* wraparound */
-			iommu->aiomt_event_head =
-			/*LINTED*/
-			    (uint32_t *)iommu->aiomt_eventlog;
-			evhead_off = 0;
-		} else {
-			evhead_off =  (caddr_t)iommu->aiomt_event_head
-			/*LINTED*/
-			    - iommu->aiomt_eventlog;
-		}
-
-		ASSERT(evhead_off < iommu->aiomt_eventlog_sz);
-
-		AMD_IOMMU_REG_SET64(REGADDR64(
-		    iommu->aiomt_reg_eventlog_head_va),
-		    AMD_IOMMU_EVENTHEADPTR, OFF2EV(evhead_off));
-	}
-	mutex_exit(&iommu->aiomt_eventlock);
-
-	return (DDI_SUCCESS);
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_log.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _AMD_IOMMU_LOG_H
-#define	_AMD_IOMMU_LOG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/amd_iommu.h>
-
-#ifdef _KERNEL
-
-#define	EV2OFF(e)	((e) << 4)
-#define	OFF2EV(o)	((o) >> 4)
-
-typedef enum {
-	AMD_IOMMU_EVENT_INVALID = 0,
-	AMD_IOMMU_EVENT_DEVTAB_ILLEGAL_ENTRY = 1,
-	AMD_IOMMU_EVENT_IO_PAGE_FAULT = 2,
-	AMD_IOMMU_EVENT_DEVTAB_HW_ERROR = 3,
-	AMD_IOMMU_EVENT_PGTABLE_HW_ERROR = 4,
-	AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD = 5,
-	AMD_IOMMU_EVENT_CMDBUF_HW_ERROR = 6,
-	AMD_IOMMU_EVENT_IOTLB_INVAL_TO = 7,
-	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ = 8
-} amd_iommu_event_t;
-
-/* Common to all events */
-#define	AMD_IOMMU_EVENT_TYPE			(31 << 16 | 28)
-
-/* Illegal device Table Entry Event bits */
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_TR		(24 << 16 | 24)
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_RZ		(23 << 16 | 23)
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_RW		(21 << 16 | 21)
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_INTR		(19 << 16 | 19)
-#define	AMD_IOMMU_EVENT_DEVTAB_ILL_VADDR_LO	(31 << 16 | 2)
-
-/* IO Page Fault event bits */
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_TR		(24 << 16 | 24)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_RZ		(23 << 16 | 23)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_PE		(22 << 16 | 22)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_RW		(21 << 16 | 21)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_PR		(20 << 16 | 20)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_INTR		(19 << 16 | 19)
-#define	AMD_IOMMU_EVENT_IO_PGFAULT_DOMAINID	(15 << 16 | 0)
-
-
-/* Device Table HW Error event bits */
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE	(26 << 16 | 25)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TR		(24 << 16 | 24)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_RW		(21 << 16 | 21)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_INTR	(19 << 16 | 19)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_PHYSADDR_LO	(31 << 16 | 4)
-
-
-/* Page Table HW Error event bits */
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_DEVTAB_HWERR_TYPE	(26 << 16 | 25)
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_TR	(24 << 16 | 24)
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_RW	(21 << 16 | 21)
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_INTR	(19 << 16 | 19)
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_DOMAINID  (15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_PGTABLE_HWERR_PHYSADDR_LO	(31 << 16 | 3)
-
-/* Illegal Command Error event bits */
-#define	AMD_IOMMU_EVENT_CMDBUF_ILLEGAL_CMD_PHYS_LO	(31 << 16 | 4)
-
-/* Command Buffer HW Error event bits */
-#define	AMD_IOMMU_EVENT_CMDBUF_HWERR_TYPE	(26 << 16 | 25)
-#define	AMD_IOMMU_EVENT_CMDBUF_HWERR_PHYS_LO	(31 << 16 | 4)
-
-
-/* IOTLB Invalidation TO event bits */
-#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_TYPE	(26 << 16 | 25)
-#define	AMD_IOMMU_EVENT_IOTLB_INVAL_TO_PHYS_LO	(31 << 16 | 4)
-
-/* Illegal Device request event bits */
-#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_DEVICEID	(15 << 16 | 0)
-#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TYPE		(27 << 16 | 25)
-#define	AMD_IOMMU_EVENT_DEVICE_ILLEGAL_REQ_TR		(24 << 16 | 24)
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _AMD_IOMMU_LOG_H */
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_page_tables.c	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1699 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/sunddi.h>
-#include <sys/sunndi.h>
-#include <sys/acpi/acpi.h>
-#include <sys/acpica.h>
-#include <sys/amd_iommu.h>
-#include <sys/bootconf.h>
-#include <sys/sysmacros.h>
-#include <sys/ddidmareq.h>
-
-#include "amd_iommu_impl.h"
-#include "amd_iommu_acpi.h"
-#include "amd_iommu_page_tables.h"
-
-ddi_dma_attr_t amd_iommu_pgtable_dma_attr = {
-	DMA_ATTR_V0,
-	0U,				/* dma_attr_addr_lo */
-	0xffffffffffffffffULL,		/* dma_attr_addr_hi */
-	0xffffffffU,			/* dma_attr_count_max */
-	(uint64_t)4096,			/* dma_attr_align */
-	1,				/* dma_attr_burstsizes */
-	64,				/* dma_attr_minxfer */
-	0xffffffffU,			/* dma_attr_maxxfer */
-	0xffffffffU,			/* dma_attr_seg */
-	1,				/* dma_attr_sgllen, variable */
-	64,				/* dma_attr_granular */
-	0				/* dma_attr_flags */
-};
-
-static amd_iommu_domain_t **amd_iommu_domain_table;
-
-static struct {
-	int f_count;
-	amd_iommu_page_table_t *f_list;
-} amd_iommu_pgtable_freelist;
-int amd_iommu_no_pgtable_freelist;
-
-/*ARGSUSED*/
-static int
-amd_iommu_get_src_bdf(amd_iommu_t *iommu, int32_t bdf, int32_t *src_bdfp)
-{
-	amd_iommu_acpi_ivhd_t *hinfop;
-
-	hinfop = amd_iommu_lookup_ivhd(bdf);
-	if (hinfop == NULL || hinfop->ach_src_deviceid == -1)
-		*src_bdfp = bdf;
-	else
-		*src_bdfp = hinfop->ach_src_deviceid;
-
-	return (DDI_SUCCESS);
-}
-
-static dev_info_t *
-amd_iommu_pci_dip(dev_info_t *rdip, const char *path)
-{
-	dev_info_t *pdip;
-	const char *driver = ddi_driver_name(rdip);
-	int instance = ddi_get_instance(rdip);
-	const char *f = "amd_iommu_pci_dip";
-
-	/* Hold rdip so it and its parents don't go away */
-	ndi_hold_devi(rdip);
-
-	if (ddi_is_pci_dip(rdip))
-		return (rdip);
-
-	pdip = rdip;
-	while (pdip = ddi_get_parent(pdip)) {
-		if (ddi_is_pci_dip(pdip)) {
-			ndi_hold_devi(pdip);
-			ndi_rele_devi(rdip);
-			return (pdip);
-		}
-	}
-
-	cmn_err(CE_WARN, "%s: %s%d dip = %p has no PCI parent, path = %s",
-	    f, driver, instance, (void *)rdip, path);
-
-	ndi_rele_devi(rdip);
-
-	ASSERT(0);
-
-	return (NULL);
-}
-
-/*ARGSUSED*/
-static int
-amd_iommu_get_domain(amd_iommu_t *iommu, dev_info_t *rdip, int alias,
-    uint16_t deviceid, domain_id_t *domainid, const char *path)
-{
-	const char *f = "amd_iommu_get_domain";
-
-	*domainid = AMD_IOMMU_INVALID_DOMAIN;
-
-	ASSERT(strcmp(ddi_driver_name(rdip), "agpgart") != 0);
-
-	switch (deviceid) {
-		case AMD_IOMMU_INVALID_DOMAIN:
-		case AMD_IOMMU_IDENTITY_DOMAIN:
-		case AMD_IOMMU_PASSTHRU_DOMAIN:
-		case AMD_IOMMU_SYS_DOMAIN:
-			*domainid = AMD_IOMMU_SYS_DOMAIN;
-			break;
-		default:
-			*domainid = deviceid;
-			break;
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_NOTE, "%s: domainid for %s = %d",
-		    f, path, *domainid);
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static uint16_t
-hash_domain(domain_id_t domainid)
-{
-	return (domainid % AMD_IOMMU_DOMAIN_HASH_SZ);
-}
-
-/*ARGSUSED*/
-void
-amd_iommu_init_page_tables(amd_iommu_t *iommu)
-{
-	amd_iommu_domain_table = kmem_zalloc(
-	    sizeof (amd_iommu_domain_t *) * AMD_IOMMU_DOMAIN_HASH_SZ, KM_SLEEP);
-}
-
-/*ARGSUSED*/
-void
-amd_iommu_fini_page_tables(amd_iommu_t *iommu)
-{
-	if (amd_iommu_domain_table) {
-		kmem_free(amd_iommu_domain_table,
-		    sizeof (amd_iommu_domain_t *) * AMD_IOMMU_DOMAIN_HASH_SZ);
-		amd_iommu_domain_table = NULL;
-	}
-}
-
-static amd_iommu_domain_t *
-amd_iommu_lookup_domain(amd_iommu_t *iommu, domain_id_t domainid,
-    map_type_t type, int km_flags)
-{
-	uint16_t idx;
-	amd_iommu_domain_t *dp;
-	char name[AMD_IOMMU_VMEM_NAMELEN+1];
-
-	ASSERT(amd_iommu_domain_table);
-
-	idx = hash_domain(domainid);
-
-	for (dp = amd_iommu_domain_table[idx]; dp; dp = dp->d_next) {
-		if (dp->d_domainid == domainid)
-			return (dp);
-	}
-
-	ASSERT(type != AMD_IOMMU_INVALID_MAP);
-
-	dp = kmem_zalloc(sizeof (*dp), km_flags);
-	if (dp == NULL)
-		return (NULL);
-	dp->d_domainid = domainid;
-	dp->d_pgtable_root_4K = 0;	/* make this explicit */
-
-	if (type == AMD_IOMMU_VMEM_MAP) {
-		uint64_t base;
-		uint64_t size;
-		(void) snprintf(name, sizeof (name), "dvma_idx%d_domain%d",
-		    iommu->aiomt_idx, domainid);
-		base = MMU_PAGESIZE;
-		size = AMD_IOMMU_SIZE_4G - MMU_PAGESIZE;
-		dp->d_vmem = vmem_create(name, (void *)(uintptr_t)base, size,
-		    MMU_PAGESIZE, NULL, NULL, NULL, 0,
-		    km_flags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
-		if (dp->d_vmem == NULL) {
-			kmem_free(dp, sizeof (*dp));
-			return (NULL);
-		}
-	} else {
-		dp->d_vmem = NULL;
-	}
-
-	dp->d_next = amd_iommu_domain_table[idx];
-	dp->d_prev = NULL;
-	amd_iommu_domain_table[idx] = dp;
-	if (dp->d_next)
-		dp->d_next->d_prev = dp;
-	dp->d_ref = 0;
-
-
-	return (dp);
-}
-
-static void
-amd_iommu_teardown_domain(amd_iommu_t *iommu, amd_iommu_domain_t *dp)
-{
-	uint16_t idx;
-	int flags;
-	amd_iommu_cmdargs_t cmdargs = {0};
-	domain_id_t domainid = dp->d_domainid;
-	const char *f = "amd_iommu_teardown_domain";
-
-	ASSERT(dp->d_ref == 0);
-
-	idx = hash_domain(dp->d_domainid);
-
-	if (dp->d_prev == NULL)
-		amd_iommu_domain_table[idx] = dp->d_next;
-	else
-		dp->d_prev->d_next = dp->d_next;
-
-	if (dp->d_next)
-		dp->d_next->d_prev = dp->d_prev;
-
-	if (dp->d_vmem != NULL) {
-		vmem_destroy(dp->d_vmem);
-		dp->d_vmem = NULL;
-	}
-
-	kmem_free(dp, sizeof (*dp));
-
-	cmdargs.ca_domainid = (uint16_t)domainid;
-	cmdargs.ca_addr = (uintptr_t)0x7FFFFFFFFFFFF000;
-	flags = AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL |
-	    AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S;
-
-	if (amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
-	    &cmdargs, flags, 0) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: idx=%d: domainid=%d"
-		    "Failed to invalidate domain in IOMMU HW cache",
-		    f, iommu->aiomt_idx, cmdargs.ca_domainid);
-	}
-}
-
-static int
-amd_iommu_get_deviceid(amd_iommu_t *iommu, dev_info_t *rdip, int32_t *deviceid,
-    int *aliasp, const char *path)
-{
-	int bus = -1;
-	int device = -1;
-	int func = -1;
-	uint16_t bdf;
-	int32_t src_bdf;
-	dev_info_t *idip = iommu->aiomt_dip;
-	const char *driver = ddi_driver_name(idip);
-	int instance = ddi_get_instance(idip);
-	dev_info_t *pci_dip;
-	const char *f = "amd_iommu_get_deviceid";
-
-	/* be conservative. Always assume an alias */
-	*aliasp = 1;
-	*deviceid = 0;
-
-	/* Check for special special devices (rdip == NULL) */
-	if (rdip == NULL) {
-		if (amd_iommu_get_src_bdf(iommu, -1, &src_bdf) != DDI_SUCCESS) {
-			cmn_err(CE_WARN,
-			    "%s: %s%d: idx=%d, failed to get SRC BDF "
-			    "for special-device",
-			    f, driver, instance, iommu->aiomt_idx);
-			return (DDI_DMA_NOMAPPING);
-		}
-		*deviceid = src_bdf;
-		*aliasp = 1;
-		return (DDI_SUCCESS);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_NOTE, "%s: attempting to get deviceid for %s",
-		    f, path);
-	}
-
-	pci_dip = amd_iommu_pci_dip(rdip, path);
-	if (pci_dip == NULL) {
-		cmn_err(CE_WARN, "%s: %s%d: idx = %d, failed to get PCI dip "
-		    "for rdip=%p, path = %s",
-		    f, driver, instance, iommu->aiomt_idx, (void *)rdip,
-		    path);
-		return (DDI_DMA_NOMAPPING);
-	}
-
-	if (acpica_get_bdf(pci_dip, &bus, &device, &func) != DDI_SUCCESS) {
-		ndi_rele_devi(pci_dip);
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d, failed to get BDF for "
-		    "PCI dip (%p). rdip path = %s",
-		    f, driver, instance, iommu->aiomt_idx,
-		    (void *)pci_dip, path);
-		return (DDI_DMA_NOMAPPING);
-	}
-
-	ndi_rele_devi(pci_dip);
-
-	if (bus > UINT8_MAX || bus < 0 ||
-	    device > UINT8_MAX || device < 0 ||
-	    func > UINT8_MAX || func < 0) {
-		cmn_err(CE_WARN, "%s: %s%d:  idx=%d, invalid BDF(%d,%d,%d) "
-		    "for PCI dip (%p). rdip path = %s", f, driver, instance,
-		    iommu->aiomt_idx,
-		    bus, device, func,
-		    (void *)pci_dip, path);
-		return (DDI_DMA_NOMAPPING);
-	}
-
-	bdf = ((uint8_t)bus << 8) | ((uint8_t)device << 3) | (uint8_t)func;
-
-	if (amd_iommu_get_src_bdf(iommu, bdf, &src_bdf) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d, failed to get SRC BDF "
-		    "for PCI dip (%p) rdip path = %s.",
-		    f, driver, instance, iommu->aiomt_idx, (void *)pci_dip,
-		    path);
-		return (DDI_DMA_NOMAPPING);
-	}
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_NOTE, "%s: Deviceid = %u for path = %s",
-		    f, src_bdf, path);
-	}
-
-	*deviceid = src_bdf;
-	*aliasp = (src_bdf != bdf);
-
-	return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static int
-init_devtbl(amd_iommu_t *iommu, uint64_t *devtbl_entry, domain_id_t domainid,
-    amd_iommu_domain_t *dp)
-{
-	uint64_t entry[4] = {0};
-	int i;
-
-	/* If already passthru, don't touch */
-	if (AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_V) == 0 &&
-	    AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_TV) == 0) {
-		return (0);
-	}
-
-	if (AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_V) == 1 &&
-	    AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_TV) == 1) {
-
-		ASSERT(dp->d_pgtable_root_4K ==
-		    AMD_IOMMU_REG_GET64(&(devtbl_entry[0]),
-		    AMD_IOMMU_DEVTBL_ROOT_PGTBL));
-
-		ASSERT(dp->d_domainid == AMD_IOMMU_REG_GET64(&(devtbl_entry[1]),
-		    AMD_IOMMU_DEVTBL_DOMAINID));
-
-		return (0);
-	}
-
-	/* New devtbl entry for this domain. Bump up the domain ref-count */
-	dp->d_ref++;
-
-	entry[3] = 0;
-	entry[2] = 0;
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_SYSMGT, 1);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_EX, 1);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_SD, 0);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_CACHE, 0);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_IOCTL, 1);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_SA, 0);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_SE, 1);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_IOTLB, 1);
-	AMD_IOMMU_REG_SET64(&(entry[1]), AMD_IOMMU_DEVTBL_DOMAINID,
-	    (uint16_t)domainid);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_IW, 1);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_IR, 1);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_ROOT_PGTBL,
-	    dp->d_pgtable_root_4K);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_PG_MODE,
-	    AMD_IOMMU_PGTABLE_MAXLEVEL);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_TV,
-	    domainid == AMD_IOMMU_PASSTHRU_DOMAIN ? 0 : 1);
-	AMD_IOMMU_REG_SET64(&(entry[0]), AMD_IOMMU_DEVTBL_V,
-	    domainid == AMD_IOMMU_PASSTHRU_DOMAIN ? 0 : 1);
-
-	for (i = 1; i < 4; i++) {
-		devtbl_entry[i] = entry[i];
-	}
-	devtbl_entry[0] = entry[0];
-
-	/* we did an actual init */
-	return (1);
-}
-
-void
-amd_iommu_set_passthru(amd_iommu_t *iommu, dev_info_t *rdip)
-{
-	int32_t deviceid;
-	int alias;
-	uint64_t *devtbl_entry;
-	amd_iommu_cmdargs_t cmdargs = {0};
-	char *path;
-	int pathfree;
-	int V;
-	int TV;
-	int instance;
-	const char *driver;
-	const char *f = "amd_iommu_set_passthru";
-
-	if (rdip) {
-		driver = ddi_driver_name(rdip);
-		instance = ddi_get_instance(rdip);
-	} else {
-		driver = "special-device";
-		instance = 0;
-	}
-
-	path = kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
-	if (path) {
-		if (rdip)
-			(void) ddi_pathname(rdip, path);
-		else
-			(void) strcpy(path, "special-device");
-		pathfree = 1;
-	} else {
-		pathfree = 0;
-		path = "<path-mem-alloc-failed>";
-	}
-
-	if (amd_iommu_get_deviceid(iommu, rdip, &deviceid, &alias, path)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p. "
-		    "Failed to get device ID for device %s.", f, driver,
-		    instance,
-		    iommu->aiomt_idx, (void *)rdip, path);
-		goto out;
-	}
-
-	/* No deviceid */
-	if (deviceid == -1) {
-		goto out;
-	}
-
-	if ((deviceid + 1) * AMD_IOMMU_DEVTBL_ENTRY_SZ >
-	    iommu->aiomt_devtbl_sz) {
-		cmn_err(CE_WARN, "%s: %s%d: IOMMU idx=%d, deviceid (%u) "
-		    "for rdip (%p) exceeds device table size (%u), path=%s",
-		    f, driver,
-		    instance, iommu->aiomt_idx, deviceid, (void *)rdip,
-		    iommu->aiomt_devtbl_sz, path);
-		goto out;
-	}
-
-	/*LINTED*/
-	devtbl_entry = (uint64_t *)&iommu->aiomt_devtbl
-	    [deviceid * AMD_IOMMU_DEVTBL_ENTRY_SZ];
-
-	V = AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_V);
-	TV = AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_TV);
-
-	/* Already passthru */
-	if (V == 0 && TV == 0) {
-		goto out;
-	}
-
-	/* Existing translations */
-	if (V == 1 && TV == 1) {
-		goto out;
-	}
-
-	/* Invalid setting */
-	if (V == 0 && TV == 1) {
-		goto out;
-	}
-
-	AMD_IOMMU_REG_SET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_V, 0);
-
-	cmdargs.ca_deviceid = (uint16_t)deviceid;
-	(void) amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
-	    &cmdargs, 0, 0);
-
-out:
-	if (pathfree)
-		kmem_free(path, MAXPATHLEN);
-}
-
-static int
-amd_iommu_set_devtbl_entry(amd_iommu_t *iommu, dev_info_t *rdip,
-    domain_id_t domainid, uint16_t deviceid, amd_iommu_domain_t *dp,
-    const char *path)
-{
-	uint64_t *devtbl_entry;
-	amd_iommu_cmdargs_t cmdargs = {0};
-	int error;
-	dev_info_t *idip = iommu->aiomt_dip;
-	const char *driver = ddi_driver_name(idip);
-	int instance = ddi_get_instance(idip);
-	const char *f = "amd_iommu_set_devtbl_entry";
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: attempting to set devtbl entry for %s",
-		    f, path);
-	}
-
-	if ((deviceid + 1) * AMD_IOMMU_DEVTBL_ENTRY_SZ >
-	    iommu->aiomt_devtbl_sz) {
-		cmn_err(CE_WARN, "%s: %s%d: IOMMU idx=%d, deviceid (%u) "
-		    "for rdip (%p) exceeds device table size (%u), path=%s",
-		    f, driver,
-		    instance, iommu->aiomt_idx, deviceid, (void *)rdip,
-		    iommu->aiomt_devtbl_sz, path);
-		return (DDI_DMA_NOMAPPING);
-	}
-
-	/*LINTED*/
-	devtbl_entry = (uint64_t *)&iommu->aiomt_devtbl
-	    [deviceid * AMD_IOMMU_DEVTBL_ENTRY_SZ];
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: deviceid=%u devtbl entry (%p) for %s",
-		    f, deviceid, (void *)(uintptr_t)(*devtbl_entry), path);
-	}
-
-	if (init_devtbl(iommu, devtbl_entry, domainid, dp)) {
-		cmdargs.ca_deviceid = deviceid;
-		error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
-		    &cmdargs, 0, 0);
-	}
-
-	return (error);
-}
-
-int
-amd_iommu_clear_devtbl_entry(amd_iommu_t *iommu, dev_info_t *rdip,
-    domain_id_t domainid, uint16_t deviceid, amd_iommu_domain_t *dp,
-    int *domain_freed, char *path)
-{
-	uint64_t *devtbl_entry;
-	int error = DDI_SUCCESS;
-	amd_iommu_cmdargs_t cmdargs = {0};
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "amd_iommu_clear_devtbl_entry";
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_NOTE, "%s: attempting to clear devtbl entry for "
-		    "domainid = %d, deviceid = %u, path = %s",
-		    f, domainid, deviceid, path);
-	}
-
-	if ((deviceid + 1) * AMD_IOMMU_DEVTBL_ENTRY_SZ >
-	    iommu->aiomt_devtbl_sz) {
-		cmn_err(CE_WARN, "%s: %s%d: IOMMU idx=%d, deviceid (%u) "
-		    "for rdip (%p) exceeds device table size (%u), path = %s",
-		    f, driver, instance,
-		    iommu->aiomt_idx, deviceid, (void *)rdip,
-		    iommu->aiomt_devtbl_sz, path);
-		return (DDI_FAILURE);
-	}
-
-	/*LINTED*/
-	devtbl_entry = (uint64_t *)&iommu->aiomt_devtbl
-	    [deviceid * AMD_IOMMU_DEVTBL_ENTRY_SZ];
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_DEVTBL) {
-		cmn_err(CE_WARN, "%s: deviceid=%u devtbl entry (%p) for %s",
-		    f, deviceid, (void *)(uintptr_t)(*devtbl_entry), path);
-	}
-
-	if (AMD_IOMMU_REG_GET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_TV) == 0) {
-		/* Nothing to do */
-		return (DDI_SUCCESS);
-	}
-
-	ASSERT(dp->d_pgtable_root_4K == AMD_IOMMU_REG_GET64(&(devtbl_entry[0]),
-	    AMD_IOMMU_DEVTBL_ROOT_PGTBL));
-
-	ASSERT(domainid == AMD_IOMMU_REG_GET64(&(devtbl_entry[1]),
-	    AMD_IOMMU_DEVTBL_DOMAINID));
-
-	AMD_IOMMU_REG_SET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_TV, 0);
-	AMD_IOMMU_REG_SET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_ROOT_PGTBL, 0);
-	AMD_IOMMU_REG_SET64(&(devtbl_entry[0]), AMD_IOMMU_DEVTBL_V, 1);
-
-	SYNC_FORDEV(iommu->aiomt_dmahdl);
-
-	dp->d_ref--;
-	ASSERT(dp->d_ref >= 0);
-
-	if (dp->d_ref == 0) {
-		*domain_freed = 1;
-	}
-
-	cmdargs.ca_deviceid = deviceid;
-	error = amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_DEVTAB_ENTRY,
-	    &cmdargs, 0, 0);
-	if (error != DDI_SUCCESS)
-		error = DDI_FAILURE;
-
-	return (error);
-}
-
-int
-amd_iommu_page_table_hash_init(amd_iommu_page_table_hash_t *ampt)
-{
-	ampt->ampt_hash = kmem_zalloc(sizeof (amd_iommu_page_table_t *) *
-	    AMD_IOMMU_PGTABLE_HASH_SZ, KM_SLEEP);
-	return (DDI_SUCCESS);
-}
-
-void
-amd_iommu_page_table_hash_fini(amd_iommu_page_table_hash_t *ampt)
-{
-	kmem_free(ampt->ampt_hash,
-	    sizeof (amd_iommu_page_table_t *) * AMD_IOMMU_PGTABLE_HASH_SZ);
-	ampt->ampt_hash = NULL;
-}
-
-static uint32_t
-pt_hashfn(uint64_t pa_4K)
-{
-	return (pa_4K % AMD_IOMMU_PGTABLE_HASH_SZ);
-}
-
-static void
-amd_iommu_insert_pgtable_hash(amd_iommu_page_table_t *pt)
-{
-	uint64_t pa_4K = ((uint64_t)pt->pt_cookie.dmac_cookie_addr) >> 12;
-	uint32_t idx = pt_hashfn(pa_4K);
-
-	ASSERT((pt->pt_cookie.dmac_cookie_addr & AMD_IOMMU_PGTABLE_ALIGN) == 0);
-
-	mutex_enter(&amd_iommu_page_table_hash.ampt_lock);
-
-	pt->pt_next = amd_iommu_page_table_hash.ampt_hash[idx];
-	pt->pt_prev = NULL;
-	amd_iommu_page_table_hash.ampt_hash[idx] = pt;
-	if (pt->pt_next)
-		pt->pt_next->pt_prev = pt;
-
-	mutex_exit(&amd_iommu_page_table_hash.ampt_lock);
-}
-
-static void
-amd_iommu_remove_pgtable_hash(amd_iommu_page_table_t *pt)
-{
-	uint64_t pa_4K = (pt->pt_cookie.dmac_cookie_addr >> 12);
-	uint32_t idx = pt_hashfn(pa_4K);
-
-	ASSERT((pt->pt_cookie.dmac_cookie_addr & AMD_IOMMU_PGTABLE_ALIGN) == 0);
-
-	mutex_enter(&amd_iommu_page_table_hash.ampt_lock);
-
-	if (pt->pt_next)
-		pt->pt_next->pt_prev = pt->pt_prev;
-
-	if (pt->pt_prev)
-		pt->pt_prev->pt_next = pt->pt_next;
-	else
-		amd_iommu_page_table_hash.ampt_hash[idx] = pt->pt_next;
-
-	pt->pt_next = NULL;
-	pt->pt_prev = NULL;
-
-	mutex_exit(&amd_iommu_page_table_hash.ampt_lock);
-}
-
-static amd_iommu_page_table_t *
-amd_iommu_lookup_pgtable_hash(domain_id_t domainid, uint64_t pgtable_pa_4K)
-{
-	amd_iommu_page_table_t *pt;
-	uint32_t idx = pt_hashfn(pgtable_pa_4K);
-
-	mutex_enter(&amd_iommu_page_table_hash.ampt_lock);
-	pt = amd_iommu_page_table_hash.ampt_hash[idx];
-	for (; pt; pt = pt->pt_next) {
-		if (domainid != pt->pt_domainid)
-			continue;
-		ASSERT((pt->pt_cookie.dmac_cookie_addr &
-		    AMD_IOMMU_PGTABLE_ALIGN) == 0);
-		if ((pt->pt_cookie.dmac_cookie_addr >> 12) == pgtable_pa_4K) {
-			break;
-		}
-	}
-	mutex_exit(&amd_iommu_page_table_hash.ampt_lock);
-
-	return (pt);
-}
-
-/*ARGSUSED*/
-static amd_iommu_page_table_t *
-amd_iommu_lookup_pgtable(amd_iommu_t *iommu, amd_iommu_page_table_t *ppt,
-    amd_iommu_domain_t *dp, int level, uint16_t index)
-{
-	uint64_t *pdtep;
-	uint64_t pgtable_pa_4K;
-
-	ASSERT(level > 0 && level <= AMD_IOMMU_PGTABLE_MAXLEVEL);
-	ASSERT(dp);
-
-	if (level == AMD_IOMMU_PGTABLE_MAXLEVEL) {
-		ASSERT(ppt == NULL);
-		ASSERT(index == 0);
-		pgtable_pa_4K = dp->d_pgtable_root_4K;
-	} else {
-		ASSERT(ppt);
-		pdtep = &(ppt->pt_pgtblva[index]);
-		if (AMD_IOMMU_REG_GET64(pdtep, AMD_IOMMU_PTDE_PR) == 0) {
-			if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-				cmn_err(CE_NOTE, "Skipping PR=0 pdte: 0x%"
-				    PRIx64, *pdtep);
-			}
-			return (NULL);
-		}
-		pgtable_pa_4K = AMD_IOMMU_REG_GET64(pdtep, AMD_IOMMU_PTDE_ADDR);
-	}
-
-	return (amd_iommu_lookup_pgtable_hash(dp->d_domainid, pgtable_pa_4K));
-}
-
-static amd_iommu_page_table_t *
-amd_iommu_alloc_from_freelist(void)
-{
-	int i;
-	uint64_t *pte_array;
-	amd_iommu_page_table_t *pt;
-
-	if (amd_iommu_no_pgtable_freelist == 1)
-		return (NULL);
-
-	if (amd_iommu_pgtable_freelist.f_count == 0)
-		return (NULL);
-
-	pt = amd_iommu_pgtable_freelist.f_list;
-	amd_iommu_pgtable_freelist.f_list = pt->pt_next;
-	amd_iommu_pgtable_freelist.f_count--;
-
-	pte_array = pt->pt_pgtblva;
-	for (i = 0; i < AMD_IOMMU_PGTABLE_SZ / (sizeof (*pte_array)); i++) {
-		ASSERT(pt->pt_pte_ref[i] == 0);
-		ASSERT(AMD_IOMMU_REG_GET64(&(pte_array[i]),
-		    AMD_IOMMU_PTDE_PR)  == 0);
-	}
-
-	return (pt);
-}
-
-static int
-amd_iommu_alloc_pgtable(amd_iommu_t *iommu, domain_id_t domainid,
-    const char *path, amd_iommu_page_table_t **ptp, int km_flags)
-{
-	int err;
-	uint_t ncookies;
-	amd_iommu_page_table_t *pt;
-	dev_info_t *idip = iommu->aiomt_dip;
-	const char *driver = ddi_driver_name(idip);
-	int instance = ddi_get_instance(idip);
-	const char *f = "amd_iommu_alloc_pgtable";
-
-	*ptp = NULL;
-
-	pt = amd_iommu_alloc_from_freelist();
-	if (pt)
-		goto init_pgtable;
-
-	pt = kmem_zalloc(sizeof (amd_iommu_page_table_t), km_flags);
-	if (pt == NULL)
-		return (DDI_DMA_NORESOURCES);
-
-	/*
-	 * Each page table is 4K in size
-	 */
-	pt->pt_mem_reqsz = AMD_IOMMU_PGTABLE_SZ;
-
-	/*
-	 * Alloc a DMA handle. Use the IOMMU dip as we want this DMA
-	 * to *not* enter the IOMMU - no recursive entrance.
-	 */
-	err = ddi_dma_alloc_handle(idip, &amd_iommu_pgtable_dma_attr,
-	    km_flags == KM_SLEEP ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
-	    NULL, &pt->pt_dma_hdl);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: domainid = %d, path = %s. "
-		    "Cannot alloc DMA handle for IO Page Table",
-		    f, driver, instance, domainid, path);
-		kmem_free(pt, sizeof (amd_iommu_page_table_t));
-		return (err == DDI_DMA_NORESOURCES ? err : DDI_DMA_NOMAPPING);
-	}
-
-	/*
-	 * Alloc memory for IO Page Table.
-	 * XXX remove size_t cast kludge
-	 */
-	err = ddi_dma_mem_alloc(pt->pt_dma_hdl, pt->pt_mem_reqsz,
-	    &amd_iommu_devacc, DDI_DMA_CONSISTENT|IOMEM_DATA_UNCACHED,
-	    km_flags == KM_SLEEP ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
-	    NULL, (caddr_t *)&pt->pt_pgtblva,
-	    (size_t *)&pt->pt_mem_realsz, &pt->pt_mem_hdl);
-	if (err != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: domainid=%d, path = %s. "
-		    "Cannot allocate DMA memory for IO Page table",
-		    f, driver, instance, domainid, path);
-		ddi_dma_free_handle(&pt->pt_dma_hdl);
-		kmem_free(pt, sizeof (amd_iommu_page_table_t));
-		return (DDI_DMA_NORESOURCES);
-	}
-
-	/*
-	 * The Page table DMA VA must be 4K aligned and
-	 * size >= than requested memory.
-	 *
-	 */
-	ASSERT(((uint64_t)(uintptr_t)pt->pt_pgtblva & AMD_IOMMU_PGTABLE_ALIGN)
-	    == 0);
-	ASSERT(pt->pt_mem_realsz >= pt->pt_mem_reqsz);
-
-	/*
-	 * Now bind the handle
-	 */
-	err = ddi_dma_addr_bind_handle(pt->pt_dma_hdl, NULL,
-	    (caddr_t)pt->pt_pgtblva, pt->pt_mem_realsz,
-	    DDI_DMA_READ | DDI_DMA_CONSISTENT,
-	    km_flags == KM_SLEEP ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
-	    NULL, &pt->pt_cookie, &ncookies);
-	if (err != DDI_DMA_MAPPED) {
-		cmn_err(CE_WARN, "%s: %s%d: domainid=%d, path = %s. "
-		    "Cannot bind memory for DMA to IO Page Tables. "
-		    "bufrealsz=%p",
-		    f, driver, instance, domainid, path,
-		    (void *)(uintptr_t)pt->pt_mem_realsz);
-		ddi_dma_mem_free(&pt->pt_mem_hdl);
-		ddi_dma_free_handle(&pt->pt_dma_hdl);
-		kmem_free(pt, sizeof (amd_iommu_page_table_t));
-		return (err == DDI_DMA_PARTIAL_MAP ? DDI_DMA_NOMAPPING :
-		    err);
-	}
-
-	/*
-	 * We assume the DMA engine on the IOMMU is capable of handling the
-	 * whole page table in a single cookie. If not and multiple cookies
-	 * are needed we fail.
-	 */
-	if (ncookies != 1) {
-		cmn_err(CE_WARN, "%s: %s%d: domainid = %d, path=%s "
-		    "Cannot handle multiple "
-		    "cookies for DMA to IO page Table, #cookies=%u",
-		    f, driver, instance, domainid, path, ncookies);
-		(void) ddi_dma_unbind_handle(pt->pt_dma_hdl);
-		ddi_dma_mem_free(&pt->pt_mem_hdl);
-		ddi_dma_free_handle(&pt->pt_dma_hdl);
-		kmem_free(pt, sizeof (amd_iommu_page_table_t));
-		return (DDI_DMA_NOMAPPING);
-	}
-
-init_pgtable:
-	/*
-	 * The address in the cookie must be 4K aligned and >= table size
-	 */
-	ASSERT(pt->pt_cookie.dmac_cookie_addr != NULL);
-	ASSERT((pt->pt_cookie.dmac_cookie_addr & AMD_IOMMU_PGTABLE_ALIGN) == 0);
-	ASSERT(pt->pt_cookie.dmac_size >= pt->pt_mem_realsz);
-	ASSERT(pt->pt_cookie.dmac_size >= pt->pt_mem_reqsz);
-	ASSERT(pt->pt_mem_reqsz >= AMD_IOMMU_PGTABLE_SIZE);
-	ASSERT(pt->pt_mem_realsz >= pt->pt_mem_reqsz);
-	ASSERT(pt->pt_pgtblva);
-
-	pt->pt_domainid = AMD_IOMMU_INVALID_DOMAIN;
-	pt->pt_level = 0x7;
-	pt->pt_index = 0;
-	pt->pt_ref = 0;
-	pt->pt_next = NULL;
-	pt->pt_prev = NULL;
-	pt->pt_parent = NULL;
-
-	bzero(pt->pt_pgtblva, pt->pt_mem_realsz);
-	SYNC_FORDEV(pt->pt_dma_hdl);
-
-	amd_iommu_insert_pgtable_hash(pt);
-
-	*ptp = pt;
-
-	return (DDI_SUCCESS);
-}
-
-static int
-amd_iommu_move_to_freelist(amd_iommu_page_table_t *pt)
-{
-	if (amd_iommu_no_pgtable_freelist == 1)
-		return (DDI_FAILURE);
-
-	if (amd_iommu_pgtable_freelist.f_count ==
-	    AMD_IOMMU_PGTABLE_FREELIST_MAX)
-		return (DDI_FAILURE);
-
-	pt->pt_next = amd_iommu_pgtable_freelist.f_list;
-	amd_iommu_pgtable_freelist.f_list = pt;
-	amd_iommu_pgtable_freelist.f_count++;
-
-	return (DDI_SUCCESS);
-}
-
-static void
-amd_iommu_free_pgtable(amd_iommu_t *iommu, amd_iommu_page_table_t *pt)
-{
-	int i;
-	uint64_t *pte_array;
-	dev_info_t *dip = iommu->aiomt_dip;
-	int instance = ddi_get_instance(dip);
-	const char *driver = ddi_driver_name(dip);
-	const char *f = "amd_iommu_free_pgtable";
-
-	ASSERT(pt->pt_ref == 0);
-
-	amd_iommu_remove_pgtable_hash(pt);
-
-	pte_array = pt->pt_pgtblva;
-	for (i = 0; i < AMD_IOMMU_PGTABLE_SZ / (sizeof (*pte_array)); i++) {
-		ASSERT(pt->pt_pte_ref[i] == 0);
-		ASSERT(AMD_IOMMU_REG_GET64(&(pte_array[i]),
-		    AMD_IOMMU_PTDE_PR)  == 0);
-	}
-
-	if (amd_iommu_move_to_freelist(pt) == DDI_SUCCESS)
-		return;
-
-	/* Unbind the handle */
-	if (ddi_dma_unbind_handle(pt->pt_dma_hdl) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d, domainid=%d. "
-		    "Failed to unbind handle: %p for IOMMU Page Table",
-		    f, driver, instance, iommu->aiomt_idx, pt->pt_domainid,
-		    (void *)pt->pt_dma_hdl);
-	}
-	/* Free the table memory allocated for DMA */
-	ddi_dma_mem_free(&pt->pt_mem_hdl);
-
-	/* Free the DMA handle */
-	ddi_dma_free_handle(&pt->pt_dma_hdl);
-
-	kmem_free(pt, sizeof (amd_iommu_page_table_t));
-
-}
-
-static int
-init_pde(amd_iommu_page_table_t *ppt, amd_iommu_page_table_t *pt)
-{
-	uint64_t *pdep = &(ppt->pt_pgtblva[pt->pt_index]);
-	uint64_t next_pgtable_pa_4K = (pt->pt_cookie.dmac_cookie_addr) >> 12;
-
-	/* nothing to set. PDE is already set */
-	if (AMD_IOMMU_REG_GET64(pdep, AMD_IOMMU_PTDE_PR) == 1) {
-		ASSERT(PT_REF_VALID(ppt));
-		ASSERT(PT_REF_VALID(pt));
-		ASSERT(ppt->pt_pte_ref[pt->pt_index] == 0);
-		ASSERT(AMD_IOMMU_REG_GET64(pdep, AMD_IOMMU_PTDE_ADDR)
-		    == next_pgtable_pa_4K);
-		return (DDI_SUCCESS);
-	}
-
-	ppt->pt_ref++;
-	ASSERT(PT_REF_VALID(ppt));
-
-	/* Page Directories are always RW */
-	AMD_IOMMU_REG_SET64(pdep, AMD_IOMMU_PTDE_IW, 1);
-	AMD_IOMMU_REG_SET64(pdep, AMD_IOMMU_PTDE_IR, 1);
-	AMD_IOMMU_REG_SET64(pdep, AMD_IOMMU_PTDE_ADDR,
-	    next_pgtable_pa_4K);
-	pt->pt_parent = ppt;
-	AMD_IOMMU_REG_SET64(pdep, AMD_IOMMU_PTDE_NXT_LVL,
-	    pt->pt_level);
-	ppt->pt_pte_ref[pt->pt_index] = 0;
-	AMD_IOMMU_REG_SET64(pdep, AMD_IOMMU_PTDE_PR, 1);
-	SYNC_FORDEV(ppt->pt_dma_hdl);
-	ASSERT(AMD_IOMMU_REG_GET64(pdep, AMD_IOMMU_PTDE_PR) == 1);
-
-	return (DDI_SUCCESS);
-}
-
-static int
-init_pte(amd_iommu_page_table_t *pt, uint64_t pa, uint16_t index,
-    struct ddi_dma_req *dmareq)
-{
-	uint64_t *ptep = &(pt->pt_pgtblva[index]);
-	uint64_t pa_4K = pa >> 12;
-	int R;
-	int W;
-
-	/* nothing to set if PTE is already set */
-	if (AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_PR) == 1) {
-		/*
-		 * Adjust current permissions
-		 * DDI_DMA_WRITE means direction of DMA is MEM -> I/O
-		 * so that requires Memory READ permissions i.e. sense
-		 * is inverted.
-		 * Note: either or both of DD_DMA_READ/WRITE may be set
-		 */
-		if (amd_iommu_no_RW_perms == 0) {
-			R = AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_IR);
-			W = AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_IW);
-			if (R == 0 && ((dmareq->dmar_flags & DDI_DMA_WRITE) ||
-			    (dmareq->dmar_flags & DDI_DMA_RDWR))) {
-				AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IR, 1);
-			}
-			if (W  == 0 && ((dmareq->dmar_flags & DDI_DMA_READ) ||
-			    (dmareq->dmar_flags & DDI_DMA_RDWR))) {
-				AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IW, 1);
-			}
-		}
-		ASSERT(PT_REF_VALID(pt));
-		pt->pt_pte_ref[index]++;
-		ASSERT(AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_ADDR)
-		    == pa_4K);
-		return (DDI_SUCCESS);
-	}
-
-	pt->pt_ref++;
-	ASSERT(PT_REF_VALID(pt));
-
-	/* see comment above about inverting sense of RD/WR */
-	if (amd_iommu_no_RW_perms == 0) {
-		AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IR, 0);
-		AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IW, 0);
-		if (dmareq->dmar_flags & DDI_DMA_RDWR) {
-			AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IW, 1);
-			AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IR, 1);
-		} else {
-			if (dmareq->dmar_flags & DDI_DMA_WRITE) {
-				AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IR, 1);
-			}
-			if (dmareq->dmar_flags & DDI_DMA_READ) {
-				AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IW, 1);
-			}
-		}
-	} else {
-		AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IR, 1);
-		AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_IW, 1);
-	}
-
-	/* TODO what is correct for FC and U */
-	AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTE_FC, 0);
-	AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTE_U, 0);
-	AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_ADDR, pa_4K);
-	AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_NXT_LVL, 0);
-	ASSERT(pt->pt_pte_ref[index] == 0);
-	pt->pt_pte_ref[index] = 1;
-	AMD_IOMMU_REG_SET64(ptep, AMD_IOMMU_PTDE_PR, 1);
-	SYNC_FORDEV(pt->pt_dma_hdl);
-	ASSERT(AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_PR) == 1);
-
-	return (DDI_SUCCESS);
-}
-
-
-static void
-init_pt(amd_iommu_page_table_t *pt, amd_iommu_domain_t *dp,
-    int level, uint16_t index)
-{
-	ASSERT(dp);
-
-	if (level == AMD_IOMMU_PGTABLE_MAXLEVEL) {
-		dp->d_pgtable_root_4K = (pt->pt_cookie.dmac_cookie_addr) >> 12;
-	} else {
-		ASSERT(level >= 1 && level < AMD_IOMMU_PGTABLE_MAXLEVEL);
-	}
-
-	pt->pt_domainid = dp->d_domainid;
-	pt->pt_level = level;
-	pt->pt_index = index;
-}
-
-static int
-amd_iommu_setup_1_pgtable(amd_iommu_t *iommu, dev_info_t *rdip,
-    struct ddi_dma_req *dmareq,
-    domain_id_t domainid, amd_iommu_domain_t *dp,
-    amd_iommu_page_table_t *ppt,
-    uint16_t index, int level, uint64_t va, uint64_t pa,
-    amd_iommu_page_table_t **ptp,  uint16_t *next_idxp, const char *path,
-    int km_flags)
-{
-	int error;
-	amd_iommu_page_table_t *pt;
-	const char *driver = ddi_driver_name(rdip);
-	int instance = ddi_get_instance(rdip);
-	const char *f = "amd_iommu_setup_1_pgtable";
-
-	*ptp = NULL;
-	*next_idxp = 0;
-	error = DDI_SUCCESS;
-
-	ASSERT(level > 0 && level <= AMD_IOMMU_PGTABLE_MAXLEVEL);
-
-	ASSERT(dp);
-	if (level == AMD_IOMMU_PGTABLE_MAXLEVEL) {
-		ASSERT(ppt == NULL);
-		ASSERT(index == 0);
-	} else {
-		ASSERT(ppt);
-	}
-
-	/* Check if page table is already allocated */
-	if (pt = amd_iommu_lookup_pgtable(iommu, ppt, dp, level, index)) {
-		ASSERT(pt->pt_domainid == domainid);
-		ASSERT(pt->pt_level == level);
-		ASSERT(pt->pt_index == index);
-		goto out;
-	}
-
-	if ((error = amd_iommu_alloc_pgtable(iommu, domainid, path, &pt,
-	    km_flags)) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx = %u, domainid = %d, va = %p "
-		    "path = %s", f, driver, instance, iommu->aiomt_idx,
-		    domainid, (void *)(uintptr_t)va, path);
-		return (error);
-	}
-
-	ASSERT(dp->d_domainid == domainid);
-
-	init_pt(pt, dp, level, index);
-
-out:
-	if (level != AMD_IOMMU_PGTABLE_MAXLEVEL) {
-		error = init_pde(ppt, pt);
-	}
-
-	if (level == 1) {
-		ASSERT(error == DDI_SUCCESS);
-		error = init_pte(pt, pa, AMD_IOMMU_VA_BITS(va, level), dmareq);
-	} else {
-		*next_idxp = AMD_IOMMU_VA_BITS(va, level);
-		*ptp = pt;
-	}
-
-	return (error);
-}
-
-typedef enum {
-	PDTE_NOT_TORN = 0x1,
-	PDTE_TORN_DOWN = 0x2,
-	PGTABLE_TORN_DOWN = 0x4
-} pdte_tear_t;
-
-static pdte_tear_t
-amd_iommu_teardown_pdte(amd_iommu_t *iommu,
-    amd_iommu_page_table_t *pt, int index)
-{
-	uint8_t next_level;
-	pdte_tear_t retval;
-	uint64_t *ptdep = &(pt->pt_pgtblva[index]);
-
-	next_level = AMD_IOMMU_REG_GET64(ptdep,
-	    AMD_IOMMU_PTDE_NXT_LVL);
-
-	if (AMD_IOMMU_REG_GET64(ptdep, AMD_IOMMU_PTDE_PR) == 1) {
-		if (pt->pt_level == 1) {
-			ASSERT(next_level == 0);
-			/* PTE */
-			pt->pt_pte_ref[index]--;
-			if (pt->pt_pte_ref[index] != 0) {
-				return (PDTE_NOT_TORN);
-			}
-		} else {
-			ASSERT(next_level != 0 && next_level != 7);
-		}
-		ASSERT(pt->pt_pte_ref[index] == 0);
-		ASSERT(PT_REF_VALID(pt));
-
-		AMD_IOMMU_REG_SET64(ptdep, AMD_IOMMU_PTDE_PR, 0);
-		SYNC_FORDEV(pt->pt_dma_hdl);
-		ASSERT(AMD_IOMMU_REG_GET64(ptdep,
-		    AMD_IOMMU_PTDE_PR) == 0);
-		pt->pt_ref--;
-		ASSERT(PT_REF_VALID(pt));
-		retval = PDTE_TORN_DOWN;
-	} else {
-		ASSERT(0);
-		ASSERT(pt->pt_pte_ref[index] == 0);
-		ASSERT(PT_REF_VALID(pt));
-		retval = PDTE_NOT_TORN;
-	}
-
-	if (pt->pt_ref == 0) {
-		amd_iommu_free_pgtable(iommu, pt);
-		return (PGTABLE_TORN_DOWN);
-	}
-
-	return (retval);
-}
-
-static int
-amd_iommu_create_pgtables(amd_iommu_t *iommu, dev_info_t *rdip,
-    struct ddi_dma_req *dmareq, uint64_t va,
-    uint64_t pa, uint16_t deviceid, domain_id_t domainid,
-    amd_iommu_domain_t *dp, const char *path, int km_flags)
-{
-	int level;
-	uint16_t index;
-	uint16_t next_idx;
-	amd_iommu_page_table_t *pt;
-	amd_iommu_page_table_t *ppt;
-	int error;
-	const char *driver = ddi_driver_name(rdip);
-	int instance = ddi_get_instance(rdip);
-	const char *f = "amd_iommu_create_pgtables";
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_NOTE, "%s: %s%d: idx = %u, domainid = %d, "
-		    "deviceid = %u, va = %p, pa = %p, path = %s",
-		    f, driver, instance,
-		    iommu->aiomt_idx, domainid, deviceid,
-		    (void *)(uintptr_t)va,
-		    (void *)(uintptr_t)pa, path);
-	}
-
-	if (domainid == AMD_IOMMU_PASSTHRU_DOMAIN) {
-		/* No need for pagetables. Just set up device table entry */
-		goto passthru;
-	}
-
-	index = 0;
-	ppt = NULL;
-	for (level = AMD_IOMMU_PGTABLE_MAXLEVEL; level > 0;
-	    level--, pt = NULL, next_idx = 0) {
-		if ((error = amd_iommu_setup_1_pgtable(iommu, rdip, dmareq,
-		    domainid, dp, ppt, index, level, va, pa, &pt,
-		    &next_idx, path, km_flags)) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: %s%d: idx=%d: domainid=%d, "
-			    "deviceid=%u, va= %p, pa = %p, Failed to setup "
-			    "page table(s) at level = %d, path = %s.",
-			    f, driver, instance, iommu->aiomt_idx,
-			    domainid, deviceid, (void *)(uintptr_t)va,
-			    (void *)(uintptr_t)pa, level, path);
-			return (error);
-		}
-
-		if (level > 1) {
-			ASSERT(pt);
-			ASSERT(pt->pt_domainid == domainid);
-			ppt = pt;
-			index = next_idx;
-		} else {
-			ASSERT(level == 1);
-			ASSERT(pt == NULL);
-			ASSERT(next_idx == 0);
-			ppt = NULL;
-			index = 0;
-		}
-	}
-
-passthru:
-	if ((error = amd_iommu_set_devtbl_entry(iommu, rdip, domainid, deviceid,
-	    dp, path)) != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p, deviceid=%u, "
-		    "domainid=%d."
-		    "Failed to set device table entry for path %s.",
-		    f, driver, instance,
-		    iommu->aiomt_idx, (void *)rdip, deviceid, domainid, path);
-		return (error);
-	}
-
-	SYNC_FORDEV(iommu->aiomt_dmahdl);
-
-	return (DDI_SUCCESS);
-}
-
-static int
-amd_iommu_destroy_pgtables(amd_iommu_t *iommu, dev_info_t *rdip,
-    uint64_t pageva, uint16_t deviceid, domain_id_t domainid,
-    amd_iommu_domain_t *dp, map_type_t type, int *domain_freed, char *path)
-{
-	int level;
-	int flags;
-	amd_iommu_cmdargs_t cmdargs = {0};
-	uint16_t index;
-	uint16_t prev_index;
-	amd_iommu_page_table_t *pt;
-	amd_iommu_page_table_t *ppt;
-	pdte_tear_t retval;
-	int tear_level;
-	int invalidate_pte;
-	int invalidate_pde;
-	int error = DDI_FAILURE;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "amd_iommu_destroy_pgtables";
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_NOTE, "%s: %s%d: idx = %u, domainid = %d, "
-		    "deviceid = %u, va = %p, path = %s",
-		    f, driver, instance,
-		    iommu->aiomt_idx, domainid, deviceid,
-		    (void *)(uintptr_t)pageva, path);
-	}
-
-	if (domainid == AMD_IOMMU_PASSTHRU_DOMAIN) {
-		/*
-		 * there are no pagetables for the passthru domain.
-		 * Just the device table entry
-		 */
-		error = DDI_SUCCESS;
-		goto passthru;
-	}
-
-	ppt = NULL;
-	index = 0;
-	for (level = AMD_IOMMU_PGTABLE_MAXLEVEL; level > 0; level--) {
-		pt = amd_iommu_lookup_pgtable(iommu, ppt, dp, level, index);
-		if (pt) {
-			ppt = pt;
-			index = AMD_IOMMU_VA_BITS(pageva, level);
-			continue;
-		}
-		break;
-	}
-
-	if (level == 0) {
-		uint64_t *ptep;
-		uint64_t pa_4K;
-
-		ASSERT(pt);
-		ASSERT(pt == ppt);
-		ASSERT(pt->pt_domainid == dp->d_domainid);
-
-		ptep = &(pt->pt_pgtblva[index]);
-
-		pa_4K = AMD_IOMMU_REG_GET64(ptep, AMD_IOMMU_PTDE_ADDR);
-		if (amd_iommu_unity_map || type == AMD_IOMMU_UNITY_MAP) {
-			ASSERT(pageva == (pa_4K << MMU_PAGESHIFT));
-		}
-	}
-
-	tear_level = -1;
-	invalidate_pde = 0;
-	invalidate_pte = 0;
-	for (++level; level <= AMD_IOMMU_PGTABLE_MAXLEVEL; level++) {
-		prev_index = pt->pt_index;
-		ppt = pt->pt_parent;
-		retval = amd_iommu_teardown_pdte(iommu, pt, index);
-		switch (retval) {
-			case PDTE_NOT_TORN:
-				goto invalidate;
-			case PDTE_TORN_DOWN:
-				invalidate_pte = 1;
-				goto invalidate;
-			case PGTABLE_TORN_DOWN:
-				invalidate_pte = 1;
-				invalidate_pde = 1;
-				tear_level = level;
-				break;
-		}
-		index = prev_index;
-		pt = ppt;
-	}
-
-invalidate:
-	/*
-	 * Now teardown the IOMMU HW caches if applicable
-	 */
-	if (invalidate_pte) {
-		cmdargs.ca_domainid = (uint16_t)domainid;
-		if (amd_iommu_pageva_inval_all) {
-			cmdargs.ca_addr = (uintptr_t)0x7FFFFFFFFFFFF000;
-			flags = AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL |
-			    AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S;
-		} else if (invalidate_pde) {
-			cmdargs.ca_addr =
-			    (uintptr_t)AMD_IOMMU_VA_INVAL(pageva, tear_level);
-			flags = AMD_IOMMU_CMD_FLAGS_PAGE_PDE_INVAL |
-			    AMD_IOMMU_CMD_FLAGS_PAGE_INVAL_S;
-		} else {
-			cmdargs.ca_addr = (uintptr_t)pageva;
-			flags = 0;
-		}
-		if (amd_iommu_cmd(iommu, AMD_IOMMU_CMD_INVAL_IOMMU_PAGES,
-		    &cmdargs, flags, 0) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "%s: %s%d: idx=%d: domainid=%d, "
-			    "rdip=%p. Failed to invalidate IOMMU HW cache "
-			    "for %s", f, driver, instance,
-			    iommu->aiomt_idx, domainid, (void *)rdip, path);
-			error = DDI_FAILURE;
-			goto out;
-		}
-	}
-
-passthru:
-	if (tear_level ==  AMD_IOMMU_PGTABLE_MAXLEVEL) {
-		error = amd_iommu_clear_devtbl_entry(iommu, rdip, domainid,
-		    deviceid, dp, domain_freed, path);
-	} else {
-		error = DDI_SUCCESS;
-	}
-
-out:
-	SYNC_FORDEV(iommu->aiomt_dmahdl);
-
-	return (error);
-}
-
-static int
-cvt_bind_error(int error)
-{
-	switch (error) {
-	case DDI_DMA_MAPPED:
-	case DDI_DMA_PARTIAL_MAP:
-	case DDI_DMA_NORESOURCES:
-	case DDI_DMA_NOMAPPING:
-		break;
-	default:
-		cmn_err(CE_PANIC, "Unsupported error code: %d", error);
-		/*NOTREACHED*/
-	}
-	return (error);
-}
-
-int
-amd_iommu_map_pa2va(amd_iommu_t *iommu, dev_info_t *rdip, ddi_dma_attr_t *attrp,
-    struct ddi_dma_req *dmareq, uint64_t start_pa, uint64_t pa_sz,
-    map_type_t type, uint64_t *start_vap, int km_flags)
-{
-	pfn_t pfn_start;
-	pfn_t pfn_end;
-	pfn_t pfn;
-	int alias;
-	int32_t deviceid;
-	domain_id_t domainid;
-	amd_iommu_domain_t *dp;
-	uint64_t end_pa;
-	uint64_t start_va;
-	uint64_t end_va;
-	uint64_t pg_start;
-	uint64_t pg_end;
-	uint64_t pg;
-	uint64_t va_sz;
-	char *path;
-	int error = DDI_DMA_NOMAPPING;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "amd_iommu_map_pa2va";
-
-	ASSERT(pa_sz != 0);
-
-	*start_vap = 0;
-
-	ASSERT(rdip);
-
-	path = kmem_alloc(MAXPATHLEN, km_flags);
-	if (path == NULL) {
-		error = DDI_DMA_NORESOURCES;
-		goto out;
-	}
-	(void) ddi_pathname(rdip, path);
-
-	/*
-	 * First get deviceid
-	 */
-	if (amd_iommu_get_deviceid(iommu, rdip, &deviceid, &alias, path)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p. "
-		    "Failed to get device ID for %s.", f, driver, instance,
-		    iommu->aiomt_idx, (void *)rdip, path);
-		error = DDI_DMA_NOMAPPING;
-		goto out;
-	}
-
-	/*
-	 * Next get the domain for this rdip
-	 */
-	if (amd_iommu_get_domain(iommu, rdip, alias, deviceid, &domainid, path)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p, path=%s. "
-		    "Failed to get domain.", f, driver, instance,
-		    iommu->aiomt_idx, (void *)rdip, path);
-		error = DDI_DMA_NOMAPPING;
-		goto out;
-	}
-
-	dp = amd_iommu_lookup_domain(iommu, domainid, type, km_flags);
-	if (dp == NULL) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: domainid=%d, rdip=%p. "
-		    "Failed to get device ID for %s.", f, driver, instance,
-		    iommu->aiomt_idx, domainid, (void *)rdip, path);
-		error = DDI_DMA_NORESOURCES;
-		goto out;
-	}
-
-	ASSERT(dp->d_domainid == domainid);
-
-	pfn_start = start_pa >> MMU_PAGESHIFT;
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-		cmn_err(CE_NOTE, "pa = %p, pfn_new = %p, pfn_start = %p, "
-		    "pgshift = %d",
-		    (void *)(uintptr_t)start_pa,
-		    (void *)(uintptr_t)(start_pa >> MMU_PAGESHIFT),
-		    (void *)(uintptr_t)pfn_start, MMU_PAGESHIFT);
-	}
-
-	end_pa = start_pa + pa_sz - 1;
-	pfn_end = end_pa >> MMU_PAGESHIFT;
-
-	if (amd_iommu_unity_map || type == AMD_IOMMU_UNITY_MAP) {
-		start_va = start_pa;
-		end_va = end_pa;
-		va_sz = pa_sz;
-		*start_vap = start_va;
-	} else {
-		va_sz = mmu_ptob(pfn_end - pfn_start + 1);
-		start_va = (uintptr_t)vmem_xalloc(dp->d_vmem, va_sz,
-		    MAX(attrp->dma_attr_align, MMU_PAGESIZE),
-		    0,
-		    attrp->dma_attr_seg + 1,
-		    (void *)(uintptr_t)attrp->dma_attr_addr_lo,
-		    (void *)(uintptr_t)MIN((attrp->dma_attr_addr_hi + 1),
-		    AMD_IOMMU_SIZE_4G),	/* XXX rollover */
-		    km_flags == KM_SLEEP ? VM_SLEEP : VM_NOSLEEP);
-		if (start_va == 0) {
-			cmn_err(CE_WARN, "%s: No VA resources",
-			    amd_iommu_modname);
-			error = DDI_DMA_NORESOURCES;
-			goto out;
-		}
-		ASSERT((start_va & MMU_PAGEOFFSET) == 0);
-		end_va = start_va + va_sz - 1;
-		*start_vap = start_va + (start_pa & MMU_PAGEOFFSET);
-	}
-
-	pg_start = start_va >> MMU_PAGESHIFT;
-	pg_end = end_va >> MMU_PAGESHIFT;
-
-	pg = pg_start;
-	for (pfn = pfn_start; pfn <= pfn_end; pfn++, pg++) {
-
-		if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-			cmn_err(CE_WARN, "%s: attempting to create page tables "
-			    "for pfn = %p, va = %p, path = %s",
-			    f, (void *)(uintptr_t)(pfn << MMU_PAGESHIFT),
-			    (void *)(uintptr_t)(pg << MMU_PAGESHIFT), path);
-
-		}
-
-		if (amd_iommu_unity_map || type == AMD_IOMMU_UNITY_MAP) {
-			ASSERT(pfn == pg);
-		}
-
-		if ((error = amd_iommu_create_pgtables(iommu, rdip, dmareq,
-		    pg << MMU_PAGESHIFT,
-		    pfn << MMU_PAGESHIFT, deviceid, domainid, dp, path,
-		    km_flags)) != DDI_SUCCESS) {
-			cmn_err(CE_WARN, "Failed to create_pgtables");
-			goto out;
-		}
-
-		if (amd_iommu_debug & AMD_IOMMU_DEBUG_PAGE_TABLES) {
-			cmn_err(CE_WARN, "%s: successfuly created page tables "
-			    "for pfn = %p, vapg = %p, path = %s",
-			    f, (void *)(uintptr_t)pfn,
-			    (void *)(uintptr_t)pg, path);
-		}
-
-	}
-	ASSERT(pg == pg_end + 1);
-
-
-	if (amd_iommu_debug & AMD_IOMMU_DEBUG_PA2VA) {
-		cmn_err(CE_NOTE, "pa=%p, va=%p",
-		    (void *)(uintptr_t)start_pa,
-		    (void *)(uintptr_t)(*start_vap));
-	}
-	error = DDI_DMA_MAPPED;
-
-out:
-	kmem_free(path, MAXPATHLEN);
-	return (cvt_bind_error(error));
-}
-
-int
-amd_iommu_unmap_va(amd_iommu_t *iommu, dev_info_t *rdip, uint64_t start_va,
-    uint64_t va_sz, map_type_t type)
-{
-	uint64_t end_va;
-	uint64_t pg_start;
-	uint64_t pg_end;
-	uint64_t pg;
-	uint64_t actual_sz;
-	char *path;
-	int pathfree;
-	int alias;
-	int32_t deviceid;
-	domain_id_t domainid;
-	amd_iommu_domain_t *dp;
-	int error;
-	int domain_freed;
-	const char *driver = ddi_driver_name(iommu->aiomt_dip);
-	int instance = ddi_get_instance(iommu->aiomt_dip);
-	const char *f = "amd_iommu_unmap_va";
-
-	if (amd_iommu_no_unmap)
-		return (DDI_SUCCESS);
-
-	path = kmem_alloc(MAXPATHLEN, KM_NOSLEEP);
-	if (path) {
-		(void) ddi_pathname(rdip, path);
-		pathfree = 1;
-	} else {
-		pathfree = 0;
-		path = "<path-mem-alloc-failed>";
-	}
-
-	/*
-	 * First get deviceid
-	 */
-	if (amd_iommu_get_deviceid(iommu, rdip, &deviceid, &alias, path)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p. "
-		    "Failed to get device ID for %s.", f, driver, instance,
-		    iommu->aiomt_idx, (void *)rdip, path);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	/*
-	 * Next get the domain for this rdip
-	 */
-	if (amd_iommu_get_domain(iommu, rdip, alias, deviceid, &domainid, path)
-	    != DDI_SUCCESS) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: rdip=%p, path=%s. "
-		    "Failed to get domain.", f, driver, instance,
-		    iommu->aiomt_idx, (void *)rdip, path);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	/* should never result in domain allocation/vmem_create */
-	dp = amd_iommu_lookup_domain(iommu, domainid, AMD_IOMMU_INVALID_MAP,
-	    KM_NOSLEEP);
-	if (dp == NULL) {
-		cmn_err(CE_WARN, "%s: %s%d: idx=%d: domainid=%d, rdip=%p. "
-		    "Failed to get device ID for %s.", f, driver, instance,
-		    iommu->aiomt_idx, domainid, (void *)rdip, path);
-		error = DDI_FAILURE;
-		goto out;
-	}
-
-	ASSERT(dp->d_domainid == domainid);
-
-	pg_start = start_va >> MMU_PAGESHIFT;
-	end_va = start_va + va_sz - 1;
-	pg_end = end_va >> MMU_PAGESHIFT;
-	actual_sz = (pg_end - pg_start + 1) << MMU_PAGESHIFT;
-
-	domain_freed = 0;
-	for (pg = pg_start; pg <= pg_end; pg++) {
-		domain_freed = 0;
-		if (amd_iommu_destroy_pgtables(iommu, rdip,
-		    pg << MMU_PAGESHIFT, deviceid, domainid, dp, type,
-		    &domain_freed, path) != DDI_SUCCESS) {
-			error = DDI_FAILURE;
-			goto out;
-		}
-		if (domain_freed) {
-			ASSERT(pg == pg_end);
-			break;
-		}
-	}
-
-	/*
-	 * vmem_xalloc() must be paired with vmem_xfree
-	 */
-	if (type == AMD_IOMMU_VMEM_MAP && !amd_iommu_unity_map) {
-		vmem_xfree(dp->d_vmem,
-		    (void *)(uintptr_t)(pg_start << MMU_PAGESHIFT), actual_sz);
-	}
-
-	if (domain_freed)
-		amd_iommu_teardown_domain(iommu, dp);
-
-	error = DDI_SUCCESS;
-out:
-	if (pathfree)
-		kmem_free(path, MAXPATHLEN);
-	return (error);
-}
--- a/usr/src/uts/intel/io/amd_iommu/amd_iommu_page_tables.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _AMD_IOMMU_PAGE_TABLES_H
-#define	_AMD_IOMMU_PAGE_TABLES_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _KERNEL
-
-/* Common to PTEs and PDEs */
-#define	AMD_IOMMU_PTDE_IW		(62 << 16 | 62)
-#define	AMD_IOMMU_PTDE_IR		(61 << 16 | 61)
-#define	AMD_IOMMU_PTDE_ADDR		(51 << 16 | 12)
-#define	AMD_IOMMU_PTDE_NXT_LVL		(11 << 16 | 9)
-#define	AMD_IOMMU_PTDE_PR		(0 << 16 | 0)
-
-#define	AMD_IOMMU_PTE_FC		(60 << 16 | 60)
-#define	AMD_IOMMU_PTE_U			(59 << 16 | 59)
-
-#define	AMD_IOMMU_VA_NBITS(l)		((l) == 6 ? 7 : 9)
-#define	AMD_IOMMU_VA_BITMASK(l)		((1 << AMD_IOMMU_VA_NBITS(l)) - 1)
-#define	AMD_IOMMU_VA_SHIFT(v, l)	\
-	((v) >> (MMU_PAGESHIFT + (AMD_IOMMU_VA_NBITS(l - 1) * (l - 1))))
-#define	AMD_IOMMU_VA_BITS(v, l)		\
-	(AMD_IOMMU_VA_SHIFT(v, l) & AMD_IOMMU_VA_BITMASK(l))
-#define	AMD_IOMMU_VA_TOTBITS(l)		\
-	(((l) == 6 ? 7 + (l - 1) * 9: l*9) + MMU_PAGESHIFT)
-#define	AMD_IOMMU_VA_TOTMASK(l)		((1 << AMD_IOMMU_VA_TOTBITS(l)) - 1)
-#define	AMD_IOMMU_VA_INVAL_SETMASK(l)	\
-	(((1 << AMD_IOMMU_VA_TOTBITS(l)) - 1) >> 1)
-#define	AMD_IOMMU_VA_INVAL_CLRMASK(l)	\
-	(~(1 << (AMD_IOMMU_VA_TOTBITS(l) - 1)))
-#define	AMD_IOMMU_VA_INVAL(v, l)	\
-	(((v) & AMD_IOMMU_VA_INVAL_CLRMASK(l)) | AMD_IOMMU_VA_INVAL_SETMASK(l))
-
-#define	AMD_IOMMU_PGTABLE_SZ		(4096)
-#define	AMD_IOMMU_PGTABLE_MAXLEVEL	(6)
-#define	AMD_IOMMU_PGTABLE_HASH_SZ	(256)
-
-#define	AMD_IOMMU_PGTABLE_ALIGN		((1ULL << 12) - 1)
-#define	AMD_IOMMU_PGTABLE_SIZE		(1ULL << 12)
-
-#define	AMD_IOMMU_MAX_PDTE		(1ULL << AMD_IOMMU_VA_NBITS(1))
-#define	PT_REF_VALID(p)			((p)->pt_ref >= 0 && \
-					(p)->pt_ref <= AMD_IOMMU_MAX_PDTE)
-
-#define	AMD_IOMMU_DOMAIN_HASH_SZ	(256)
-#define	AMD_IOMMU_PGTABLE_FREELIST_MAX	(256)
-#define	AMD_IOMMU_PA2VA_HASH_SZ		(256)
-
-#define	AMD_IOMMU_SIZE_4G		((uint64_t)1 << 32)
-#define	AMD_IOMMU_VMEM_NAMELEN		(30)
-
-typedef enum {
-	AMD_IOMMU_INVALID_DOMAIN = 0,
-	AMD_IOMMU_IDENTITY_DOMAIN = 0xFFFD,
-	AMD_IOMMU_PASSTHRU_DOMAIN = 0xFFFE,
-	AMD_IOMMU_SYS_DOMAIN = 0xFFFF
-} domain_id_t;
-
-typedef enum {
-	AMD_IOMMU_INVALID_MAP = 0,
-	AMD_IOMMU_UNITY_MAP,
-	AMD_IOMMU_VMEM_MAP
-} map_type_t;
-
-typedef struct amd_iommu_page_table {
-	domain_id_t pt_domainid;
-	int pt_level;
-	ddi_dma_handle_t pt_dma_hdl;
-	ddi_acc_handle_t pt_mem_hdl;
-	uint64_t pt_mem_reqsz;
-	uint64_t pt_mem_realsz;
-	uint64_t *pt_pgtblva;
-	uint64_t pt_pte_ref[AMD_IOMMU_MAX_PDTE];
-	uint16_t pt_index;
-	int pt_ref;
-	ddi_dma_cookie_t pt_cookie;
-	struct amd_iommu_page_table *pt_next;
-	struct amd_iommu_page_table *pt_prev;
-	struct amd_iommu_page_table *pt_parent;
-} amd_iommu_page_table_t;
-
-typedef struct amd_iommu_domain {
-	domain_id_t d_domainid;
-	uint64_t d_pgtable_root_4K;
-	int64_t d_ref;
-	vmem_t *d_vmem;
-	struct amd_iommu_domain *d_prev;
-	struct amd_iommu_domain *d_next;
-} amd_iommu_domain_t;
-
-int amd_iommu_map_pa2va(amd_iommu_t *iommu, dev_info_t *rdip,
-    ddi_dma_attr_t *attrp, struct ddi_dma_req *dmareq,
-    uint64_t pa, uint64_t pa_sz, map_type_t type,
-    uint64_t *start_vap, int km_flags);
-int amd_iommu_unmap_va(amd_iommu_t *iommu, dev_info_t *rdip,
-    uint64_t va, uint64_t va_sz, map_type_t type);
-void amd_iommu_init_page_tables(amd_iommu_t *iommu);
-void amd_iommu_fini_page_tables(amd_iommu_t *iommu);
-void amd_iommu_set_passthru(amd_iommu_t *iommu, dev_info_t *rdip);
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif	/* _AMD_IOMMU_PAGE_TABLES_H */
--- a/usr/src/uts/intel/io/intel_nhm/intel_nhm.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/io/intel_nhm/intel_nhm.h	Mon Sep 21 11:26:40 2009 -0400
@@ -34,6 +34,10 @@
 #define	NHM_EP_CPU	0x2c408086
 #define	NHM_WS_CPU	0x2c418086
 #define	NHM_CPU_RAS	0x2c1a8086
+#define	NHM_JF_CPU	0x2c588086
+#define	NHM_JF_CPU_RAS	0x2cda8086
+#define	NHM_WM_CPU	0x2c708086
+#define	NHM_WM_CPU_RAS	0x2d9a8086
 
 #define	NHM_INTERCONNECT	"Intel QuickPath"
 
--- a/usr/src/uts/intel/io/intel_nhm/mem_addr.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/io/intel_nhm/mem_addr.c	Mon Sep 21 11:26:40 2009 -0400
@@ -749,9 +749,11 @@
 	first = 0;
 	last = MAX_CPU_NODES;
 	id = CPU_ID_RD(0);
-	if (id == NHM_EP_CPU || id == NHM_WS_CPU) {
+	if (id == NHM_EP_CPU || id == NHM_WS_CPU || id == NHM_JF_CPU ||
+	    id == NHM_WM_CPU) {
 		id = CPU_ID_RD(1);
-		if (id != NHM_EP_CPU && id !=  NHM_WS_CPU) {
+		if (id != NHM_EP_CPU && id != NHM_WS_CPU && id != NHM_JF_CPU &&
+		    id != NHM_WM_CPU) {
 			last = 1;
 		}
 	} else {
@@ -829,10 +831,12 @@
 	uint32_t rir_limit;
 	uint32_t rir_way;
 	uint32_t mc_control;
+	uint32_t id;
 	int nhm_slot;
 	int nhm_lastslot;
 	uint8_t	rank;
 	uint64_t base;
+	int ras_dev = 0;
 
 	nhm_slot = choose_cpu(&nhm_lastslot);
 
@@ -846,7 +850,10 @@
 	}
 
 	for (i = nhm_slot; i < nhm_lastslot; i++) {
-		if (MC_CPU_RAS_RD(i) == NHM_CPU_RAS) {
+		id = MC_CPU_RAS_RD(i);
+		if (id == NHM_CPU_RAS || id == NHM_JF_CPU_RAS ||
+		    id == NHM_WM_CPU_RAS) {
+			ras_dev = 1;
 			mc_ras_enables = MC_RAS_ENABLES_RD(i);
 			if (RAS_LOCKSTEP_ENABLE(mc_ras_enables))
 				lockstep[i] = 1;
@@ -923,7 +930,7 @@
 	}
 	mc_control = MC_CONTROL_RD(nhm_slot);
 	closed_page = MC_CONTROL_CLOSED_PAGE(mc_control);
-	if (MC_CPU_RAS_RD(nhm_slot) == NHM_CPU_RAS)
+	if (ras_dev)
 		ecc_enabled = MC_CONTROL_ECCEN(mc_control);
 	else if ((MC_STATUS_RD(nhm_slot) & WS_ECC_ENABLED) != 0)
 		ecc_enabled = 1;
--- a/usr/src/uts/intel/io/intel_nhm/nhm_init.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/io/intel_nhm/nhm_init.c	Mon Sep 21 11:26:40 2009 -0400
@@ -234,13 +234,15 @@
 	uint32_t mc_dimm_clk_ratio_status;
 	uint64_t cycle_time;
 	uint32_t interval;
+	uint32_t id;
 	int i;
 	int hw_scrub = 0;
 
 	if (ecc_enabled && (nhm_patrol_scrub || nhm_demand_scrub)) {
 		for (i = 0; i < MAX_MEMORY_CONTROLLERS; i++) {
-			if (MC_CPU_RAS_RD(i) != NHM_CPU_RAS ||
-			    nhm_memory_on_ctl[i] == 0)
+			id = MC_CPU_RAS_RD(i);
+			if ((id != NHM_CPU_RAS && id != NHM_JF_CPU_RAS &&
+			    id != NHM_WM_CPU_RAS) || nhm_memory_on_ctl[i] == 0)
 				continue;
 			mc_ssrcontrol = MC_SSR_CONTROL_RD(i);
 			if (nhm_demand_scrub &&
@@ -286,7 +288,8 @@
 	dimmpp = nhm_dimms;
 	for (i = 0; i < MAX_MEMORY_CONTROLLERS; i++) {
 		did = CPU_ID_RD(i);
-		if (did != NHM_EP_CPU && did != NHM_WS_CPU) {
+		if (did != NHM_EP_CPU && did != NHM_WS_CPU &&
+		    did != NHM_JF_CPU && did != NHM_WM_CPU) {
 			dimmpp += CHANNELS_PER_MEMORY_CONTROLLER *
 			    MAX_DIMMS_PER_CHANNEL;
 			continue;
@@ -324,10 +327,11 @@
 		return (ENOTSUP);
 	for (slot = 0; slot < MAX_CPU_NODES; slot++) {
 		nhm_chipset = CPU_ID_RD(slot);
-		if (nhm_chipset == NHM_EP_CPU || nhm_chipset == NHM_WS_CPU)
+		if (nhm_chipset == NHM_EP_CPU || nhm_chipset == NHM_WS_CPU ||
+		    nhm_chipset == NHM_JF_CPU || nhm_chipset == NHM_WM_CPU)
 			break;
 	}
-	if (nhm_chipset != NHM_EP_CPU && nhm_chipset != NHM_WS_CPU) {
+	if (slot == MAX_CPU_NODES) {
 		return (ENOTSUP);
 	}
 	mem_reg_init();
--- a/usr/src/uts/intel/io/pci/pci_boot.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/io/pci/pci_boot.c	Mon Sep 21 11:26:40 2009 -0400
@@ -44,6 +44,7 @@
 #include <sys/acpica.h>
 #include <sys/intel_iommu.h>
 #include <sys/iommulib.h>
+#include <sys/devcache.h>
 
 #define	pci_getb	(*pci_getb_func)
 #define	pci_getw	(*pci_getw_func)
@@ -134,6 +135,15 @@
 static void memlist_remove_list(struct memlist **list,
     struct memlist *remove_list);
 
+static void pci_scan_bbn(void);
+static int pci_unitaddr_cache_valid(void);
+static int pci_bus_unitaddr(int);
+static void pci_unitaddr_cache_create(void);
+
+static int pci_cache_unpack_nvlist(nvf_handle_t, nvlist_t *, char *);
+static int pci_cache_pack_nvlist(nvf_handle_t, nvlist_t **);
+static void pci_cache_free_list(nvf_handle_t);
+
 extern int pci_slot_names_prop(int, char *, int);
 
 /* set non-zero to force PCI peer-bus renumbering */
@@ -149,10 +159,285 @@
 } isa_res;
 
 /*
+ * PCI unit-address cache management
+ */
+static nvf_ops_t pci_unitaddr_cache_ops = {
+	"/etc/devices/pci_unitaddr_persistent",	/* path to cache */
+	pci_cache_unpack_nvlist,		/* read in nvlist form */
+	pci_cache_pack_nvlist,			/* convert to nvlist form */
+	pci_cache_free_list,			/* free data list */
+	NULL					/* write complete callback */
+};
+
+typedef struct {
+	list_node_t	pua_nodes;
+	int		pua_index;
+	int		pua_addr;
+} pua_node_t;
+
+nvf_handle_t	puafd_handle;
+int		pua_cache_valid = 0;
+
+
+/*ARGSUSED*/
+static ACPI_STATUS
+pci_process_acpi_device(ACPI_HANDLE hdl, UINT32 level, void *ctx, void **rv)
+{
+	ACPI_BUFFER	rb;
+	ACPI_OBJECT	ro;
+	ACPI_DEVICE_INFO *adi;
+
+	/*
+	 * Use AcpiGetObjectInfo() to find the device _HID
+	 * If not a PCI root-bus, ignore this device and continue
+	 * the walk
+	 */
+
+	rb.Length = ACPI_ALLOCATE_BUFFER;
+	if (ACPI_FAILURE(AcpiGetObjectInfo(hdl, &rb)))
+		return (AE_OK);
+
+	adi = rb.Pointer;
+	if (!(adi->Valid & ACPI_VALID_HID)) {
+		AcpiOsFree(adi);
+		return (AE_OK);
+	}
+
+	if (strncmp(adi->HardwareId.Value, PCI_ROOT_HID_STRING,
+	    sizeof (PCI_ROOT_HID_STRING)) &&
+	    strncmp(adi->HardwareId.Value, PCI_EXPRESS_ROOT_HID_STRING,
+	    sizeof (PCI_EXPRESS_ROOT_HID_STRING))) {
+		AcpiOsFree(adi);
+		return (AE_OK);
+	}
+
+	AcpiOsFree(adi);
+
+	/*
+	 * XXX: ancient Big Bear broken _BBN will result in two
+	 * bus 0 _BBNs being found, so we need to handle duplicate
+	 * bus 0 gracefully.  However, broken _BBN does not
+	 * hide a childless root-bridge so no need to work-around it
+	 * here
+	 */
+	rb.Pointer = &ro;
+	rb.Length = sizeof (ro);
+	if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, "_BBN",
+	    NULL, &rb, ACPI_TYPE_INTEGER))) {
+		/* PCI with _BBN, process it, go no deeper */
+		if (pci_bus_res[ro.Integer.Value].par_bus == (uchar_t)-1 &&
+		    pci_bus_res[ro.Integer.Value].dip == NULL)
+			create_root_bus_dip((uchar_t)ro.Integer.Value);
+		return (AE_CTRL_DEPTH);
+	}
+
+	/* PCI and no _BBN, continue walk */
+	return (AE_OK);
+}
+
+/*
+ * Scan the ACPI namespace for all top-level instances of _BBN
+ * in order to discover childless root-bridges (which enumeration
+ * may not find; root-bridges are inferred by the existence of
+ * children).  This scan should find all root-bridges that have
+ * been enumerated, and any childless root-bridges not enumerated.
+ * Root-bridge for bus 0 may not have a _BBN object.
+ */
+static void
+pci_scan_bbn()
+{
+	void *rv;
+
+	(void) AcpiGetDevices(NULL, pci_process_acpi_device, NULL, &rv);
+}
+
+static void
+pci_unitaddr_cache_init(void)
+{
+
+	puafd_handle = nvf_register_file(&pci_unitaddr_cache_ops);
+	ASSERT(puafd_handle);
+
+	list_create(nvf_list(puafd_handle), sizeof (pua_node_t),
+	    offsetof(pua_node_t, pua_nodes));
+
+	rw_enter(nvf_lock(puafd_handle), RW_WRITER);
+	(void) nvf_read_file(puafd_handle);
+	rw_exit(nvf_lock(puafd_handle));
+}
+
+/*
+ * Format of /etc/devices/pci_unitaddr_persistent:
+ *
+ * The persistent record of unit-address assignments contains
+ * a list of name/value pairs, where name is a string representation
+ * of the "index value" of the PCI root-bus and the value is
+ * the assigned unit-address.
+ *
+ * The "index value" is simply the zero-based index of the PCI
+ * root-buses ordered by physical bus number; first PCI bus is 0,
+ * second is 1, and so on.
+ */
+
+/*ARGSUSED*/
+static int
+pci_cache_unpack_nvlist(nvf_handle_t hdl, nvlist_t *nvl, char *name)
+{
+	long		index;
+	int32_t		value;
+	nvpair_t	*np;
+	pua_node_t	*node;
+
+	np = NULL;
+	while ((np = nvlist_next_nvpair(nvl, np)) != NULL) {
+		/* name of nvpair is index value */
+		if (ddi_strtol(nvpair_name(np), NULL, 10, &index) != 0)
+			continue;
+
+		if (nvpair_value_int32(np, &value) != 0)
+			continue;
+
+		node = kmem_zalloc(sizeof (pua_node_t), KM_SLEEP);
+		node->pua_index = index;
+		node->pua_addr = value;
+		list_insert_tail(nvf_list(hdl), node);
+	}
+
+	pua_cache_valid = 1;
+	return (DDI_SUCCESS);
+}
+
+static int
+pci_cache_pack_nvlist(nvf_handle_t hdl, nvlist_t **ret_nvl)
+{
+	int		rval;
+	nvlist_t	*nvl, *sub_nvl;
+	list_t		*listp;
+	pua_node_t	*pua;
+	char		buf[13];
+
+	ASSERT(RW_WRITE_HELD(nvf_lock(hdl)));
+
+	rval = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
+	if (rval != DDI_SUCCESS) {
+		nvf_error("%s: nvlist alloc error %d\n",
+		    nvf_cache_name(hdl), rval);
+		return (DDI_FAILURE);
+	}
+
+	sub_nvl = NULL;
+	rval = nvlist_alloc(&sub_nvl, NV_UNIQUE_NAME, KM_SLEEP);
+	if (rval != DDI_SUCCESS)
+		goto error;
+
+	listp = nvf_list(hdl);
+	for (pua = list_head(listp); pua != NULL;
+	    pua = list_next(listp, pua)) {
+		(void) snprintf(buf, sizeof (buf), "%d", pua->pua_index);
+		rval = nvlist_add_int32(sub_nvl, buf, pua->pua_addr);
+		if (rval != DDI_SUCCESS)
+			goto error;
+	}
+
+	rval = nvlist_add_nvlist(nvl, "table", sub_nvl);
+	if (rval != DDI_SUCCESS)
+		goto error;
+	nvlist_free(sub_nvl);
+
+	*ret_nvl = nvl;
+	return (DDI_SUCCESS);
+
+error:
+	if (sub_nvl)
+		nvlist_free(sub_nvl);
+	ASSERT(nvl);
+	nvlist_free(nvl);
+	*ret_nvl = NULL;
+	return (DDI_FAILURE);
+}
+
+static void
+pci_cache_free_list(nvf_handle_t hdl)
+{
+	list_t		*listp;
+	pua_node_t	*pua;
+
+	ASSERT(RW_WRITE_HELD(nvf_lock(hdl)));
+
+	listp = nvf_list(hdl);
+	for (pua = list_head(listp); pua != NULL;
+	    pua = list_next(listp, pua)) {
+		list_remove(listp, pua);
+		kmem_free(pua, sizeof (pua_node_t));
+	}
+}
+
+
+static int
+pci_unitaddr_cache_valid(void)
+{
+
+	/* read only, no need for rw lock */
+	return (pua_cache_valid);
+}
+
+
+static int
+pci_bus_unitaddr(int index)
+{
+	pua_node_t	*pua;
+	list_t		*listp;
+	int		addr;
+
+	rw_enter(nvf_lock(puafd_handle), RW_READER);
+
+	addr = -1;	/* default return if no match */
+	listp = nvf_list(puafd_handle);
+	for (pua = list_head(listp); pua != NULL;
+	    pua = list_next(listp, pua)) {
+		if (pua->pua_index == index) {
+			addr = pua->pua_addr;
+			break;
+		}
+	}
+
+	rw_exit(nvf_lock(puafd_handle));
+	return (addr);
+}
+
+static void
+pci_unitaddr_cache_create(void)
+{
+	int		i, index;
+	pua_node_t	*node;
+	list_t		*listp;
+
+	rw_enter(nvf_lock(puafd_handle), RW_WRITER);
+
+	index = 0;
+	listp = nvf_list(puafd_handle);
+	for (i = 0; i <= pci_bios_nbus; i++) {
+		/* skip non-root (peer) PCI busses */
+		if ((pci_bus_res[i].par_bus != (uchar_t)-1) ||
+		    (pci_bus_res[i].dip == NULL))
+			continue;
+		node = kmem_zalloc(sizeof (pua_node_t), KM_SLEEP);
+		node->pua_index = index++;
+		node->pua_addr = pci_bus_res[i].root_addr;
+		list_insert_tail(listp, node);
+	}
+
+	(void) nvf_mark_dirty(puafd_handle);
+	rw_exit(nvf_lock(puafd_handle));
+	nvf_wake_daemon();
+}
+
+
+/*
  * Enumerate all PCI devices
  */
 void
-pci_setup_tree()
+pci_setup_tree(void)
 {
 	uint_t i, root_bus_addr = 0;
 
@@ -978,9 +1263,42 @@
 	int bus;
 
 	/*
-	 * Excise phantom roots if possible
+	 * Scan ACPI namespace for _BBN objects, make sure that
+	 * childless root-bridges appear in devinfo tree
+	 */
+	pci_scan_bbn();
+	pci_unitaddr_cache_init();
+
+	/*
+	 * Fix-up unit-address assignments if cache is available
 	 */
-	pci_renumber_root_busses();
+	if (pci_unitaddr_cache_valid()) {
+		int pci_regs[] = {0, 0, 0};
+		int	new_addr;
+		int	index = 0;
+
+		for (bus = 0; bus <= pci_bios_nbus; bus++) {
+			/* skip non-root (peer) PCI busses */
+			if ((pci_bus_res[bus].par_bus != (uchar_t)-1) ||
+			    (pci_bus_res[bus].dip == NULL))
+				continue;
+
+			new_addr = pci_bus_unitaddr(index);
+			if (pci_bus_res[bus].root_addr != new_addr) {
+				/* update reg property for node */
+				pci_regs[0] = pci_bus_res[bus].root_addr =
+				    new_addr;
+				(void) ndi_prop_update_int_array(
+				    DDI_DEV_T_NONE, pci_bus_res[bus].dip,
+				    "reg", (int *)pci_regs, 3);
+			}
+			index++;
+		}
+	} else {
+		/* perform legacy processing */
+		pci_renumber_root_busses();
+		pci_unitaddr_cache_create();
+	}
 
 	/*
 	 * Do root-bus resource discovery
--- a/usr/src/uts/intel/io/pci/pci_resource.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/io/pci/pci_resource.c	Mon Sep 21 11:26:40 2009 -0400
@@ -340,6 +340,12 @@
 		break;
 
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
+	/*
+	 * We comment out this block because we currently cannot deal with
+	 * PCI 64-bit addresses. Will revisit this when we add PCI 64-bit MMIO
+	 * support.
+	 */
+#if 0
 		if (rp->Data.Address64.AddressLength == 0)
 			break;
 		acpi_cb_cnt++;
@@ -347,9 +353,11 @@
 		    rp->Data.Address64.Info.TypeSpecific, bus),
 		    rp->Data.Address64.Minimum,
 		    rp->Data.Address64.AddressLength);
+#endif
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+#if 0	/* Will revisit this when we add PCI 64-bit MMIO support */
 		if (rp->Data.ExtAddress64.AddressLength == 0)
 			break;
 		acpi_cb_cnt++;
@@ -357,6 +365,7 @@
 		    rp->Data.ExtAddress64.Info.TypeSpecific, bus),
 		    rp->Data.ExtAddress64.Minimum,
 		    rp->Data.ExtAddress64.AddressLength);
+#endif
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
--- a/usr/src/uts/intel/os/driver_aliases	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/os/driver_aliases	Mon Sep 21 11:26:40 2009 -0400
@@ -47,6 +47,7 @@
 intel_nb5000 "pci8086,4003"
 intel_nb5000 "pci8086,65c0"
 intel_nhm "pci8086,3423"
+intel_nhm "pci8086,372a"
 xpv "pci5853,1.1"
 amd_iommu "pci1022,11ff"
 amd_iommu "pci1002,5a23"
--- a/usr/src/uts/intel/sys/Makefile	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/sys/Makefile	Mon Sep 21 11:26:40 2009 -0400
@@ -31,7 +31,6 @@
 #	from being built, so these headers are not exported (installed).
 
 HDRS	=			\
-	amd_iommu.h		\
 	archsystm.h		\
 	asm_linkage.h		\
 	bootconf.h		\
--- a/usr/src/uts/intel/sys/amd_iommu.h	Mon Sep 21 11:25:09 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef	_SYS_AMD_IOMMU_H
-#define	_SYS_AMD_IOMMU_H
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-#include <sys/sunddi.h>
-#include <sys/iommulib.h>
-
-#ifdef _KERNEL
-
-typedef struct amd_iommu_state {
-	int	aioms_instance;			/* instance */
-	dev_info_t *aioms_devi;			/* dip */
-	struct amd_iommu *aioms_iommu_start;	/* start of list of IOMMUs */
-	struct amd_iommu *aioms_iommu_end;	/* end of list of IOMMUs */
-	int aioms_nunits;			/* # of IOMMUs in function */
-} amd_iommu_state_t;
-
-int amd_iommu_setup(dev_info_t *dip, amd_iommu_state_t *statep);
-int amd_iommu_teardown(dev_info_t *dip, amd_iommu_state_t *statep);
-int amd_iommu_lookup_src_bdf(uint16_t bdf, uint16_t *src_bdfp);
-
-#endif	/* _KERNEL */
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif	/* _SYS_AMD_IOMMU_H */
--- a/usr/src/uts/intel/sys/mc_intel.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/sys/mc_intel.h	Mon Sep 21 11:26:40 2009 -0400
@@ -223,6 +223,23 @@
 #define	INTEL_QP_U2	0x34028086
 #define	INTEL_QP_U3	0x34048086
 #define	INTEL_QP_U4	0x34078086
+#define	INTEL_QP_JF	0x37208086
+#define	INTEL_QP_JF0	0x37008086
+#define	INTEL_QP_JF1	0x37018086
+#define	INTEL_QP_JF2	0x37028086
+#define	INTEL_QP_JF3	0x37038086
+#define	INTEL_QP_JF4	0x37048086
+#define	INTEL_QP_JF5	0x37058086
+#define	INTEL_QP_JF6	0x37068086
+#define	INTEL_QP_JF7	0x37078086
+#define	INTEL_QP_JF8	0x37088086
+#define	INTEL_QP_JF9	0x37098086
+#define	INTEL_QP_JFa	0x370a8086
+#define	INTEL_QP_JFb	0x370b8086
+#define	INTEL_QP_JFc	0x370c8086
+#define	INTEL_QP_JFd	0x370d8086
+#define	INTEL_QP_JFe	0x370e8086
+#define	INTEL_QP_JFf	0x370f8086
 
 /* Intel QuickPath Bus Interconnect Errors */
 
--- a/usr/src/uts/intel/sys/x86_archext.h	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/intel/sys/x86_archext.h	Mon Sep 21 11:26:40 2009 -0400
@@ -550,6 +550,8 @@
 #define	X86_SOCKET_AM2R2	_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000200)
 #define	X86_SOCKET_AM3		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000400)
 #define	X86_SOCKET_G34		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x000800)
+#define	X86_SOCKET_ASB2		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x001000)
+#define	X86_SOCKET_C32		_X86_SOCKET_MKVAL(X86_VENDOR_AMD, 0x002000)
 
 #if !defined(_ASM)
 
--- a/usr/src/uts/sun4u/io/pci/pci_pci.c	Mon Sep 21 11:25:09 2009 -0400
+++ b/usr/src/uts/sun4u/io/pci/pci_pci.c	Mon Sep 21 11:26:40 2009 -0400
@@ -1471,16 +1471,23 @@
 	base = PPB_16bit_IOADDR(io_base_lo);
 	limit = PPB_16bit_IOADDR(io_limit_lo);
 
+	/*
+	 * Check for 32-bit I/O support as per PCI-to-PCI Bridge Arch Spec
+	 */
 	if ((io_base_lo & 0xf) == PPB_32BIT_IO) {
 		base = PPB_LADDR(base, io_base_hi);
-	}
-	if ((io_limit_lo & 0xf) == PPB_32BIT_IO) {
 		limit = PPB_LADDR(limit, io_limit_hi);
 	}
 
-	if ((io_base_lo & PPB_32BIT_IO) && (io_limit_hi > 0)) {
-		base = PPB_LADDR(base, io_base_hi);
-		limit = PPB_LADDR(limit, io_limit_hi);
+	/*
+	 * Check if the bridge implements an I/O address range as per
+	 * PCI-to-PCI Bridge Arch Spec
+	 */
+	if ((io_base_lo != 0 || io_limit_lo != 0) && limit >= base) {
+		ranges[i].parent_low = ranges[i].child_low =
+		    base;
+		ranges[i].size_low = limit - base + PPB_IOGRAIN;
+		i++;
 	}
 
 	/*