changeset 2722:3846fae40902

6338238 DWARF parser can't handle anon struct/union 6415645 cpu_t hack isn't working as expected 6441836 ctffindmod.sh still talks about ia64 6458224 genassym could handle blank lines better
author johnlev
date Wed, 13 Sep 2006 11:29:23 -0700
parents a1fe0f523f8f
children 200331b43252
files usr/src/tools/ctf/cvt/Makefile.com usr/src/tools/ctf/cvt/ctftools.h usr/src/tools/ctf/cvt/dwarf.c usr/src/tools/ctf/cvt/fixup_tdescs.c usr/src/tools/ctf/cvt/iidesc.c usr/src/tools/ctf/cvt/output.c usr/src/tools/ctf/cvt/st_bugs.c usr/src/tools/ctf/cvt/st_parse.c usr/src/tools/ctf/cvt/stabs.c usr/src/tools/ctf/cvt/util.c usr/src/tools/ctf/scripts/ctffindmod.sh usr/src/tools/ctf/stabs/common/genassym.c usr/src/uts/common/disp/cpupart.c usr/src/uts/common/inet/squeue.c usr/src/uts/common/os/chip.c usr/src/uts/common/os/cpu.c usr/src/uts/common/sys/chip.h usr/src/uts/common/sys/cpupart.h usr/src/uts/common/sys/cpuvar.h usr/src/uts/common/sys/squeue_impl.h usr/src/uts/i86pc/os/mp_machdep.c usr/src/uts/sun4u/os/mach_startup.c usr/src/uts/sun4v/os/mach_startup.c
diffstat 23 files changed, 465 insertions(+), 397 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/tools/ctf/cvt/Makefile.com	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/Makefile.com	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -55,7 +54,7 @@
 	ctfconvert.c \
 	dwarf.c \
 	stabs.c \
-	st_bugs.c \
+	fixup_tdescs.c \
 	st_parse.c
 CVTOBJS=$(CVTSRCS:%.c=%.o)
 CVTLINTFILES = $(CVTSRCS:%.c=%.ln)
--- a/usr/src/tools/ctf/cvt/ctftools.h	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/ctftools.h	Wed Sep 13 11:29:23 2006 -0700
@@ -342,8 +342,9 @@
 
 typedef struct symit_data symit_data_t;
 
-/* bugs.c */
-void cvt_fixbugs(tdata_t *td);
+/* fixup_tdescs.c */
+void cvt_fixstabs(tdata_t *);
+void cvt_fixups(tdata_t *, size_t);
 
 /* ctf.c */
 caddr_t ctf_gen(iiburst_t *, size_t *, int);
@@ -352,6 +353,8 @@
 /* iidesc.c */
 iidesc_t *iidesc_new(char *);
 int iidesc_hash(int, void *);
+void iter_iidescs_by_name(tdata_t *, const char *,
+    int (*)(iidesc_t *, void *), void *);
 iidesc_t *iidesc_dup(iidesc_t *);
 iidesc_t *iidesc_dup_rename(iidesc_t *, char const *, char const *);
 void iidesc_add(hash_t *, iidesc_t *);
@@ -396,7 +399,7 @@
 void parse_finish(tdata_t *);
 int parse_stab(stab_t *, char *, iidesc_t **);
 tdesc_t *lookup(int);
-tdesc_t *lookupname(char *);
+tdesc_t *lookupname(const char *);
 void check_hash(void);
 void resolve_typed_bitfields(void);
 
@@ -427,8 +430,9 @@
 void tdata_label_newmax(tdata_t *, int);
 
 /* util.c */
-int streq(char *, char *);
+int streq(const char *, const char *);
 int findelfsecidx(Elf *, const char *, const char *);
+size_t elf_ptrsz(Elf *);
 char *mktmpname(const char *, const char *);
 void terminate(char *, ...);
 void aborterr(char *, ...);
--- a/usr/src/tools/ctf/cvt/dwarf.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/dwarf.c	Wed Sep 13 11:29:23 2006 -0700
@@ -955,10 +955,15 @@
 
 		ml = xcalloc(sizeof (mlist_t));
 
-		if ((ml->ml_name = die_name(dw, mem)) == NULL) {
-			terminate("die %llu: mem %llu: member has no name\n",
-			    off, memoff);
-		}
+		/*
+		 * This could be a GCC anon struct/union member, so we'll allow
+		 * an empty name, even though nothing can really handle them
+		 * properly.  Note that some versions of GCC miss out debug
+		 * info for anon structs, though recent versions are fixed (gcc
+		 * bug 11816).
+		 */
+		if ((ml->ml_name = die_name(dw, mem)) == NULL)
+			ml->ml_name = "";
 
 		ml->ml_type = die_lookup_pass1(dw, mem, DW_AT_type);
 
@@ -983,7 +988,7 @@
 #endif
 		}
 
-		debug(3, "die %llu: mem %llu: created %s (off %u sz %u)\n",
+		debug(3, "die %llu: mem %llu: created \"%s\" (off %u sz %u)\n",
 		    off, memoff, ml->ml_name, ml->ml_offset, ml->ml_size);
 
 		*mlastp = ml;
@@ -1105,9 +1110,10 @@
 
 	for (ml = tdp->t_members; ml != NULL; ml = ml->ml_next) {
 		if (ml->ml_size == 0) {
-			fprintf(stderr, "%s %d: failed to size member %s of "
-			    "type %s (%d)\n", typename, tdp->t_id, ml->ml_name,
-			    tdesc_name(ml->ml_type), ml->ml_type->t_id);
+			fprintf(stderr, "%s %d: failed to size member \"%s\" "
+			    "of type %s (%d)\n", typename, tdp->t_id,
+			    ml->ml_name, tdesc_name(ml->ml_type),
+			    ml->ml_type->t_id);
 		}
 	}
 
@@ -1771,27 +1777,6 @@
 	} while (dw->dw_nunres != 0);
 }
 
-static size_t
-elf_ptrsz(Elf *elf)
-{
-	GElf_Ehdr ehdr;
-
-	if (gelf_getehdr(elf, &ehdr) == NULL) {
-		terminate("failed to read ELF header: %s\n",
-		    elf_errmsg(-1));
-	}
-
-	if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
-		return (4);
-	else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
-		return (8);
-	else
-		terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]);
-
-	/*NOTREACHED*/
-	return (0);
-}
-
 /*ARGSUSED*/
 int
 dw_read(tdata_t *td, Elf *elf, const char *filename)
@@ -1871,6 +1856,8 @@
 
 	die_resolve(&dw);
 
+	cvt_fixups(td, dw.dw_ptrsz);
+
 	/* leak the dwarf_t */
 
 	return (0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/tools/ctf/cvt/fixup_tdescs.c	Wed Sep 13 11:29:23 2006 -0700
@@ -0,0 +1,277 @@
+/*
+ * 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 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * Workarounds for stabs generation bugs in the compiler and general needed
+ * fixups.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+
+#include "ctf_headers.h"
+#include "ctftools.h"
+#include "hash.h"
+#include "memory.h"
+
+/*
+ * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
+ * stabs.  Given a struct foo, and a corresponding typedef struct foo foo_t.
+ * In some cases, when faced with a pointer to a foo_t, the compiler will
+ * sometimes generate a stab that describes a pointer to a struct foo.
+ * Regardless of correctness, this breaks merges, as it occurs inconsistently
+ * by file.  The following two routines know how to recognize and repair foo_t *
+ * and foo_t ** bugs in a specific set of cases.  There is no general way to
+ * solve this problem without a fix to the compiler.  In general, cases should
+ * only be added to these routines to fix merging problems in genunix.
+ */
+static void
+fix_ptrptr_to_struct(tdata_t *td)
+{
+	char *strs[2] = { "as", "fdbuffer" };
+	char *mems[2] = { "a_objectdir", "fd_shadow" };
+	char *acts[2] = { "vnode", "page" };
+	char *tgts[2] = { "vnode_t", "page_t" };
+	tdesc_t *str;
+	tdesc_t *act, *tgt;
+	tdesc_t *p1, *p2;
+	mlist_t *ml;
+	int i;
+
+	for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
+		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
+			continue;
+
+		for (ml = str->t_members; ml; ml = ml->ml_next) {
+			if (streq(ml->ml_name, mems[i]))
+				break;
+		}
+		if (!ml)
+			continue;
+
+		if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
+		    ml->ml_type->t_tdesc->t_type != POINTER ||
+		    ml->ml_type->t_tdesc->t_name)
+			continue;
+
+		act = ml->ml_type->t_tdesc->t_tdesc;
+		if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
+			continue;
+
+		if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
+			continue;
+
+		/* We have an instance of the bug */
+		p2 = xcalloc(sizeof (*p2));
+		p2->t_type = POINTER;
+		p2->t_id = td->td_nextid++;
+		p2->t_tdesc = tgt;
+
+		p1 = xcalloc(sizeof (*p1));
+		p1->t_type = POINTER;
+		p1->t_id = td->td_nextid++;
+		p1->t_tdesc = p2;
+
+		ml->ml_type = p1;
+
+		debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
+		    strs[i], mems[i], acts[i]);
+	}
+}
+
+static void
+fix_ptr_to_struct(tdata_t *td)
+{
+	char *strs[2] = { "vmem", "id_space" };
+	char *mems[2] = { NULL, "is_vmem" };
+	tdesc_t *ptr = NULL;
+	tdesc_t *str, *vmt;
+	mlist_t *ml;
+	int i;
+
+	if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
+		return;
+
+	for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
+		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
+			continue;
+
+		for (ml = str->t_members; ml; ml = ml->ml_next) {
+			if (mems[i] && !streq(ml->ml_name, mems[i]))
+				continue;
+
+			if (ml->ml_type->t_type != POINTER ||
+			    ml->ml_type->t_name ||
+			    (ml->ml_type->t_tdesc->t_type != STRUCT &&
+			    ml->ml_type->t_tdesc->t_type != FORWARD) ||
+			    !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
+				continue;
+
+			debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
+			    strs[i], ml->ml_name);
+
+			if (!ptr) {
+				ptr = xcalloc(sizeof (*ptr));
+				ptr->t_type = POINTER;
+				ptr->t_id = td->td_nextid++;
+				ptr->t_tdesc = vmt;
+			}
+
+			ml->ml_type = ptr;
+		}
+	}
+}
+
+/*
+ * Fix stabs generation bugs.  These routines must be run before the
+ * post-conversion merge
+ */
+void
+cvt_fixstabs(tdata_t *td)
+{
+	fix_ptrptr_to_struct(td);
+	fix_ptr_to_struct(td);
+}
+
+struct match {
+	tdesc_t *m_ret;
+	const char *m_name;
+};
+
+static int
+matching_iidesc(iidesc_t *iidesc, struct match *match)
+{
+	if (!streq(iidesc->ii_name, match->m_name))
+		return (0);
+
+	if (iidesc->ii_type != II_TYPE && iidesc->ii_type != II_SOU)
+		return (0);
+
+	match->m_ret = iidesc->ii_dtype;
+	return (-1);
+}
+
+static tdesc_t *
+lookup_tdesc(tdata_t *td, const char *name)
+{
+	struct match match = { NULL, name };
+	iter_iidescs_by_name(td, name, (int (*)())matching_iidesc, &match);
+	return (match.m_ret);
+}
+
+/*
+ * The cpu structure grows, with the addition of a machcpu member, if
+ * _MACHDEP is defined.  This means that, for example, the cpu structure
+ * in unix is different from the cpu structure in genunix.  As one might
+ * expect, this causes merges to fail.  Since everyone indirectly contains
+ * a pointer to a CPU structure, the failed merges can cause massive amounts
+ * of duplication.  In the case of unix uniquifying against genunix, upwards
+ * of 50% of the structures were unmerged due to this problem.  We fix this
+ * by adding a cpu_m member.  If machcpu hasn't been defined in our module,
+ * we make a forward node for it.
+ */
+static void
+fix_small_cpu_struct(tdata_t *td, size_t ptrsize)
+{
+	tdesc_t *cput, *cpu;
+	tdesc_t *machcpu;
+	mlist_t *ml, *lml;
+	mlist_t *cpum;
+	int foundcpucyc = 0;
+
+	/*
+	 * We're going to take the circuitous route finding the cpu structure,
+	 * because we want to make sure that we find the right one.  It would
+	 * be nice if we could verify the header name too.  DWARF might not
+	 * have the cpu_t, so we let this pass.
+	 */
+	if ((cput = lookup_tdesc(td, "cpu_t")) != NULL) {
+		if (cput->t_type != TYPEDEF)
+			return;
+		cpu = cput->t_tdesc;
+	} else {
+		cpu = lookup_tdesc(td, "cpu");
+	}
+
+	if (cpu == NULL)
+		return;
+
+	if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT)
+		return;
+
+	for (ml = cpu->t_members, lml = NULL; ml;
+	    lml = ml, ml = ml->ml_next) {
+		if (strcmp(ml->ml_name, "cpu_cyclic") == 0)
+			foundcpucyc = 1;
+	}
+
+	if (foundcpucyc == 0 || lml == NULL ||
+	    strcmp(lml->ml_name, "cpu_m") == 0)
+		return;
+
+	/*
+	 * We need to derive the right offset for the fake cpu_m member.  To do
+	 * that, we require a special unused member to be the last member
+	 * before the 'cpu_m', that we encode knowledge of here.  ABI alignment
+	 * on all platforms is such that we only need to add a pointer-size
+	 * number of bits to get the right offset for cpu_m.  This would most
+	 * likely break if gcc's -malign-double were ever used, but that option
+	 * breaks the ABI anyway.
+	 */
+	if (!streq(lml->ml_name, "cpu_m_pad") &&
+	    getenv("CTFCONVERT_PERMISSIVE") == NULL) {
+		terminate("last cpu_t member before cpu_m is %s; "
+		    "it must be cpu_m_pad.\n", lml->ml_name);
+	}
+
+	if ((machcpu = lookup_tdesc(td, "machcpu")) == NULL) {
+		machcpu = xcalloc(sizeof (*machcpu));
+		machcpu->t_name = xstrdup("machcpu");
+		machcpu->t_id = td->td_nextid++;
+		machcpu->t_type = FORWARD;
+	} else if (machcpu->t_type != STRUCT) {
+		return;
+	}
+
+	debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
+	    (machcpu->t_type == FORWARD ? "forward" : "struct"));
+
+	cpum = xmalloc(sizeof (*cpum));
+	cpum->ml_offset = lml->ml_offset + (ptrsize * NBBY);
+	cpum->ml_size = 0;
+	cpum->ml_name = xstrdup("cpu_m");
+	cpum->ml_type = machcpu;
+	cpum->ml_next = NULL;
+
+	lml->ml_next = cpum;
+}
+
+void
+cvt_fixups(tdata_t *td, size_t ptrsize)
+{
+	fix_small_cpu_struct(td, ptrsize);
+}
--- a/usr/src/tools/ctf/cvt/iidesc.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/iidesc.c	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -107,6 +106,16 @@
 	hash_add(hash, new);
 }
 
+void
+iter_iidescs_by_name(tdata_t *td, const char *name,
+    int (*func)(iidesc_t *, void *), void *data)
+{
+	iidesc_t tmpdesc;
+	bzero(&tmpdesc, sizeof (iidesc_t));
+	tmpdesc.ii_name = (char *)name;
+	(void) hash_match(td->td_iihash, &tmpdesc, (int (*)())func, data);
+}
+
 iidesc_t *
 iidesc_dup(iidesc_t *src)
 {
--- a/usr/src/tools/ctf/cvt/output.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/output.c	Wed Sep 13 11:29:23 2006 -0700
@@ -190,13 +190,11 @@
 }
 
 static iidesc_t *
-find_iidesc(hash_t *hash, iidesc_match_t *match)
+find_iidesc(tdata_t *td, iidesc_match_t *match)
 {
-	iidesc_t tmpdesc;
 	match->iim_ret = NULL;
-	bzero(&tmpdesc, sizeof (iidesc_t));
-	tmpdesc.ii_name = match->iim_name;
-	(void) hash_match(hash, &tmpdesc, (int (*)())matching_iidesc, match);
+	iter_iidescs_by_name(td, match->iim_name,
+	    (int (*)())matching_iidesc, match);
 	return (match->iim_ret);
 }
 
@@ -390,7 +388,7 @@
 		if (ignore_symbol(&sym, match.iim_name))
 			continue;
 
-		iidesc = find_iidesc(td->td_iihash, &match);
+		iidesc = find_iidesc(td, &match);
 
 		if (iidesc != NULL) {
 			tolist[*curr] = iidesc;
@@ -412,7 +410,7 @@
 		debug(3, "Weak symbol %s resolved to %s\n", match.iim_name,
 		    smatch.iim_name);
 
-		iidesc = find_iidesc(td->td_iihash, &smatch);
+		iidesc = find_iidesc(td, &smatch);
 
 		if (iidesc != NULL) {
 			tolist[*curr] = copy_from_strong(td, &sym,
--- a/usr/src/tools/ctf/cvt/st_bugs.c	Wed Sep 13 09:42:23 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * 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.
- *
- * 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 2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * Workarounds for stabs generation bugs in the compiler
- */
-
-#include <stdio.h>
-#include <strings.h>
-
-#include "ctf_headers.h"
-#include "ctftools.h"
-#include "hash.h"
-#include "memory.h"
-
-/*
- * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
- * stabs.  Given a struct foo, and a corresponding typedef struct foo foo_t.
- * In some cases, when faced with a pointer to a foo_t, the compiler will
- * sometimes generate a stab that describes a pointer to a struct foo.
- * Regardless of correctness, this breaks merges, as it occurs inconsistently
- * by file.  The following two routines know how to recognize and repair foo_t *
- * and foo_t ** bugs in a specific set of cases.  There is no general way to
- * solve this problem without a fix to the compiler.  In general, cases should
- * only be added to these routines to fix merging problems in genunix.
- */
-static void
-fix_ptrptr_to_struct(tdata_t *td)
-{
-	char *strs[2] = { "as", "fdbuffer" };
-	char *mems[2] = { "a_objectdir", "fd_shadow" };
-	char *acts[2] = { "vnode", "page" };
-	char *tgts[2] = { "vnode_t", "page_t" };
-	tdesc_t *str;
-	tdesc_t *act, *tgt;
-	tdesc_t *p1, *p2;
-	mlist_t *ml;
-	int i;
-
-	for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
-		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
-			continue;
-
-		for (ml = str->t_members; ml; ml = ml->ml_next) {
-			if (streq(ml->ml_name, mems[i]))
-				break;
-		}
-		if (!ml)
-			continue;
-
-		if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
-		    ml->ml_type->t_tdesc->t_type != POINTER ||
-		    ml->ml_type->t_tdesc->t_name)
-			continue;
-
-		act = ml->ml_type->t_tdesc->t_tdesc;
-		if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
-			continue;
-
-		if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
-			continue;
-
-		/* We have an instance of the bug */
-		p2 = xcalloc(sizeof (*p2));
-		p2->t_type = POINTER;
-		p2->t_id = td->td_nextid++;
-		p2->t_tdesc = tgt;
-
-		p1 = xcalloc(sizeof (*p1));
-		p1->t_type = POINTER;
-		p1->t_id = td->td_nextid++;
-		p1->t_tdesc = p2;
-
-		ml->ml_type = p1;
-
-		debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
-		    strs[i], mems[i], acts[i]);
-	}
-}
-
-static void
-fix_ptr_to_struct(tdata_t *td)
-{
-	char *strs[2] = { "vmem", "id_space" };
-	char *mems[2] = { NULL, "is_vmem" };
-	tdesc_t *ptr = NULL;
-	tdesc_t *str, *vmt;
-	mlist_t *ml;
-	int i;
-
-	if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
-		return;
-
-	for (i = 0; i < sizeof (strs) / sizeof (strs[0]); i++) {
-		if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
-			continue;
-
-		for (ml = str->t_members; ml; ml = ml->ml_next) {
-			if (mems[i] && !streq(ml->ml_name, mems[i]))
-				continue;
-
-			if (ml->ml_type->t_type != POINTER ||
-			    ml->ml_type->t_name ||
-			    (ml->ml_type->t_tdesc->t_type != STRUCT &&
-			    ml->ml_type->t_tdesc->t_type != FORWARD) ||
-			    !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
-				continue;
-
-			debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
-			    strs[i], ml->ml_name);
-
-			if (!ptr) {
-				ptr = xcalloc(sizeof (*ptr));
-				ptr->t_type = POINTER;
-				ptr->t_id = td->td_nextid++;
-				ptr->t_tdesc = vmt;
-			}
-
-			ml->ml_type = ptr;
-		}
-	}
-}
-
-/*
- * The cpu structure grows, with the addition of a machcpu member, if
- * _MACHDEP is defined.  This means that, for example, the cpu structure
- * in unix is different from the cpu structure in genunix.  As one might
- * expect, this causes merges to fail.  Since everyone indirectly contains
- * a pointer to a CPU structure, the failed merges can cause massive amounts
- * of duplication.  In the case of unix uniquifying against genunix, upwards
- * of 50% of the structures were unmerged due to this problem.  We fix this
- * by adding a cpu_m member.  If machcpu hasn't been defined in our module,
- * we make a forward node for it.
- */
-static void
-fix_small_cpu_struct(tdata_t *td)
-{
-	tdesc_t *cput, *cpu;
-	tdesc_t *machcpu;
-	mlist_t *ml, *lml;
-	mlist_t *cpum;
-	int foundcpucyc = 0;
-	size_t lmlsz;
-
-	/*
-	 * We're going to take the circuitous route finding the cpu structure,
-	 * because we want to make sure that we find the right one.  It would
-	 * be nice if we could verify the header name too.
-	 */
-	if ((cput = lookupname("cpu_t")) == NULL || cput->t_type != TYPEDEF)
-		return;
-
-	cpu = cput->t_tdesc;
-	if (!streq(cpu->t_name, "cpu") || cpu->t_type != STRUCT)
-		return;
-
-	for (ml = cpu->t_members, lml = NULL; ml;
-	    lml = ml, ml = ml->ml_next) {
-		if (strcmp(ml->ml_name, "cpu_cyclic") == 0)
-			foundcpucyc = 1;
-	}
-
-	if (foundcpucyc == 0 || lml == NULL ||
-	    strcmp(lml->ml_name, "cpu_m") == 0)
-		return;
-
-	/*
-	 * We need to find out how big the last element is so we can compute the
-	 * offset of the new one.  If the last element has a size, we use it.
-	 * If it doesn't, it should be a pointer, which won't have a size.  In
-	 * that case, we look up the size of a long and use that as the size of
-	 * the pointer.
-	 */
-	if (lml->ml_type->t_size)
-		lmlsz = lml->ml_type->t_size * NBBY;
-	else {
-		tdesc_t *tdp = lookupname("long");
-		lmlsz = tdp->t_intr->intr_nbits;
-	}
-
-	if ((machcpu = lookupname("machcpu")) == NULL) {
-		machcpu = xcalloc(sizeof (*machcpu));
-		machcpu->t_name = xstrdup("machcpu");
-		machcpu->t_id = td->td_nextid++;
-		machcpu->t_type = FORWARD;
-
-	} else if (machcpu->t_type != STRUCT)
-		return;
-
-	debug(3, "Adding cpu_m machcpu %s to cpu struct\n",
-	    (machcpu->t_type == FORWARD ? "forward" : "struct"));
-
-	cpum = xmalloc(sizeof (*cpum));
-	cpum->ml_offset = lml->ml_offset + lmlsz;
-	cpum->ml_size = 0;
-	cpum->ml_name = xstrdup("cpu_m");
-	cpum->ml_type = machcpu;
-	cpum->ml_next = NULL;
-
-	lml->ml_next = cpum;
-}
-
-/*
- * Fix stabs generation bugs.  These routines must be run before the
- * post-conversion merge
- */
-void
-cvt_fixbugs(tdata_t *td)
-{
-	fix_ptrptr_to_struct(td);
-	fix_ptr_to_struct(td);
-	fix_small_cpu_struct(td);
-}
--- a/usr/src/tools/ctf/cvt/st_parse.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/st_parse.c	Wed Sep 13 11:29:23 2006 -0700
@@ -64,8 +64,7 @@
 
 static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp);
 static void enumdef(char *cp, tdesc_t **rtdp);
-static int compute_sum(char *w);
-tdesc_t *lookupname(char *name);
+static int compute_sum(const char *w);
 
 static char *number(char *cp, int *n);
 static char *name(char *cp, char **w);
@@ -1040,7 +1039,7 @@
 }
 
 tdesc_t *
-lookup_name(tdesc_t **hash, char *name)
+lookup_name(tdesc_t **hash, const char *name)
 {
 	int bucket = compute_sum(name);
 	tdesc_t *tdp, *ttdp = NULL;
@@ -1058,7 +1057,7 @@
 }
 
 tdesc_t *
-lookupname(char *name)
+lookupname(const char *name)
 {
 	return (lookup_name(name_table, name));
 }
@@ -1101,7 +1100,7 @@
 }
 
 static int
-compute_sum(char *w)
+compute_sum(const char *w)
 {
 	char c;
 	int sum;
--- a/usr/src/tools/ctf/cvt/stabs.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/stabs.c	Wed Sep 13 11:29:23 2006 -0700
@@ -374,7 +374,8 @@
 	resolve_typed_bitfields();
 	parse_finish(td);
 
-	cvt_fixbugs(td);
+	cvt_fixstabs(td);
+	cvt_fixups(td, elf_ptrsz(elf));
 
 	return (0);
 }
--- a/usr/src/tools/ctf/cvt/util.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/cvt/util.c	Wed Sep 13 11:29:23 2006 -0700
@@ -47,7 +47,7 @@
 
 /* returns 1 if s1 == s2, 0 otherwise */
 int
-streq(char *s1, char *s2)
+streq(const char *s1, const char *s2)
 {
 	if (s1 == NULL) {
 		if (s2 != NULL)
@@ -93,6 +93,27 @@
 	return (-1);
 }
 
+size_t
+elf_ptrsz(Elf *elf)
+{
+	GElf_Ehdr ehdr;
+
+	if (gelf_getehdr(elf, &ehdr) == NULL) {
+		terminate("failed to read ELF header: %s\n",
+		    elf_errmsg(-1));
+	}
+
+	if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+		return (4);
+	else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
+		return (8);
+	else
+		terminate("unknown ELF class %d\n", ehdr.e_ident[EI_CLASS]);
+
+	/*NOTREACHED*/
+	return (0);
+}
+
 /*PRINTFLIKE2*/
 static void
 whine(char *type, char *format, va_list ap)
--- a/usr/src/tools/ctf/scripts/ctffindmod.sh	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/scripts/ctffindmod.sh	Wed Sep 13 11:29:23 2006 -0700
@@ -3,9 +3,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.
@@ -23,7 +22,7 @@
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # Given a machine-optimal patch makeup table (see ctfcvtptbl), this program
@@ -161,7 +160,7 @@
 		if [ `uname -p` = "sparc" ] ; then
 			suffix=/sparcv9
 		else
-			suffix=/ia64
+			suffix=/amd64
 		fi
 	fi
 	echo "$space$garpath/$ku$suffix/genunix\c"
--- a/usr/src/tools/ctf/stabs/common/genassym.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/tools/ctf/stabs/common/genassym.c	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -301,15 +300,16 @@
 ga_process_line(char *line)
 {
 	static int curtype = -1;
-	int nblank = 0;
+	static int blanks = 0;
 
 	if (strlen(line) == 0) {
-		curtype = -1;
-		if (nblank++ == 1)
-			(void) fprintf(out, "\n");
+		blanks++;
 		return (1);
-	} else
-		nblank = 0;
+	} else if (blanks) {
+		if (!isspace(line[0]))
+			curtype = -1;
+		blanks = 0;
+	}
 
 	if (line[0] == '\\') {
 		if (line[1] == '#') {
--- a/usr/src/uts/common/disp/cpupart.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/disp/cpupart.c	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -69,6 +68,7 @@
 
 cpupart_t		*cp_list_head;
 cpupart_t		cp_default;
+struct mach_cpupart	cp_default_mach;
 static cpupartid_t	cp_id_next;
 uint_t			cp_numparts;
 uint_t			cp_numparts_nonempty;
@@ -100,7 +100,6 @@
 #define	PSTOCP(psid)	((cpupartid_t)((psid) == PS_NONE ? CP_DEFAULT : (psid)))
 #define	CPTOPS(cpid)	((psetid_t)((cpid) == CP_DEFAULT ? PS_NONE : (cpid)))
 
-
 /*
  * Find a CPU partition given a processor set ID.
  */
@@ -236,7 +235,7 @@
 	for (i = 0; i < S_LOADAVG_SZ; i++) {
 		cp_default.cp_loadavg.lg_loads[i] = 0;
 	}
-	CPUSET_ZERO(cp_default.cp_haltset);
+	CPUSET_ZERO(cp_default.cp_mach->mc_haltset);
 	DISP_LOCK_INIT(&cp_default.cp_kp_queue.disp_lock);
 	cp_id_next = CP_DEFAULT + 1;
 	cpupart_kstat_create(&cp_default);
@@ -416,8 +415,8 @@
 	newpp->cp_ncpus++;
 	newpp->cp_gen++;
 
-	ASSERT(CPUSET_ISNULL(newpp->cp_haltset));
-	ASSERT(CPUSET_ISNULL(oldpp->cp_haltset));
+	ASSERT(CPUSET_ISNULL(newpp->cp_mach->mc_haltset));
+	ASSERT(CPUSET_ISNULL(oldpp->cp_mach->mc_haltset));
 
 	/*
 	 * let the lgroup framework know cp has entered the partition
@@ -730,6 +729,7 @@
 	ASSERT(pool_lock_held());
 
 	pp = kmem_zalloc(sizeof (cpupart_t), KM_SLEEP);
+	pp->cp_mach = kmem_zalloc(sizeof (struct mach_cpupart), KM_SLEEP);
 	pp->cp_nlgrploads = lgrp_plat_max_lgrps();
 	pp->cp_lgrploads = kmem_zalloc(sizeof (lpl_t) * pp->cp_nlgrploads,
 	    KM_SLEEP);
@@ -739,6 +739,7 @@
 		mutex_exit(&cpu_lock);
 		kmem_free(pp->cp_lgrploads, sizeof (lpl_t) * pp->cp_nlgrploads);
 		pp->cp_lgrploads = NULL;
+		kmem_free(pp->cp_mach, sizeof (struct mach_cpupart));
 		kmem_free(pp, sizeof (cpupart_t));
 		return (ENOMEM);
 	}
@@ -755,7 +756,7 @@
 	pp->cp_kp_queue.disp_max_unbound_pri = -1;
 	pp->cp_kp_queue.disp_cpu = NULL;
 	pp->cp_gen = 0;
-	CPUSET_ZERO(pp->cp_haltset);
+	CPUSET_ZERO(pp->cp_mach->mc_haltset);
 	DISP_LOCK_INIT(&pp->cp_kp_queue.disp_lock);
 	*psid = CPTOPS(pp->cp_id);
 	disp_kp_alloc(&pp->cp_kp_queue, v.v_nglobpris);
@@ -763,7 +764,7 @@
 	for (i = 0; i < pp->cp_nlgrploads; i++) {
 		pp->cp_lgrploads[i].lpl_lgrpid = i;
 	}
-	CHIP_SET_ZERO(pp->cp_chipset);
+	CHIP_SET_ZERO(pp->cp_mach->mc_chipset);
 
 	/*
 	 * Pause all CPUs while changing the partition list, to make sure
@@ -858,8 +859,8 @@
 		}
 	}
 
-	ASSERT(CHIP_SET_ISNULL(pp->cp_chipset));
-	ASSERT(CPUSET_ISNULL(pp->cp_haltset));
+	ASSERT(CHIP_SET_ISNULL(pp->cp_mach->mc_chipset));
+	ASSERT(CPUSET_ISNULL(pp->cp_mach->mc_haltset));
 
 	/*
 	 * Reset the pointers in any offline processors so they won't
@@ -898,6 +899,7 @@
 	disp_kp_free(&pp->cp_kp_queue);
 	kmem_free(pp->cp_lgrploads, sizeof (lpl_t) * pp->cp_nlgrploads);
 	pp->cp_lgrploads = NULL;
+	kmem_free(pp->cp_mach, sizeof (struct mach_cpupart));
 	kmem_free(pp, sizeof (cpupart_t));
 	mutex_exit(&cpu_lock);
 
--- a/usr/src/uts/common/inet/squeue.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/inet/squeue.c	Wed Sep 13 11:29:23 2006 -0700
@@ -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.
@@ -158,18 +157,6 @@
  * squeue_workerwait_ms: When worker thread is interrupted because workerdrain
  *	expired, how much time to wait before waking worker thread again.
  *    Default: 10 ms.
- *
- * DEFINES:
- *
- * SQUEUE_DEBUG: If defined as 1, special code is compiled in which records
- *	additional information aiding debugging is recorded in squeue.
- *
- * SQUEUE_PROFILE: If defined as 1, special code is compiled in which collects
- *	various squeue statistics and exports them as kstats.
- *
- * Ideally we would like both SQUEUE_DEBUG and SQUEUE_PROFILE to be always set,
- * but it affects performance, so they are enabled on DEBUG kernels and disabled
- * on non-DEBUG by default.
  */
 
 #include <sys/types.h>
@@ -200,14 +187,6 @@
 #define	SQS_REENTER	0x0080	/* Re entered thread */
 #define	SQS_TMO_PROG	0x0100	/* Timeout is being set */
 
-#ifdef DEBUG
-#define	SQUEUE_DEBUG 1
-#define	SQUEUE_PROFILE 1
-#else
-#define	SQUEUE_DEBUG 0
-#define	SQUEUE_PROFILE 0
-#endif
-
 #include <sys/squeue_impl.h>
 
 static void squeue_fire(void *);
--- a/usr/src/uts/common/os/chip.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/os/chip.c	Wed Sep 13 11:29:23 2006 -0700
@@ -267,7 +267,7 @@
 		 */
 		if (chip_list == NULL) {
 			CHIP_SET_ZERO(chip_set);
-			CHIP_SET_ZERO(cp->cpu_part->cp_chipset);
+			CHIP_SET_ZERO(cp->cpu_part->cp_mach->mc_chipset);
 			chp->chip_nrunning++;	/* for t0 */
 		}
 
@@ -515,7 +515,7 @@
 		/*
 		 * Add the chip's seqid to the cpupart's chip set
 		 */
-		CHIP_SET_ADD(newpp->cp_chipset, chp->chip_seqid);
+		CHIP_SET_ADD(newpp->cp_mach->mc_chipset, chp->chip_seqid);
 	}
 
 	if (oldpp != NULL) {
@@ -534,7 +534,7 @@
 		 * No other cpu on the chip is in the old partition
 		 * so remove the chip's seqid from it's set
 		 */
-		CHIP_SET_REMOVE(oldpp->cp_chipset, chp->chip_seqid);
+		CHIP_SET_REMOVE(oldpp->cp_mach->mc_chipset, chp->chip_seqid);
 	}
 }
 
--- a/usr/src/uts/common/os/cpu.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/os/cpu.c	Wed Sep 13 11:29:23 2006 -0700
@@ -1633,6 +1633,7 @@
 	cp->cpu_seqid = 0;
 	CPUSET_ADD(cpu_seqid_inuse, 0);
 	cp->cpu_cache_offset = KMEM_CACHE_SIZE(cp->cpu_seqid);
+	cp_default.cp_mach = &cp_default_mach;
 	cp_default.cp_cpulist = cp;
 	cp_default.cp_ncpus = 1;
 	cp->cpu_next_part = cp;
--- a/usr/src/uts/common/sys/chip.h	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/sys/chip.h	Wed Sep 13 11:29:23 2006 -0700
@@ -170,7 +170,7 @@
 }
 
 #define	CHIP_IN_CPUPART(chp, cp)			\
-	(CHIP_SET_TEST((cp)->cp_chipset, (chp)->chip_seqid))
+	(CHIP_SET_TEST((cp)->cp_mach->mc_chipset, (chp)->chip_seqid))
 
 #endif	/* _MACHDEP */
 
--- a/usr/src/uts/common/sys/cpupart.h	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/sys/cpupart.h	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,6 +57,17 @@
 #define	CP_ALL		0		/* return all cpu partitions */
 #define	CP_NONEMPTY	1		/* return only non-empty ones */
 
+#if defined(_MACHDEP)
+struct mach_cpupart {
+	cpuset_t	mc_haltset;
+	chip_set_t	mc_chipset;
+};
+
+extern struct mach_cpupart cp_default_mach;
+#else
+struct mach_cpupart;
+#endif
+
 typedef struct cpupart {
 	disp_t		cp_kp_queue;	/* partition-wide kpreempt queue */
 	cpupartid_t	cp_id;		/* partition ID */
@@ -92,13 +102,8 @@
 	uint_t		cp_attr;	/* bitmask of attributes */
 	lgrp_gen_t	cp_gen;		/* generation number */
 	lgrp_id_t	cp_lgrp_hint;	/* last home lgroup chosen */
-#if defined(_MACHDEP)
-	/*
-	 * These guarded members must reside at the end of the structure
-	 */
-	cpuset_t	cp_haltset;	/* bitmask of halted cpus */
-	chip_set_t	cp_chipset;	/* set of chips spanned by this part */
-#endif	/* _MACHDEP */
+
+	struct mach_cpupart *cp_mach;   /* mach-specific */
 } cpupart_t;
 
 typedef struct cpupart_kstat {
--- a/usr/src/uts/common/sys/cpuvar.h	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/sys/cpuvar.h	Wed Sep 13 11:29:23 2006 -0700
@@ -82,6 +82,11 @@
 
 /*
  * Per-CPU data.
+ *
+ * Be careful adding new members: if they are not the same in all modules (e.g.
+ * change size depending on a #define), CTF uniquification can fail to work
+ * properly.  Furthermore, this is transitive in that it applies recursively to
+ * all types pointed to by cpu_t.
  */
 typedef struct cpu {
 	processorid_t	cpu_id;			/* CPU number */
@@ -206,14 +211,16 @@
 
 	struct cpu_physid *cpu_physid;	/* physical associations */
 
+	/*
+	 * New members must be added /before/ this member, as the CTF tools
+	 * rely on this being the last field before cpu_m, so they can
+	 * correctly calculate the offset when synthetically adding the cpu_m
+	 * member in objects that do not have it.  This fixup is required for
+	 * uniquification to work correctly.
+	 */
+	uintptr_t	cpu_m_pad;
+
 #if (defined(_KERNEL) || defined(_KMEMUSER)) && defined(_MACHDEP)
-	/*
-	 * XXX - needs to be fixed. Structure size should not change.
-	 *	 probably needs to be a pointer to an opaque structure.
-	 * XXX - this is OK as long as cpu structs aren't in an array.
-	 *	 A user program will either read the first part,
-	 *	 which is machine-independent, or read the whole thing.
-	 */
 	struct machcpu	cpu_m;		/* per architecture info */
 #endif
 } cpu_t;
--- a/usr/src/uts/common/sys/squeue_impl.h	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/common/sys/squeue_impl.h	Wed Sep 13 11:29:23 2006 -0700
@@ -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 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -37,6 +36,25 @@
 
 #define	SQ_NAMELEN 31
 
+/*
+ * SQUEUE_DEBUG: If defined as 1, special code is compiled in which records
+ *      additional information aiding debugging is recorded in squeue.
+ *
+ * SQUEUE_PROFILE: If defined as 1, special code is compiled in which collects
+ *      various squeue statistics and exports them as kstats.
+ *
+ * Ideally we would like both SQUEUE_DEBUG and SQUEUE_PROFILE to be always set,
+ * but it affects performance, so they are enabled on DEBUG kernels and disabled
+ * on non-DEBUG by default.
+ */
+#ifdef DEBUG
+#define	SQUEUE_DEBUG 1
+#define	SQUEUE_PROFILE 1
+#else
+#define	SQUEUE_DEBUG 0
+#define	SQUEUE_PROFILE 0
+#endif
+
 typedef struct sqstat_s {
 	uint_t		sq_max_qlen;
 	uint_t		sq_npackets_worker;
--- a/usr/src/uts/i86pc/os/mp_machdep.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/i86pc/os/mp_machdep.c	Wed Sep 13 11:29:23 2006 -0700
@@ -247,7 +247,7 @@
 	 */
 	if (hset_update) {
 		cpup->cpu_disp_flags |= CPU_DISP_HALTED;
-		CPUSET_ATOMIC_ADD(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_ADD(cp->cp_mach->mc_haltset, cpun);
 	}
 
 	/*
@@ -259,7 +259,7 @@
 	if (disp_anywork()) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		return;
 	}
@@ -282,7 +282,7 @@
 	 */
 	cli();
 
-	if (hset_update && !CPU_IN_SET(cp->cp_haltset, cpun)) {
+	if (hset_update && !CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
 		sti();
 		return;
@@ -297,7 +297,7 @@
 	if (cpup->cpu_disp->disp_nrunnable != 0) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		sti();
 		return;
@@ -315,7 +315,7 @@
 	 */
 	if (hset_update) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 	}
 }
 
@@ -334,12 +334,12 @@
 	cpupart_t	*cp;
 
 	cp = cpu->cpu_part;
-	if (CPU_IN_SET(cp->cp_haltset, cpu->cpu_id)) {
+	if (CPU_IN_SET(cp->cp_mach->mc_haltset, cpu->cpu_id)) {
 		/*
 		 * Clear the halted bit for that CPU since it will be
 		 * poked in a moment.
 		 */
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpu->cpu_id);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpu->cpu_id);
 		/*
 		 * We may find the current CPU present in the halted cpuset
 		 * if we're in the context of an interrupt that occurred
@@ -376,12 +376,12 @@
 	 * In that case, look again.
 	 */
 	do {
-		CPUSET_FIND(cp->cp_haltset, cpu_found);
+		CPUSET_FIND(cp->cp_mach->mc_haltset, cpu_found);
 		if (cpu_found == CPUSET_NOTINSET)
 			return;
 
 		ASSERT(cpu_found >= 0 && cpu_found < NCPU);
-		CPUSET_ATOMIC_XDEL(cp->cp_haltset, cpu_found, result);
+		CPUSET_ATOMIC_XDEL(cp->cp_mach->mc_haltset, cpu_found, result);
 	} while (result < 0);
 
 	if (cpu_found != CPU->cpu_id)
--- a/usr/src/uts/sun4u/os/mach_startup.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/sun4u/os/mach_startup.c	Wed Sep 13 11:29:23 2006 -0700
@@ -240,7 +240,7 @@
 	if (hset_update) {
 		cpup->cpu_disp_flags |= CPU_DISP_HALTED;
 		membar_producer();
-		CPUSET_ATOMIC_ADD(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_ADD(cp->cp_mach->mc_haltset, cpun);
 	}
 
 	/*
@@ -252,7 +252,7 @@
 	if (disp_anywork()) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		return;
 	}
@@ -276,7 +276,7 @@
 	pstate = getpstate();
 	setpstate(pstate & ~PSTATE_IE);
 
-	if (hset_update && !CPU_IN_SET(cp->cp_haltset, cpun)) {
+	if (hset_update && !CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
 		setpstate(pstate);
 		return;
@@ -291,7 +291,7 @@
 	if (cpup->cpu_disp->disp_nrunnable != 0) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		setpstate(pstate);
 		return;
@@ -309,7 +309,7 @@
 	setpstate(pstate);
 	if (hset_update) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 	}
 }
 
@@ -329,12 +329,12 @@
 	cpupart_t	*cp;
 
 	cp = cpu->cpu_part;
-	if (CPU_IN_SET(cp->cp_haltset, cpu->cpu_id)) {
+	if (CPU_IN_SET(cp->cp_mach->mc_haltset, cpu->cpu_id)) {
 		/*
 		 * Clear the halted bit for that CPU since it will be
 		 * poked in a moment.
 		 */
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpu->cpu_id);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpu->cpu_id);
 		/*
 		 * We may find the current CPU present in the halted cpuset
 		 * if we're in the context of an interrupt that occurred
@@ -370,12 +370,12 @@
 	 * In that case, look again.
 	 */
 	do {
-		CPUSET_FIND(cp->cp_haltset, cpu_found);
+		CPUSET_FIND(cp->cp_mach->mc_haltset, cpu_found);
 		if (cpu_found == CPUSET_NOTINSET)
 			return;
 
 		ASSERT(cpu_found >= 0 && cpu_found < NCPU);
-		CPUSET_ATOMIC_XDEL(cp->cp_haltset, cpu_found, result);
+		CPUSET_ATOMIC_XDEL(cp->cp_mach->mc_haltset, cpu_found, result);
 	} while (result < 0);
 
 	if (cpu_found != CPU->cpu_id)
--- a/usr/src/uts/sun4v/os/mach_startup.c	Wed Sep 13 09:42:23 2006 -0700
+++ b/usr/src/uts/sun4v/os/mach_startup.c	Wed Sep 13 11:29:23 2006 -0700
@@ -112,7 +112,7 @@
 	if (hset_update) {
 		cpup->cpu_disp_flags |= CPU_DISP_HALTED;
 		membar_producer();
-		CPUSET_ATOMIC_ADD(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_ADD(cp->cp_mach->mc_haltset, cpun);
 	}
 
 	/*
@@ -124,7 +124,7 @@
 	if (disp_anywork()) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		return;
 	}
@@ -147,7 +147,7 @@
 	 */
 	s = disable_vec_intr();
 
-	if (hset_update && !CPU_IN_SET(cp->cp_haltset, cpun)) {
+	if (hset_update && !CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
 		enable_vec_intr(s);
 		return;
@@ -162,7 +162,7 @@
 	if (cpup->cpu_disp->disp_nrunnable != 0) {
 		if (hset_update) {
 			cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-			CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+			CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 		}
 		enable_vec_intr(s);
 		return;
@@ -179,7 +179,7 @@
 	enable_vec_intr(s);
 	if (hset_update) {
 		cpup->cpu_disp_flags &= ~CPU_DISP_HALTED;
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpun);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun);
 	}
 }
 
@@ -197,12 +197,12 @@
 	cpupart_t	*cp;
 
 	cp = cpu->cpu_part;
-	if (CPU_IN_SET(cp->cp_haltset, cpu->cpu_id)) {
+	if (CPU_IN_SET(cp->cp_mach->mc_haltset, cpu->cpu_id)) {
 		/*
 		 * Clear the halted bit for that CPU since it will be
 		 * poked in a moment.
 		 */
-		CPUSET_ATOMIC_DEL(cp->cp_haltset, cpu->cpu_id);
+		CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpu->cpu_id);
 		/*
 		 * We may find the current CPU present in the halted cpuset
 		 * if we're in the context of an interrupt that occurred
@@ -238,12 +238,12 @@
 	 * In that case, look again.
 	 */
 	do {
-		CPUSET_FIND(cp->cp_haltset, cpu_found);
+		CPUSET_FIND(cp->cp_mach->mc_haltset, cpu_found);
 		if (cpu_found == CPUSET_NOTINSET)
 			return;
 
 		ASSERT(cpu_found >= 0 && cpu_found < NCPU);
-		CPUSET_ATOMIC_XDEL(cp->cp_haltset, cpu_found, result);
+		CPUSET_ATOMIC_XDEL(cp->cp_mach->mc_haltset, cpu_found, result);
 	} while (result < 0);
 
 	if (cpu_found != CPU->cpu_id)