changeset 13905:b151bd260b71

3414 Need a new word of AT_SUN_HWCAP bits 3415 Add isainfo support for f16c and rdrand 3416 Need disassembler support for rdrand and f16c Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Robert Mustacchi <rm@joyent.com>
date Thu, 13 Dec 2012 11:29:00 -0800
parents dbedaaf7ebd8
children 1da8bb09d310
files usr/src/cmd/isainfo/isainfo.c usr/src/cmd/ptools/pargs/pargs.c usr/src/cmd/sgs/elfdump/common/corenote.c usr/src/cmd/sgs/libconv/common/corenote.c usr/src/cmd/sgs/libconv/common/corenote.msg usr/src/cmd/sgs/rtld/amd64/_setup.c usr/src/cmd/sgs/rtld/common/_rtld.h usr/src/cmd/sgs/rtld/common/setup.c usr/src/cmd/sgs/rtld/i386/_setup.c usr/src/cmd/sgs/rtld/sparc/_setup.c usr/src/cmd/sgs/rtld/sparcv9/_setup.c usr/src/common/dis/i386/dis_tables.c usr/src/common/elfcap/elfcap.c usr/src/common/elfcap/elfcap.h usr/src/lib/libc/port/gen/getisax.c usr/src/uts/common/exec/elf/elf.c usr/src/uts/common/io/cpuid_drv.c usr/src/uts/common/os/exec.c usr/src/uts/common/sys/auxv.h usr/src/uts/common/sys/auxv_386.h usr/src/uts/common/sys/cpuid_drv.h usr/src/uts/common/sys/user.h usr/src/uts/i86pc/os/cpuid.c usr/src/uts/i86pc/os/mp_startup.c usr/src/uts/intel/ia32/os/archdep.c usr/src/uts/intel/sys/x86_archext.h
diffstat 26 files changed, 328 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/isainfo/isainfo.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/isainfo/isainfo.c	Thu Dec 13 11:29:00 2012 -0800
@@ -24,7 +24,7 @@
  */
 
 /*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -147,21 +147,41 @@
 report_hwcap(int d, const char *isa)
 {
 	struct cpuid_get_hwcap __cgh, *cgh = &__cgh;
-	char buffer[1024];
+	char buffer[1024], cap2[1024];
 
 	cgh->cgh_archname = (char *)isa;
 	if (ioctl(d, CPUID_GET_HWCAP, cgh) != 0)
 		return;
 
-	(void) elfcap_hw1_to_str(ELFCAP_STYLE_LC, cgh->cgh_hwcap,
+	(void) elfcap_hw1_to_str(ELFCAP_STYLE_LC, cgh->cgh_hwcap[0],
 	    buffer, sizeof (buffer), ELFCAP_FMT_SNGSPACE, machtype(isa));
 
+	if (cgh->cgh_hwcap[1] != 0)
+		(void) elfcap_hw2_to_str(ELFCAP_STYLE_LC, cgh->cgh_hwcap[1],
+		    cap2, sizeof (cap2), ELFCAP_FMT_SNGSPACE, machtype(isa));
+	else
+		cap2[0] = '\0';
+
 	if (mode & EXTN_MODE) {
-		(void) printf(": %s\n", buffer);
+		(void) printf(":");
+		if (cgh->cgh_hwcap[1] != NULL)
+			(void) printf(" %s", cap2);
+		(void) printf(" %s", buffer);
+		(void) printf("\n");
 	} else {
 		char *p;
 		int linecnt = 0;
 
+		for (p = strtok(cap2, " "); p; p = strtok(NULL, " ")) {
+			if (linecnt + strlen(p) > 68) {
+				(void) printf("\n");
+				linecnt = 0;
+			}
+			if (linecnt == 0)
+				linecnt = printf("\t");
+			linecnt += printf("%s ", p);
+		}
+
 		for (p = strtok(buffer, " "); p; p = strtok(NULL, " ")) {
 			if (linecnt + strlen(p) > 68) {
 				(void) printf("\n");
@@ -171,6 +191,7 @@
 				linecnt = printf("\t");
 			linecnt += printf("%s ", p);
 		}
+
 		if (linecnt != 0)
 			(void) printf("\n");
 	}
--- a/usr/src/cmd/ptools/pargs/pargs.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/ptools/pargs/pargs.c	Thu Dec 13 11:29:00 2012 -0800
@@ -22,8 +22,9 @@
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * pargs examines and prints the arguments (argv), environment (environ),
@@ -707,6 +708,23 @@
 
 /*ARGSUSED*/
 static void
+at_hwcap2(long val, char *instr, size_t n, char *str)
+{
+#if defined(__sparc) || defined(__sparcv9)
+	(void) elfcap_hw2_to_str(ELFCAP_STYLE_UC, val, str, n,
+	    ELFCAP_FMT_PIPSPACE, EM_SPARC);
+
+#elif defined(__i386) || defined(__amd64)
+	(void) elfcap_hw2_to_str(ELFCAP_STYLE_UC, val, str, n,
+	    ELFCAP_FMT_PIPSPACE, EM_386);
+#else
+#error	"port me"
+#endif
+}
+
+
+/*ARGSUSED*/
+static void
 at_uid(long val, char *instr, size_t n, char *str)
 {
 	struct passwd *pw = getpwuid((uid_t)val);
@@ -784,6 +802,7 @@
 	{ AT_SUN_PLATFORM,	"AT_SUN_PLATFORM",	at_str	},
 	{ AT_SUN_EXECNAME,	"AT_SUN_EXECNAME",	at_str	},
 	{ AT_SUN_HWCAP,		"AT_SUN_HWCAP",		at_hwcap },
+	{ AT_SUN_HWCAP2,	"AT_SUN_HWCAP2",	at_hwcap2 },
 	{ AT_SUN_IFLUSH,	"AT_SUN_IFLUSH",	at_null	},
 	{ AT_SUN_CPU,		"AT_SUN_CPU",		at_null	},
 	{ AT_SUN_MMU,		"AT_SUN_MMU",		at_null	},
--- a/usr/src/cmd/sgs/elfdump/common/corenote.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/elfdump/common/corenote.c	Thu Dec 13 11:29:00 2012 -0800
@@ -432,6 +432,7 @@
 	const sl_auxv_layout_t	*layout = state->ns_arch->auxv;
 	union {
 		Conv_cap_val_hw1_buf_t		hw1;
+		Conv_cap_val_hw2_buf_t		hw2;
 		Conv_cnote_auxv_af_buf_t	auxv_af;
 		Conv_ehdr_flags_buf_t		ehdr_flags;
 		Conv_inv_buf_t			inv;
@@ -524,6 +525,28 @@
 				vstr = NULL;
 			num_fmt = SL_FMT_NUM_HEX;
 			break;
+		case AT_SUN_HWCAP2:
+			w = extract_as_word(state, &layout->a_val);
+			vstr = conv_cap_val_hw2(w, state->ns_mach,
+			    0, &conv_buf.hw2);
+			/*
+			 * conv_cap_val_hw2() produces output like:
+			 *
+			 *	0xfff [ flg1 flg2 0xff]
+			 *
+			 * where the first hex value is the complete value,
+			 * and the second is the leftover bits. We only
+			 * want the part in brackets, and failing that,
+			 * would rather fall back to formatting the full
+			 * value ourselves.
+			 */
+			while ((*vstr != '\0') && (*vstr != '['))
+				vstr++;
+			if (*vstr != '[')
+				vstr = NULL;
+			num_fmt = SL_FMT_NUM_HEX;
+			break;
+
 
 
 		case AT_SUN_AUXFLAGS:
--- a/usr/src/cmd/sgs/libconv/common/corenote.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c	Thu Dec 13 11:29:00 2012 -0800
@@ -102,19 +102,19 @@
 	static const conv_ds_msg_t ds_types_2000_2011 = {
 	    CONV_DS_MSG_INIT(2000, types_2000_2011) };
 
-	static const Msg	types_2014_2022[] = {
+	static const Msg	types_2014_2023[] = {
 		MSG_AUXV_AT_SUN_EXECNAME,	MSG_AUXV_AT_SUN_MMU,
 		MSG_AUXV_AT_SUN_LDDATA,		MSG_AUXV_AT_SUN_AUXFLAGS,
 		MSG_AUXV_AT_SUN_EMULATOR,	MSG_AUXV_AT_SUN_BRANDNAME,
 		MSG_AUXV_AT_SUN_BRAND_AUX1,	MSG_AUXV_AT_SUN_BRAND_AUX2,
-		MSG_AUXV_AT_SUN_BRAND_AUX3
+		MSG_AUXV_AT_SUN_BRAND_AUX3,	MSG_AUXV_AT_SUN_HWCAP2
 	};
-	static const conv_ds_msg_t ds_types_2014_2022 = {
-	    CONV_DS_MSG_INIT(2014, types_2014_2022) };
+	static const conv_ds_msg_t ds_types_2014_2023 = {
+	    CONV_DS_MSG_INIT(2014, types_2014_2023) };
 
 	static const conv_ds_t	*ds[] = {
 		CONV_DS_ADDR(ds_types_0_22), CONV_DS_ADDR(ds_types_2000_2011),
-		CONV_DS_ADDR(ds_types_2014_2022), NULL };
+		CONV_DS_ADDR(ds_types_2014_2023), NULL };
 
 	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, type, ds, fmt_flags,
 	    inv_buf));
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg	Thu Dec 13 11:29:00 2012 -0800
@@ -97,6 +97,7 @@
 @ MSG_AUXV_AT_SUN_BRAND_AUX1		"SUN_BRAND_AUX1"
 @ MSG_AUXV_AT_SUN_BRAND_AUX2		"SUN_BRAND_AUX2"
 @ MSG_AUXV_AT_SUN_BRAND_AUX3		"SUN_BRAND_AUX3"
+@ MSG_AUXV_AT_SUN_HWCAP2		"SUN_HWCAP2"
 
 
 @ MSG_CC_CONTENT_STACK		"STACK"
--- a/usr/src/cmd/sgs/rtld/amd64/_setup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/amd64/_setup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -23,6 +23,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * amd64 specific setup routine  -  relocate ld.so's symbols, setup its
@@ -55,7 +58,8 @@
 	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
 	int		_syspagsz = 0, fd = -1;
-	uint_t		_flags = 0, hwcap_1 = 0;
+	uint_t		_flags = 0;
+	uint_t		hwcap[2] = { 0, 0 };
 	Dyn		*dyn_ptr;
 	Phdr		*phdr = NULL;
 	Rt_map		*lmp;
@@ -144,7 +148,11 @@
 			break;
 		case AT_SUN_HWCAP:
 			/* hardware capabilities */
-			hwcap_1 = (uint_t)auxv->a_un.a_val;
+			hwcap[0] = (uint_t)auxv->a_un.a_val;
+			break;
+		case AT_SUN_HWCAP2:
+			/* hardware capabilities */
+			hwcap[1] = (uint_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
@@ -228,7 +236,7 @@
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
 	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
 	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
-	    hwcap_1)) == NULL) {
+	    hwcap)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
 
--- a/usr/src/cmd/sgs/rtld/common/_rtld.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/common/_rtld.h	Thu Dec 13 11:29:00 2012 -0800
@@ -25,6 +25,9 @@
  *
  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 #ifndef	__RTLD_H
 #define	__RTLD_H
 
@@ -786,7 +789,7 @@
 extern int		set_prot(Rt_map *, mmapobj_result_t *, int);
 extern Rt_map		*setup(char **, auxv_t *, Word, char *, int, char *,
 			    ulong_t, ulong_t, int fd, Phdr *, char *, char **,
-			    uid_t, uid_t, gid_t, gid_t, void *, int, uint_t);
+			    uid_t, uid_t, gid_t, gid_t, void *, int, uint_t *);
 extern const char	*stravl_insert(const char *, uint_t, size_t, int);
 extern void		spavl_insert(const char *);
 extern int		sfcap1_check(Syscapset *, Xword, Rej_desc *);
--- a/usr/src/cmd/sgs/rtld/common/setup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/common/setup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -27,6 +27,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * Run time linker common setup.
@@ -192,7 +195,7 @@
 setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
     char *_rtldname, ulong_t ld_base, ulong_t interp_base, int fd, Phdr *phdr,
     char *execname, char **argv, uid_t uid, uid_t euid, gid_t gid, gid_t egid,
-    void *aoutdyn, int auxflags, uint_t hwcap_1)
+    void *aoutdyn, int auxflags, uint_t *hwcap)
 {
 	Rt_map			*rlmp, *mlmp, *clmp, **tobj = NULL;
 	Ehdr			*ehdr;
@@ -405,7 +408,8 @@
 	 */
 	if (auxflags & AF_SUN_HWCAPVERIFY) {
 		rtld_flags2 |= RT_FL2_HWCAP;
-		org_scapset->sc_hw_1 = (Xword)hwcap_1;
+		org_scapset->sc_hw_1 = (Xword)hwcap[0];
+		org_scapset->sc_hw_2 = (Xword)hwcap[1];
 	}
 
 	/*
--- a/usr/src/cmd/sgs/rtld/i386/_setup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/i386/_setup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -28,6 +28,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * i386 specific setup routine  -  relocate ld.so's symbols, setup its
@@ -60,7 +63,8 @@
 	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
 	int		_syspagsz = 0, fd = -1;
-	uint_t		_flags = 0, hwcap_1 = 0;
+	uint_t		_flags = 0;
+	uint_t		hwcap[2] = { 0, 0 };
 	Dyn		*dyn_ptr;
 	Phdr		*phdr = NULL;
 	Rt_map		*lmp;
@@ -149,7 +153,11 @@
 			break;
 		case AT_SUN_HWCAP:
 			/* hardware capabilities */
-			hwcap_1 = (uint_t)auxv->a_un.a_val;
+			hwcap[0] = (uint_t)auxv->a_un.a_val;
+			break;
+		case AT_SUN_HWCAP2:
+			/* hardware capabilities */
+			hwcap[1] = (uint_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
@@ -228,7 +236,7 @@
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
 	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
 	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
-	    hwcap_1)) == NULL) {
+	    hwcap)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
 
--- a/usr/src/cmd/sgs/rtld/sparc/_setup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/sparc/_setup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -28,6 +28,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * SPARC specific setup routine  -  relocate ld.so's symbols, setup its
@@ -63,7 +66,8 @@
 	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
 	int		_syspagsz = 0, fd = -1;
-	uint_t		_flags = 0, hwcap_1 = 0;
+	uint_t		_flags = 0;
+	uint_t		hwcap[2] = { 0, 0 };
 	Dyn		*dyn_ptr;
 	Phdr		*phdr = NULL;
 	Rt_map		*lmp;
@@ -160,7 +164,11 @@
 			break;
 		case AT_SUN_HWCAP:
 			/* hardware capabilities */
-			hwcap_1 = (uint_t)auxv->a_un.a_val;
+			hwcap[0] = (uint_t)auxv->a_un.a_val;
+			break;
+		case AT_SUN_HWCAP2:
+			/* hardware capabilities */
+			hwcap[1] = (uint_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
@@ -233,10 +241,10 @@
 	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
 	    _execname, _argv, uid, euid, gid, egid,
 #ifdef	A_OUT
-	    aoutdyn, auxflags, hwcap_1)) == NULL) {
+	    aoutdyn, auxflags, hwcap)) == NULL) {
 #else
 	    /* CSTYLED */
-	    NULL, auxflags, hwcap_1)) == NULL) {
+	    NULL, auxflags, hwcap)) == NULL) {
 #endif	/* A_OUT */
 		rtldexit(&lml_main, 1);
 	}
--- a/usr/src/cmd/sgs/rtld/sparcv9/_setup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/cmd/sgs/rtld/sparcv9/_setup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -28,6 +28,9 @@
  *	Copyright (c) 1988 AT&T
  *	  All Rights Reserved
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 /*
  * SPARCV9-specific setup routine  -  relocate ld.so's symbols, setup its
@@ -60,7 +63,8 @@
 	ulong_t		strtab, soname, interp_base = 0;
 	char		*_rt_name, **_envp, **_argv;
 	int		_syspagsz = 0, fd = -1;
-	uint_t		_flags = 0, hwcap_1 = 0;
+	uint_t		_flags = 0;
+	uint_t		hwcap[2] = { 0, 0 };
 	Dyn		*dyn_ptr;
 	Phdr		*phdr = NULL;
 	Rt_map		*lmp;
@@ -149,7 +153,11 @@
 			break;
 		case AT_SUN_HWCAP:
 			/* hardware capabilities */
-			hwcap_1 = (uint_t)auxv->a_un.a_val;
+			hwcap[0] = (uint_t)auxv->a_un.a_val;
+			break;
+		case AT_SUN_HWCAP2:
+			/* hardware capabilities */
+			hwcap[1] = (uint_t)auxv->a_un.a_val;
 			break;
 		case AT_SUN_EMULATOR:
 			/* name of emulation library, if any */
@@ -220,7 +228,7 @@
 	if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
 	    _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
 	    _execname, _argv, uid, euid, gid, egid, NULL, auxflags,
-	    hwcap_1)) == NULL) {
+	    hwcap)) == NULL) {
 		rtldexit(&lml_main, 1);
 	}
 
--- a/usr/src/common/dis/i386/dis_tables.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/common/dis/i386/dis_tables.c	Thu Dec 13 11:29:00 2012 -0800
@@ -32,7 +32,6 @@
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
 
-
 #include	"dis_tables.h"
 
 /* BEGIN CSTYLED */
@@ -541,6 +540,16 @@
 };
 
 /*
+ * 	Decode table for 0x0FC7 opcode (group 9) mode 3
+ */
+
+const instable_t dis_op0FC7m3[8] = {
+
+/*  [0]  */	INVALID,		INVALID,	INVALID,		INVALID,
+/*  [4]  */	INVALID,		INVALID,	TNS("rdrand",MG9),	INVALID,
+};
+
+/*
  * 	Decode table for 0x0FC7 opcode with 0x66 prefix
  */
 
@@ -1215,7 +1224,7 @@
 /*  [08]  */	TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16),
 /*  [0C]  */	TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8),	TNSZ("vtestpd",VEX_RRI,16),
 
-/*  [10]  */	INVALID,		INVALID,		INVALID,		INVALID,
+/*  [10]  */	INVALID,		INVALID,		INVALID,		TNSZ("vcvtph2ps",VEX_MX,16),
 /*  [14]  */	INVALID,		INVALID,		INVALID,		TNSZ("vptest",VEX_RRI,16),
 /*  [18]  */	TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID,
 /*  [1C]  */	TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID,
@@ -1381,7 +1390,7 @@
 /*  [10]  */	INVALID,		INVALID,		INVALID,		INVALID,
 /*  [14]  */	TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16),
 /*  [18]  */	TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID,		INVALID,
-/*  [1C]  */	INVALID,		INVALID,		INVALID,		INVALID,
+/*  [1C]  */	INVALID,		TNSZ("vcvtps2ph",VEX_RX,16),		INVALID,		INVALID,
 
 /*  [20]  */	TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID,
 /*  [24]  */	INVALID,		INVALID,		INVALID,		INVALID,
@@ -3084,6 +3093,14 @@
 		 * to the SIMD business described above, but with a different
 		 * addressing mode (and an indirect table), so we deal with it
 		 * separately (if similarly).
+		 *
+		 * Intel further complicated this with the release of Ivy Bridge
+		 * where they overloaded these instructions based on the ModR/M
+		 * bytes. The VMX instructions have a mode of 0 since they are
+		 * memory instructions but rdrand instructions have a mode of
+		 * 0b11 (REG_ONLY) because they only operate on registers. While
+		 * there are different prefix formats, for now it is sufficient
+		 * to use a single different table.
 		 */
 
 		/*
@@ -3096,6 +3113,15 @@
 		    sizeof (instable_t);
 
 		/*
+		 * If we have a mode of 0b11 then we have to rewrite this.
+		 */
+		dtrace_get_modrm(x, &mode, &reg, &r_m);
+		if (mode == REG_ONLY) {
+			dp = (instable_t *)&dis_op0FC7m3[off];
+			break;
+		}
+
+		/*
 		 * Rewrite if this instruction used one of the magic prefixes.
 		 */
 		if (rep_prefix) {
@@ -4438,7 +4464,8 @@
 			dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1);
 			dtrace_get_operand(x, mode, r_m, wbit, 0);
 		} else if ((dp == &dis_opAVXF30F[0xE6]) ||
-		    (dp == &dis_opAVX0F[0x5][0xA])) {
+		    (dp == &dis_opAVX0F[0x5][0xA]) ||
+		    (dp == &dis_opAVX660F38[0x13])) {
 			/* vcvtdq2pd <xmm>, <ymm> */
 			/* or vcvtps2pd <xmm>, <ymm> */
 			dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
@@ -4523,7 +4550,9 @@
 
 	case VEX_RX:
 		/* ModR/M.rm := op(ModR/M.reg) */
-		if (dp == &dis_opAVX660F3A[0x19]) {	/* vextractf128 */
+		/* vextractf128 || vcvtps2ph */
+		if (dp == &dis_opAVX660F3A[0x19] ||
+		    dp == &dis_opAVX660F3A[0x1d]) {
 			x->d86_numopnds = 3;
 
 			dtrace_get_modrm(x, &mode, &reg, &r_m);
--- a/usr/src/common/elfcap/elfcap.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/common/elfcap/elfcap.c	Thu Dec 13 11:29:00 2012 -0800
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 /* LINTLIBRARY */
@@ -307,6 +307,17 @@
 	}
 };
 
+static const elfcap_desc_t hw2_386[ELFCAP_NUM_HW2_386] = {
+	{						/* 0x00000001 */
+		AV_386_2_F16C, STRDESC("AV_386_2_F16C"),
+		STRDESC("F16C"), STRDESC("f16c"),
+	},
+	{						/* 0x00000002 */
+		AV_386_2_RDRAND, STRDESC("AV_386_2_RDRAND"),
+		STRDESC("RDRAND"), STRDESC("rdrand"),
+	}
+};
+
 /*
  * Concatenate a token to the string buffer.  This can be a capabilities token
  * or a separator token.
@@ -419,11 +430,9 @@
 }
 
 /*
- * Expand a CA_SUNW_HW_2 value.  Presently, there are no values, this routine
- * is simply a place holder for future development.
+ * Expand a CA_SUNW_HW_2 value.
  */
 elfcap_err_t
-/* ARGSUSED0 */
 elfcap_hw2_to_str(elfcap_style_t style, elfcap_mask_t val, char *str,
     size_t len, elfcap_fmt_t fmt, ushort_t mach)
 {
@@ -434,6 +443,10 @@
 	if ((fmt < 0) || (fmt >= FORMAT_NELTS))
 		return (ELFCAP_ERR_INVFMT);
 
+	if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
+		return (expand(style, val, &hw2_386[0], ELFCAP_NUM_HW2_386,
+		    str, len, fmt));
+
 	return (expand(style, val, NULL, 0, str, len, fmt));
 }
 
@@ -532,9 +545,11 @@
 	return (0);
 }
 elfcap_mask_t
-/* ARGSUSED0 */
 elfcap_hw2_from_str(elfcap_style_t style, const char *str, ushort_t mach)
 {
+	if ((mach == EM_386) || (mach == EM_IA_64) || (mach == EM_AMD64))
+		return (value(style, str, &hw2_386[0], ELFCAP_NUM_HW2_386));
+
 	return (0);
 }
 
--- a/usr/src/common/elfcap/elfcap.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/common/elfcap/elfcap.h	Thu Dec 13 11:29:00 2012 -0800
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 #ifndef _ELFCAP_DOT_H
@@ -115,6 +115,7 @@
 #define	ELFCAP_NUM_SF1			3
 #define	ELFCAP_NUM_HW1_SPARC		17
 #define	ELFCAP_NUM_HW1_386		32
+#define	ELFCAP_NUM_HW2_386		2
 
 
 /*
--- a/usr/src/lib/libc/port/gen/getisax.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/lib/libc/port/gen/getisax.c	Thu Dec 13 11:29:00 2012 -0800
@@ -23,8 +23,9 @@
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #pragma weak _getisax = getisax
 
@@ -35,11 +36,8 @@
 extern long ___getauxval(int type);
 
 /*
- * Return the 'hwcap' vector of bits in the AT_SUN_HWCAP aux vector entry.
- *
- * At this time, the worst-case implementation only uses 13 bits, but for
- * future-proofing, we allow the interface to describe an arbitrary length
- * array of 32-bit words.
+ * Return the 'hwcap' vector of bits in the AT_SUN_HWCAP and AT_SUN_HWCAP2 aux
+ * vector entries. Therefore there are two words of bits here.
  *
  * As a convenience, the routine returns the maximum number of array alements
  * that may contain non-zero values.
@@ -49,15 +47,21 @@
 {
 	int i;
 	static uint32_t auxv_hwcap;
+	static uint32_t auxv_hwcap_2;
 
-	if (auxv_hwcap == 0)
+	if (auxv_hwcap == 0) {
 		auxv_hwcap = (uint32_t)___getauxval(AT_SUN_HWCAP);
+		auxv_hwcap_2 = (uint32_t)___getauxval(AT_SUN_HWCAP2);
+	}
 
 	if (n > 0) {
 		if (n >= 1)
 			array[0] = auxv_hwcap;
-		for (i = 1; i < n; i++)
+		if (n >= 2)
+			array[1] = auxv_hwcap_2;
+		for (i = 2; i < n; i++)
 			array[i] = 0;
 	}
-	return (auxv_hwcap == 0 ? 0 : 1);
+
+	return (auxv_hwcap == 0 ? 0 : n >= 2 ? 2 : 1);
 }
--- a/usr/src/uts/common/exec/elf/elf.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/exec/elf/elf.c	Thu Dec 13 11:29:00 2012 -0800
@@ -25,6 +25,9 @@
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -415,11 +418,12 @@
 		 *	AT_PAGESZ
 		 *	AT_SUN_LDSECURE
 		 *	AT_SUN_HWCAP
+		 *	AT_SUN_HWCAP2
 		 *	AT_SUN_PLATFORM
 		 *	AT_SUN_EXECNAME
 		 *	AT_NULL
 		 *
-		 * total == 8
+		 * total == 9
 		 */
 		if (hasdy && hasu) {
 			/*
@@ -434,7 +438,7 @@
 			 *
 			 * total = 5
 			 */
-			args->auxsize = (8 + 5) * sizeof (aux_entry_t);
+			args->auxsize = (9 + 5) * sizeof (aux_entry_t);
 		} else if (hasdy) {
 			/*
 			 * Has PT_INTERP but no PT_PHDR
@@ -444,9 +448,9 @@
 			 *
 			 * total = 2
 			 */
-			args->auxsize = (8 + 2) * sizeof (aux_entry_t);
+			args->auxsize = (9 + 2) * sizeof (aux_entry_t);
 		} else {
-			args->auxsize = 8 * sizeof (aux_entry_t);
+			args->auxsize = 9 * sizeof (aux_entry_t);
 		}
 	} else {
 		args->auxsize = 0;
@@ -759,12 +763,16 @@
 		 * (Potentially different between 32-bit and 64-bit ABIs)
 		 */
 #if defined(_LP64)
-		if (args->to_model == DATAMODEL_NATIVE)
+		if (args->to_model == DATAMODEL_NATIVE) {
 			ADDAUX(aux, AT_SUN_HWCAP, auxv_hwcap)
-		else
+			ADDAUX(aux, AT_SUN_HWCAP2, auxv_hwcap_2)
+		} else {
 			ADDAUX(aux, AT_SUN_HWCAP, auxv_hwcap32)
+			ADDAUX(aux, AT_SUN_HWCAP2, auxv_hwcap32_2)
+		}
 #else
 		ADDAUX(aux, AT_SUN_HWCAP, auxv_hwcap)
+		ADDAUX(aux, AT_SUN_HWCAP2, auxv_hwcap_2)
 #endif
 		if (branded) {
 			/*
--- a/usr/src/uts/common/io/cpuid_drv.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/io/cpuid_drv.c	Thu Dec 13 11:29:00 2012 -0800
@@ -21,6 +21,9 @@
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 
 #include <sys/types.h>
@@ -162,14 +165,18 @@
 			return (EFAULT);
 		areq[sizeof (areq) - 1] = '\0';
 
-		if (strcmp(areq, architecture) == 0)
-			STRUCT_FSET(h, cgh_hwcap, auxv_hwcap);
+		if (strcmp(areq, architecture) == 0) {
+			STRUCT_FSET(h, cgh_hwcap[0], auxv_hwcap);
+			STRUCT_FSET(h, cgh_hwcap[1], auxv_hwcap_2);
 #if defined(_SYSCALL32_IMPL)
-		else if (strcmp(areq, architecture_32) == 0)
-			STRUCT_FSET(h, cgh_hwcap, auxv_hwcap32);
+		} else if (strcmp(areq, architecture_32) == 0) {
+			STRUCT_FSET(h, cgh_hwcap[0], auxv_hwcap32);
+			STRUCT_FSET(h, cgh_hwcap[1], auxv_hwcap32_2);
 #endif
-		else
-			STRUCT_FSET(h, cgh_hwcap, 0);
+		} else {
+			STRUCT_FSET(h, cgh_hwcap[0], 0);
+			STRUCT_FSET(h, cgh_hwcap[1], 0);
+		}
 		if (ddi_copyout(STRUCT_BUF(h),
 		    (void *)arg, STRUCT_SIZE(h), mode))
 			return (EFAULT);
--- a/usr/src/uts/common/os/exec.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/os/exec.c	Thu Dec 13 11:29:00 2012 -0800
@@ -25,6 +25,9 @@
 
 /*	Copyright (c) 1988 AT&T	*/
 /*	  All Rights Reserved  	*/
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -87,8 +90,10 @@
 static int hold_execsw(struct execsw *);
 
 uint_t auxv_hwcap = 0;	/* auxv AT_SUN_HWCAP value; determined on the fly */
+uint_t auxv_hwcap_2 = 0;	/* AT_SUN_HWCAP2 */
 #if defined(_SYSCALL32_IMPL)
 uint_t auxv_hwcap32 = 0;	/* 32-bit version of auxv_hwcap */
+uint_t auxv_hwcap32_2 = 0;	/* 32-bit version of auxv_hwcap2 */
 #endif
 
 #define	PSUIDFLAGS		(SNOCD|SUGID)
--- a/usr/src/uts/common/sys/auxv.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/sys/auxv.h	Thu Dec 13 11:29:00 2012 -0800
@@ -26,12 +26,13 @@
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #ifndef	_SYS_AUXV_H
 #define	_SYS_AUXV_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2	*/
-
 #include <sys/types.h>
 
 #ifdef	__cplusplus
@@ -141,6 +142,7 @@
  * hardware capabilities that might be useful to library implementations.
  */
 #define	AT_SUN_HWCAP	2009
+#define	AT_SUN_HWCAP2	2023
 
 #if defined(_KERNEL)
 /*
@@ -148,8 +150,10 @@
  * non-native user apps.
  */
 extern uint_t auxv_hwcap;
+extern uint_t auxv_hwcap_2;
 #if defined(_SYSCALL32)
 extern uint_t auxv_hwcap32;
+extern uint_t auxv_hwcap32_2;
 #endif /* _SYSCALL32 */
 #else
 extern uint_t getisax(uint32_t *, uint_t);
@@ -186,6 +190,10 @@
 #define	AT_SUN_BRAND_AUX3	2022
 
 /*
+ * Note that 2023 is reserved for the AT_SUN_HWCAP2 word defined above.
+ */
+
+/*
  * The kernel is in a better position to determine whether a process needs to
  * ignore dangerous LD environment variables.  If set, this flags tells
  * ld.so.1 to run "secure" and ignore the the environment.
--- a/usr/src/uts/common/sys/auxv_386.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/sys/auxv_386.h	Thu Dec 13 11:29:00 2012 -0800
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011, Joyent, Inc. All rights reserved.
+ * Copyright 2012, Joyent, Inc. All rights reserved.
  */
 
 #ifndef	_SYS_AUXV_386_H
@@ -83,6 +83,13 @@
 	"\017sse3\015sse2\014sse\013fxsr\012amd3dx\011amd3d"		\
 	"\010amdmmx\07mmx\06cmov\05amdsysc\04sep\03cx8\02tsc\01fpu"
 
+#define	AV_386_2_F16C		0x00001	/* F16C half percision extensions */
+#define	AV_386_2_RDRAND		0x00002	/* RDRAND insn */
+
+#define	FMT_AV_386_2							\
+	"\020"								\
+	"\02rdrand\01f16c"
+
 #ifdef __cplusplus
 }
 #endif
--- a/usr/src/uts/common/sys/cpuid_drv.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/sys/cpuid_drv.h	Thu Dec 13 11:29:00 2012 -0800
@@ -23,12 +23,13 @@
  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #ifndef	_SYS_CPUID_DRV_H
 #define	_SYS_CPUID_DRV_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 
 #ifdef __cplusplus
@@ -66,7 +67,7 @@
 
 struct cpuid_get_hwcap {
 	char *cgh_archname;
-	uint_t cgh_hwcap;
+	uint_t cgh_hwcap[2];
 };
 
 #if defined(_SYSCALL32_IMPL)
@@ -75,7 +76,7 @@
 
 struct cpuid_get_hwcap32 {
 	caddr32_t cgh_archname;
-	uint32_t cgh_hwcap;
+	uint32_t cgh_hwcap[2];
 };
 
 #endif	/* _SYSCALL32_IMPL */
--- a/usr/src/uts/common/sys/user.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/common/sys/user.h	Thu Dec 13 11:29:00 2012 -0800
@@ -25,13 +25,14 @@
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved	*/
+/*
+ * Copyright (c) 2012 Joyent, Inc.  All rights reserved.
+ */
 
 
 #ifndef _SYS_USER_H
 #define	_SYS_USER_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/signal.h>
 
@@ -184,9 +185,9 @@
  * This value should not be changed in a patch.
  */
 #if defined(__sparc)
-#define	__KERN_NAUXV_IMPL 19
+#define	__KERN_NAUXV_IMPL 20
 #elif defined(__i386) || defined(__amd64)
-#define	__KERN_NAUXV_IMPL 21
+#define	__KERN_NAUXV_IMPL 22
 #endif
 
 struct execsw;
--- a/usr/src/uts/i86pc/os/cpuid.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/i86pc/os/cpuid.c	Thu Dec 13 11:29:00 2012 -0800
@@ -161,7 +161,9 @@
 	"avx",
 	"vmx",
 	"svm",
-	"topoext"
+	"topoext",
+	"f16c",
+	"rdrand"
 };
 
 boolean_t
@@ -1155,6 +1157,7 @@
 	if (xsave_force_disable) {
 		mask_ecx &= ~CPUID_INTC_ECX_XSAVE;
 		mask_ecx &= ~CPUID_INTC_ECX_AVX;
+		mask_ecx &= ~CPUID_INTC_ECX_F16C;
 	}
 
 	/*
@@ -1255,10 +1258,15 @@
 
 		if (cp->cp_ecx & CPUID_INTC_ECX_XSAVE) {
 			add_x86_feature(featureset, X86FSET_XSAVE);
+
 			/* We only test AVX when there is XSAVE */
 			if (cp->cp_ecx & CPUID_INTC_ECX_AVX) {
 				add_x86_feature(featureset,
 				    X86FSET_AVX);
+
+				if (cp->cp_ecx & CPUID_INTC_ECX_F16C)
+					add_x86_feature(featureset,
+					    X86FSET_F16C);
 			}
 		}
 	}
@@ -1294,6 +1302,9 @@
 		add_x86_feature(featureset, X86FSET_VMX);
 	}
 
+	if (cp->cp_ecx & CPUID_INTC_ECX_RDRAND)
+		add_x86_feature(featureset, X86FSET_RDRAND);
+
 	/*
 	 * Only need it first time, rest of the cpus would follow suit.
 	 * we only capture this for the bootcpu.
@@ -1897,6 +1908,7 @@
 				remove_x86_feature(x86_featureset, X86FSET_AVX);
 				CPI_FEATURES_ECX(cpi) &= ~CPUID_INTC_ECX_XSAVE;
 				CPI_FEATURES_ECX(cpi) &= ~CPUID_INTC_ECX_AVX;
+				CPI_FEATURES_ECX(cpi) &= ~CPUID_INTC_ECX_F16C;
 				xsave_force_disable = B_TRUE;
 			}
 		}
@@ -2518,11 +2530,11 @@
  * the hardware feature support and kernel support for those features into
  * what we're actually going to tell applications via the aux vector.
  */
-uint_t
-cpuid_pass4(cpu_t *cpu)
+void
+cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
 {
 	struct cpuid_info *cpi;
-	uint_t hwcap_flags = 0;
+	uint_t hwcap_flags = 0, hwcap_flags_2 = 0;
 
 	if (cpu == NULL)
 		cpu = CPU;
@@ -2569,6 +2581,8 @@
 			    CPUID_INTC_ECX_OSXSAVE);
 		if (!is_x86_feature(x86_featureset, X86FSET_AVX))
 			*ecx &= ~CPUID_INTC_ECX_AVX;
+		if (!is_x86_feature(x86_featureset, X86FSET_F16C))
+			*ecx &= ~CPUID_INTC_ECX_F16C;
 
 		/*
 		 * [no explicit support required beyond x87 fp context]
@@ -2604,8 +2618,11 @@
 		    (*ecx & CPUID_INTC_ECX_OSXSAVE)) {
 			hwcap_flags |= AV_386_XSAVE;
 
-			if (*ecx & CPUID_INTC_ECX_AVX)
+			if (*ecx & CPUID_INTC_ECX_AVX) {
 				hwcap_flags |= AV_386_AVX;
+				if (*ecx & CPUID_INTC_ECX_F16C)
+					hwcap_flags_2 |= AV_386_2_F16C;
+			}
 		}
 		if (*ecx & CPUID_INTC_ECX_VMX)
 			hwcap_flags |= AV_386_VMX;
@@ -2624,6 +2641,9 @@
 			hwcap_flags |= AV_386_CMOV;
 		if (*ecx & CPUID_INTC_ECX_CX16)
 			hwcap_flags |= AV_386_CX16;
+
+		if (*ecx & CPUID_INTC_ECX_RDRAND)
+			hwcap_flags_2 |= AV_386_2_RDRAND;
 	}
 
 	if (cpi->cpi_xmaxeax < 0x80000001)
@@ -2739,7 +2759,10 @@
 
 pass4_done:
 	cpi->cpi_pass = 4;
-	return (hwcap_flags);
+	if (hwcap_out != NULL) {
+		hwcap_out[0] = hwcap_flags;
+		hwcap_out[1] = hwcap_flags_2;
+	}
 }
 
 
--- a/usr/src/uts/i86pc/os/mp_startup.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/i86pc/os/mp_startup.c	Thu Dec 13 11:29:00 2012 -0800
@@ -26,6 +26,9 @@
  * Copyright (c) 2010, Intel Corporation.
  * All rights reserved.
  */
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/thread.h>
@@ -1737,7 +1740,7 @@
 
 	cpuid_pass2(cp);
 	cpuid_pass3(cp);
-	(void) cpuid_pass4(cp);
+	cpuid_pass4(cp, NULL);
 
 	/*
 	 * Correct cpu_idstr and cpu_brandstr on target CPU after
--- a/usr/src/uts/intel/ia32/os/archdep.c	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/intel/ia32/os/archdep.c	Thu Dec 13 11:29:00 2012 -0800
@@ -24,6 +24,9 @@
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
+/*
+ * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -922,10 +925,14 @@
 }
 
 uint_t auxv_hwcap_include = 0;	/* patch to enable unrecognized features */
+uint_t auxv_hwcap_include_2 = 0;	/* second word */
 uint_t auxv_hwcap_exclude = 0;	/* patch for broken cpus, debugging */
+uint_t auxv_hwcap_exclude_2 = 0;	/* second word */
 #if defined(_SYSCALL32_IMPL)
 uint_t auxv_hwcap32_include = 0;	/* ditto for 32-bit apps */
+uint_t auxv_hwcap32_include_2 = 0;	/* ditto for 32-bit apps */
 uint_t auxv_hwcap32_exclude = 0;	/* ditto for 32-bit apps */
+uint_t auxv_hwcap32_exclude_2 = 0;	/* ditto for 32-bit apps */
 #endif
 
 /*
@@ -939,10 +946,13 @@
 void
 bind_hwcap(void)
 {
-	uint_t cpu_hwcap_flags = cpuid_pass4(NULL);
+	uint_t cpu_hwcap_flags[2];
+	cpuid_pass4(NULL, cpu_hwcap_flags);
 
-	auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags) &
+	auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags[0]) &
 	    ~auxv_hwcap_exclude;
+	auxv_hwcap_2 = (auxv_hwcap_include_2 | cpu_hwcap_flags[1]) &
+	    ~auxv_hwcap_exclude_2;
 
 #if defined(__amd64)
 	/*
@@ -962,7 +972,8 @@
 	auxv_hwcap |= AV_386_AHF;
 #endif
 
-	if (auxv_hwcap_include || auxv_hwcap_exclude) {
+	if (auxv_hwcap_include || auxv_hwcap_exclude || auxv_hwcap_include_2 ||
+	    auxv_hwcap_exclude_2) {
 		/*
 		 * The below assignment is regrettably required to get lint
 		 * to accept the validity of our format string.  The format
@@ -977,13 +988,17 @@
 		 * and as soon as the format string is programmatic, it
 		 * knows enough to shut up.
 		 */
-		const char *fmt = "?user ABI extensions: %b\n";
+		char *fmt = "?user ABI extensions: %b\n";
 		cmn_err(CE_CONT, fmt, auxv_hwcap, FMT_AV_386);
+		fmt = "?user ABI extensions (word 2): %b\n";
+		cmn_err(CE_CONT, fmt, auxv_hwcap_2, FMT_AV_386_2);
 	}
 
 #if defined(_SYSCALL32_IMPL)
-	auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags) &
+	auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags[0]) &
 	    ~auxv_hwcap32_exclude;
+	auxv_hwcap32_2 = (auxv_hwcap32_include_2 | cpu_hwcap_flags[1]) &
+	    ~auxv_hwcap32_exclude_2;
 
 #if defined(__amd64)
 	/*
@@ -1001,12 +1016,15 @@
 	auxv_hwcap32 |= AV_386_AHF;
 #endif
 
-	if (auxv_hwcap32_include || auxv_hwcap32_exclude) {
+	if (auxv_hwcap32_include || auxv_hwcap32_exclude ||
+	    auxv_hwcap32_include_2 || auxv_hwcap32_exclude_2) {
 		/*
 		 * See the block comment in the cmn_err() of auxv_hwcap, above.
 		 */
-		const char *fmt = "?32-bit user ABI extensions: %b\n";
+		char *fmt = "?32-bit user ABI extensions: %b\n";
 		cmn_err(CE_CONT, fmt, auxv_hwcap32, FMT_AV_386);
+		fmt = "?32-bit user ABI extensions (word 2): %b\n";
+		cmn_err(CE_CONT, fmt, auxv_hwcap32_2, FMT_AV_386_2);
 	}
 #endif
 }
--- a/usr/src/uts/intel/sys/x86_archext.h	Thu Dec 13 11:25:45 2012 -0800
+++ b/usr/src/uts/intel/sys/x86_archext.h	Thu Dec 13 11:29:00 2012 -0800
@@ -27,7 +27,7 @@
  * All rights reserved.
  */
 /*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 #ifndef _SYS_X86_ARCHEXT_H
@@ -119,10 +119,12 @@
 #define	CPUID_INTC_ECX_XSAVE	0x04000000	/* XSAVE/XRESTOR insns */
 #define	CPUID_INTC_ECX_OSXSAVE	0x08000000	/* OS supports XSAVE insns */
 #define	CPUID_INTC_ECX_AVX	0x10000000	/* AVX supported */
+#define	CPUID_INTC_ECX_F16C	0x20000000	/* F16C supported */
+#define	CPUID_INTC_ECX_RDRAND	0x40000000	/* RDRAND supported */
 
 #define	FMT_CPUID_INTC_ECX					\
 	"\20"							\
-	"\35avx\34osxsav\33xsave"				\
+	"\37rdrand\36f16c\35avx\34osxsav\33xsave"		\
 	"\32aes"						\
 	"\30popcnt\27movbe\25sse4.2\24sse4.1\23dca"		\
 	"\20\17etprd\16cx16\13cid\12ssse3\11tm2"		\
@@ -371,6 +373,8 @@
 #define	X86FSET_VMX		35
 #define	X86FSET_SVM		36
 #define	X86FSET_TOPOEXT		37
+#define	X86FSET_F16C		38
+#define	X86FSET_RDRAND		39
 
 /*
  * flags to patch tsc_read routine.
@@ -588,13 +592,14 @@
 #define	XFEATURE_SSE		0x2
 #define	XFEATURE_AVX		0x4
 #define	XFEATURE_MAX		XFEATURE_AVX
-#define	XFEATURE_FP_ALL		(XFEATURE_LEGACY_FP|XFEATURE_SSE|XFEATURE_AVX)
+#define	XFEATURE_FP_ALL	\
+	(XFEATURE_LEGACY_FP|XFEATURE_SSE|XFEATURE_AVX)
 
 #if !defined(_ASM)
 
 #if defined(_KERNEL) || defined(_KMEMUSER)
 
-#define	NUM_X86_FEATURES	38
+#define	NUM_X86_FEATURES	40
 extern uchar_t x86_featureset[];
 
 extern void free_x86_featureset(void *featureset);
@@ -702,7 +707,7 @@
 extern void cpuid_pass1(struct cpu *, uchar_t *);
 extern void cpuid_pass2(struct cpu *);
 extern void cpuid_pass3(struct cpu *);
-extern uint_t cpuid_pass4(struct cpu *);
+extern void cpuid_pass4(struct cpu *, uint_t *);
 extern void cpuid_set_cpu_properties(void *, processorid_t,
     struct cpuid_info *);